Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Vazquez <blendergit@gmail.com>2020-03-09 18:27:24 +0300
committerAntonio Vazquez <blendergit@gmail.com>2020-03-09 18:27:24 +0300
commit29f3af95272590d26f610ae828b2eeee89c82a00 (patch)
treea696a58a2561c48f7ec6166e369e22081e0a64d8 /source/blender/draw/engines/overlay
parentdcb93126876879d969a30a7865700abd072066f8 (diff)
GPencil: Refactor of Draw Engine, Vertex Paint and all internal functions
This commit is a full refactor of the grease pencil modules including Draw Engine, Modifiers, VFX, depsgraph update, improvements in operators and conversion of Sculpt and Weight paint tools to real brushes. Also, a huge code cleanup has been done at all levels. Thanks to @fclem for his work and yo @pepeland and @mendio for the testing and help in the development. Differential Revision: https://developer.blender.org/D6293
Diffstat (limited to 'source/blender/draw/engines/overlay')
-rw-r--r--source/blender/draw/engines/overlay/overlay_engine.c24
-rw-r--r--source/blender/draw/engines/overlay/overlay_extra.c85
-rw-r--r--source/blender/draw/engines/overlay/overlay_gpencil.c391
-rw-r--r--source/blender/draw/engines/overlay/overlay_motion_path.c4
-rw-r--r--source/blender/draw/engines/overlay/overlay_outline.c158
-rw-r--r--source/blender/draw/engines/overlay/overlay_private.h19
-rw-r--r--source/blender/draw/engines/overlay/overlay_shader.c103
-rw-r--r--source/blender/draw/engines/overlay/overlay_wireframe.c6
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_gpencil_canvas_vert.glsl35
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_gpencil_guide_vert.glsl14
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_gpencil_vert.glsl103
-rw-r--r--source/blender/draw/engines/overlay/shaders/outline_prepass_frag.glsl38
-rw-r--r--source/blender/draw/engines/overlay/shaders/outline_prepass_vert.glsl14
-rw-r--r--source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl6
14 files changed, 902 insertions, 98 deletions
diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c
index a8d2c4c6cf0..cfa0fa9eb1a 100644
--- a/source/blender/draw/engines/overlay/overlay_engine.c
+++ b/source/blender/draw/engines/overlay/overlay_engine.c
@@ -25,6 +25,8 @@
#include "DRW_engine.h"
#include "DRW_render.h"
+#include "DEG_depsgraph_query.h"
+
#include "ED_view3d.h"
#include "BKE_object.h"
@@ -79,6 +81,7 @@ static void OVERLAY_engine_init(void *vedata)
pd->xray_enabled = XRAY_ACTIVE(v3d);
pd->xray_enabled_and_not_wire = pd->xray_enabled && v3d->shading.type > OB_WIRE;
pd->clear_in_front = (v3d->shading.type != OB_SOLID);
+ pd->cfra = DEG_get_ctime(draw_ctx->depsgraph);
OVERLAY_antialiasing_init(vedata);
@@ -133,11 +136,14 @@ static void OVERLAY_cache_init(void *vedata)
case CTX_MODE_SCULPT:
OVERLAY_sculpt_cache_init(vedata);
break;
- case CTX_MODE_OBJECT:
- case CTX_MODE_PAINT_GPENCIL:
case CTX_MODE_EDIT_GPENCIL:
+ case CTX_MODE_PAINT_GPENCIL:
case CTX_MODE_SCULPT_GPENCIL:
+ case CTX_MODE_VERTEX_GPENCIL:
case CTX_MODE_WEIGHT_GPENCIL:
+ OVERLAY_edit_gpencil_cache_init(vedata);
+ break;
+ case CTX_MODE_OBJECT:
break;
default:
BLI_assert(!"Draw mode invalid");
@@ -148,6 +154,7 @@ static void OVERLAY_cache_init(void *vedata)
OVERLAY_background_cache_init(vedata);
OVERLAY_extra_cache_init(vedata);
OVERLAY_facing_cache_init(vedata);
+ OVERLAY_gpencil_cache_init(vedata);
OVERLAY_grid_cache_init(vedata);
OVERLAY_image_cache_init(vedata);
OVERLAY_metaball_cache_init(vedata);
@@ -216,8 +223,9 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
const bool in_paint_mode = (ob == draw_ctx->obact) &&
(draw_ctx->object_mode & OB_MODE_ALL_PAINT);
const bool in_sculpt_mode = (ob == draw_ctx->obact) && (ob->sculpt != NULL);
- const bool has_surface = ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_MBALL, OB_FONT);
- const bool draw_surface = !((ob->dt < OB_WIRE) || (!renderable && (ob->dt != OB_WIRE)));
+ const bool has_surface = ELEM(
+ ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_MBALL, OB_FONT, OB_GPENCIL);
+ const bool draw_surface = (ob->dt >= OB_WIRE) && (renderable || (ob->dt == OB_WIRE));
const bool draw_facing = draw_surface && (pd->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION);
const bool draw_bones = (pd->overlay.flag & V3D_OVERLAY_HIDE_BONES) == 0;
const bool draw_wires = draw_surface && has_surface &&
@@ -429,6 +437,7 @@ static void OVERLAY_draw_scene(void *vedata)
OVERLAY_armature_draw(vedata);
OVERLAY_particle_draw(vedata);
OVERLAY_metaball_draw(vedata);
+ OVERLAY_gpencil_draw(vedata);
OVERLAY_extra_draw(vedata);
if (DRW_state_is_fbo()) {
@@ -491,6 +500,13 @@ static void OVERLAY_draw_scene(void *vedata)
case CTX_MODE_SCULPT:
OVERLAY_sculpt_draw(vedata);
break;
+ case CTX_MODE_EDIT_GPENCIL:
+ case CTX_MODE_PAINT_GPENCIL:
+ case CTX_MODE_SCULPT_GPENCIL:
+ case CTX_MODE_VERTEX_GPENCIL:
+ case CTX_MODE_WEIGHT_GPENCIL:
+ OVERLAY_edit_gpencil_draw(vedata);
+ break;
default:
break;
}
diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c
index b40e95d538c..49f266291da 100644
--- a/source/blender/draw/engines/overlay/overlay_extra.c
+++ b/source/blender/draw/engines/overlay/overlay_extra.c
@@ -38,7 +38,7 @@
#include "DNA_camera_types.h"
#include "DNA_constraint_types.h"
-#include "DNA_gpencil_types.h"
+#include "DNA_curve_types.h"
#include "DNA_lightprobe_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
@@ -1331,89 +1331,6 @@ static void OVERLAY_relationship_lines(OVERLAY_ExtraCallBuffers *cb,
/** \} */
/* -------------------------------------------------------------------- */
-/** \name GPencil.
- * \{ */
-
-static void OVERLAY_gpencil_color_names(Object *ob)
-{
- if (ob->mode != OB_MODE_EDIT_GPENCIL) {
- return;
- }
-
- bGPdata *gpd = (bGPdata *)ob->data;
- if (gpd == NULL) {
- return;
- }
-
- const DRWContextState *draw_ctx = DRW_context_state_get();
- ViewLayer *view_layer = draw_ctx->view_layer;
- int theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
- uchar color[4];
- /* Color Management: Exception here as texts are drawn in sRGB space directly. */
- UI_GetThemeColor3ubv(theme_id, color);
- color[3] = 255;
- struct DRWTextStore *dt = DRW_text_cache_ensure();
-
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (gpl->flag & GP_LAYER_HIDE) {
- continue;
- }
- bGPDframe *gpf = gpl->actframe;
- if (gpf == NULL) {
- continue;
- }
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- Material *ma = BKE_object_material_get(ob, gps->mat_nr + 1);
- if (ma == NULL) {
- continue;
- }
-
- MaterialGPencilStyle *gp_style = ma->gp_style;
- /* skip stroke if it doesn't have any valid data */
- if ((gps->points == NULL) || (gps->totpoints < 1) || (gp_style == NULL)) {
- continue;
- }
- /* check if the color is visible */
- if (gp_style->flag & GP_STYLE_COLOR_HIDE) {
- continue;
- }
-
- /* only if selected */
- if (gps->flag & GP_STROKE_SELECT) {
- float fpt[3];
- for (int i = 0; i < gps->totpoints; i++) {
- bGPDspoint *pt = &gps->points[i];
- if (pt->flag & GP_SPOINT_SELECT) {
- mul_v3_m4v3(fpt, ob->obmat, &pt->x);
- DRW_text_cache_add(dt,
- fpt,
- ma->id.name + 2,
- strlen(ma->id.name + 2),
- 10,
- 0,
- DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR,
- color);
- break;
- }
- }
- }
- }
- }
-}
-
-void OVERLAY_gpencil_cache_populate(OVERLAY_Data *UNUSED(vedata), Object *ob)
-{
- /* don't show object extras in set's */
- if ((ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI)) == 0) {
- if ((ob->dtx & OB_DRAWNAME) && DRW_state_show_text()) {
- OVERLAY_gpencil_color_names(ob);
- }
- }
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Volumetric / Smoke sim
* \{ */
diff --git a/source/blender/draw/engines/overlay/overlay_gpencil.c b/source/blender/draw/engines/overlay/overlay_gpencil.c
new file mode 100644
index 00000000000..c96c448c63b
--- /dev/null
+++ b/source/blender/draw/engines/overlay/overlay_gpencil.c
@@ -0,0 +1,391 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2020, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#include "DRW_render.h"
+
+#include "BKE_gpencil.h"
+
+#include "UI_resources.h"
+
+#include "DNA_gpencil_types.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "ED_view3d.h"
+
+#include "overlay_private.h"
+
+#include "draw_common.h"
+#include "draw_manager_text.h"
+
+void OVERLAY_edit_gpencil_cache_init(OVERLAY_Data *vedata)
+{
+ OVERLAY_PassList *psl = vedata->psl;
+ OVERLAY_PrivateData *pd = vedata->stl->pd;
+ struct GPUShader *sh;
+ DRWShadingGroup *grp;
+
+ /* Default: Display nothing. */
+ pd->edit_gpencil_points_grp = NULL;
+ pd->edit_gpencil_wires_grp = NULL;
+ psl->edit_gpencil_ps = NULL;
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+ Object *ob = draw_ctx->obact;
+ bGPdata *gpd = ob ? (bGPdata *)ob->data : NULL;
+ Scene *scene = draw_ctx->scene;
+ ToolSettings *ts = scene->toolsettings;
+
+ if (gpd == NULL || ob->type != OB_GPENCIL) {
+ return;
+ }
+
+ /* For sculpt show only if mask mode, and only points if not stroke mode. */
+ const bool use_sculpt_mask = (GPENCIL_SCULPT_MODE(gpd) &&
+ GPENCIL_ANY_SCULPT_MASK(ts->gpencil_selectmode_sculpt));
+ const bool show_sculpt_points = (GPENCIL_SCULPT_MODE(gpd) &&
+ (ts->gpencil_selectmode_sculpt &
+ (GP_SCULPT_MASK_SELECTMODE_POINT |
+ GP_SCULPT_MASK_SELECTMODE_SEGMENT)));
+
+ /* For vertex paint show only if mask mode, and only points if not stroke mode. */
+ bool use_vertex_mask = (GPENCIL_VERTEX_MODE(gpd) &&
+ GPENCIL_ANY_VERTEX_MASK(ts->gpencil_selectmode_vertex));
+ const bool show_vertex_points = (GPENCIL_VERTEX_MODE(gpd) &&
+ (ts->gpencil_selectmode_vertex &
+ (GP_VERTEX_MASK_SELECTMODE_POINT |
+ GP_VERTEX_MASK_SELECTMODE_SEGMENT)));
+
+ /* If Sculpt or Vertex mode and the mask is disabled, the select must be hidden. */
+ const bool hide_select = ((GPENCIL_SCULPT_MODE(gpd) && !use_sculpt_mask) ||
+ (GPENCIL_VERTEX_MODE(gpd) && !use_vertex_mask));
+
+ const bool do_multiedit = GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ const bool show_multi_edit_lines = (v3d->gp_flag & V3D_GP_SHOW_MULTIEDIT_LINES) != 0;
+
+ const bool show_lines = (v3d->gp_flag & V3D_GP_SHOW_EDIT_LINES) || show_multi_edit_lines;
+
+ const bool hide_lines = !GPENCIL_EDIT_MODE(gpd) && !GPENCIL_WEIGHT_MODE(gpd) &&
+ !use_sculpt_mask && !use_vertex_mask && !show_lines;
+
+ /* Special case when vertex paint and multiedit lines. */
+ if (do_multiedit && show_multi_edit_lines && GPENCIL_VERTEX_MODE(gpd)) {
+ use_vertex_mask = true;
+ }
+
+ const bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE);
+
+ /* Show Edit points if:
+ * Edit mode: Not in Stroke selection mode
+ * Sculpt mode: If use Mask and not Stroke mode
+ * Weight mode: Always
+ * Vertex mode: If use Mask and not Stroke mode
+ */
+ const bool show_points = show_sculpt_points || is_weight_paint || show_vertex_points ||
+ (GPENCIL_EDIT_MODE(gpd) &&
+ (ts->gpencil_selectmode_edit != GP_SELECTMODE_STROKE));
+
+ if ((!GPENCIL_VERTEX_MODE(gpd) && !GPENCIL_PAINT_MODE(gpd)) || use_vertex_mask) {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
+ DRW_STATE_BLEND_ALPHA;
+ DRW_PASS_CREATE(psl->edit_gpencil_ps, state | pd->clipping_state);
+
+ if (show_lines && !hide_lines) {
+ sh = OVERLAY_shader_edit_gpencil_wire();
+ pd->edit_gpencil_wires_grp = grp = DRW_shgroup_create(sh, psl->edit_gpencil_ps);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_bool_copy(grp, "doMultiframe", show_multi_edit_lines);
+ DRW_shgroup_uniform_bool_copy(grp, "doWeightColor", is_weight_paint);
+ DRW_shgroup_uniform_bool_copy(grp, "hideSelect", hide_select);
+ DRW_shgroup_uniform_float_copy(grp, "gpEditOpacity", v3d->vertex_opacity);
+ DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.weight_ramp);
+ }
+
+ if (show_points && !hide_select) {
+ sh = OVERLAY_shader_edit_gpencil_point();
+ pd->edit_gpencil_points_grp = grp = DRW_shgroup_create(sh, psl->edit_gpencil_ps);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_bool_copy(grp, "doMultiframe", do_multiedit);
+ DRW_shgroup_uniform_bool_copy(grp, "doWeightColor", is_weight_paint);
+ DRW_shgroup_uniform_float_copy(grp, "gpEditOpacity", v3d->vertex_opacity);
+ DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.weight_ramp);
+ }
+ }
+
+ /* control points for primitives and speed guide */
+ const bool is_cppoint = (gpd->runtime.tot_cp_points > 0);
+ const bool is_speed_guide = (ts->gp_sculpt.guide.use_guide &&
+ (draw_ctx->object_mode == OB_MODE_PAINT_GPENCIL));
+ const bool is_show_gizmo = (((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) &&
+ ((v3d->gizmo_flag & V3D_GIZMO_HIDE_TOOL) == 0));
+
+ if ((is_cppoint || is_speed_guide) && (is_show_gizmo)) {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA;
+ DRW_PASS_CREATE(psl->edit_gpencil_gizmos_ps, state);
+
+ sh = OVERLAY_shader_edit_gpencil_guide_point();
+ grp = DRW_shgroup_create(sh, psl->edit_gpencil_gizmos_ps);
+
+ if (gpd->runtime.cp_points != NULL) {
+ for (int i = 0; i < gpd->runtime.tot_cp_points; i++) {
+ bGPDcontrolpoint *cp = &gpd->runtime.cp_points[i];
+ grp = DRW_shgroup_create_sub(grp);
+ DRW_shgroup_uniform_vec3_copy(grp, "pPosition", &cp->x);
+ DRW_shgroup_uniform_float_copy(grp, "pSize", cp->size * 0.8f * G_draw.block.sizePixel);
+ DRW_shgroup_uniform_vec4_copy(grp, "pColor", cp->color);
+ DRW_shgroup_call_procedural_points(grp, NULL, 1);
+ }
+ }
+
+ if (ts->gp_sculpt.guide.use_guide) {
+ float color[4];
+ if (ts->gp_sculpt.guide.reference_point == GP_GUIDE_REF_CUSTOM) {
+ UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color);
+ DRW_shgroup_uniform_vec3_copy(grp, "pPosition", ts->gp_sculpt.guide.location);
+ }
+ else if (ts->gp_sculpt.guide.reference_point == GP_GUIDE_REF_OBJECT &&
+ ts->gp_sculpt.guide.reference_object != NULL) {
+ UI_GetThemeColor4fv(TH_GIZMO_SECONDARY, color);
+ DRW_shgroup_uniform_vec3_copy(grp, "pPosition", ts->gp_sculpt.guide.reference_object->loc);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_REDALERT, color);
+ DRW_shgroup_uniform_vec3_copy(grp, "pPosition", scene->cursor.location);
+ }
+ DRW_shgroup_uniform_vec4_copy(grp, "pColor", color);
+ DRW_shgroup_uniform_float_copy(grp, "pSize", 8.0f * G_draw.block.sizePixel);
+ DRW_shgroup_call_procedural_points(grp, NULL, 1);
+ }
+ }
+}
+
+void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata)
+{
+ OVERLAY_PassList *psl = vedata->psl;
+ struct GPUShader *sh;
+ DRWShadingGroup *grp;
+
+ /* Default: Display nothing. */
+ psl->gpencil_canvas_ps = NULL;
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+ Object *ob = draw_ctx->obact;
+ bGPdata *gpd = ob ? (bGPdata *)ob->data : NULL;
+ Scene *scene = draw_ctx->scene;
+ ToolSettings *ts = scene->toolsettings;
+ const View3DCursor *cursor = &scene->cursor;
+
+ if (gpd == NULL || ob->type != OB_GPENCIL) {
+ return;
+ }
+
+ const bool show_overlays = (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0;
+ const bool show_grid = (v3d->gp_flag & V3D_GP_SHOW_GRID) != 0;
+
+ if (show_grid && show_overlays) {
+ const char *grid_unit = NULL;
+ float mat[4][4];
+ float col_grid[4];
+ float size[2];
+
+ /* set color */
+ copy_v3_v3(col_grid, gpd->grid.color);
+ col_grid[3] = max_ff(v3d->overlay.gpencil_grid_opacity, 0.01f);
+
+ copy_m4_m4(mat, ob->obmat);
+
+ float viewinv[4][4];
+ /* Set the grid in the selected axis */
+ switch (ts->gp_sculpt.lock_axis) {
+ case GP_LOCKAXIS_X:
+ swap_v4_v4(mat[0], mat[2]);
+ break;
+ case GP_LOCKAXIS_Y:
+ swap_v4_v4(mat[1], mat[2]);
+ break;
+ case GP_LOCKAXIS_Z:
+ /* Default. */
+ break;
+ case GP_LOCKAXIS_CURSOR:
+ loc_eul_size_to_mat4(mat, cursor->location, cursor->rotation_euler, (float[3]){1, 1, 1});
+ break;
+ case GP_LOCKAXIS_VIEW:
+ /* view aligned */
+ DRW_view_viewmat_get(NULL, viewinv, true);
+ copy_v3_v3(mat[0], viewinv[0]);
+ copy_v3_v3(mat[1], viewinv[1]);
+ break;
+ }
+
+ translate_m4(mat, gpd->grid.offset[0], gpd->grid.offset[1], 0.0f);
+ mul_v2_v2fl(size, gpd->grid.scale, 2.0f * ED_scene_grid_scale(scene, &grid_unit));
+ rescale_m4(mat, (float[3]){size[0], size[1], 0.0f});
+
+ const int gridlines = (gpd->grid.lines <= 0) ? 1 : gpd->grid.lines;
+ int line_ct = gridlines * 4 + 2;
+
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA;
+ DRW_PASS_CREATE(psl->gpencil_canvas_ps, state);
+
+ sh = OVERLAY_shader_gpencil_canvas();
+ grp = DRW_shgroup_create(sh, psl->gpencil_canvas_ps);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_vec4_copy(grp, "color", col_grid);
+ DRW_shgroup_uniform_vec3_copy(grp, "xAxis", mat[0]);
+ DRW_shgroup_uniform_vec3_copy(grp, "yAxis", mat[1]);
+ DRW_shgroup_uniform_vec3_copy(grp, "origin", mat[3]);
+ DRW_shgroup_uniform_int_copy(grp, "halfLineCount", line_ct / 2);
+ DRW_shgroup_call_procedural_lines(grp, NULL, line_ct);
+ }
+}
+
+static void OVERLAY_edit_gpencil_cache_populate(OVERLAY_Data *vedata, Object *ob)
+{
+ OVERLAY_PrivateData *pd = vedata->stl->pd;
+ bGPdata *gpd = (bGPdata *)ob->data;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+
+ if (pd->edit_gpencil_wires_grp) {
+ DRWShadingGroup *grp = DRW_shgroup_create_sub(pd->edit_gpencil_wires_grp);
+ DRW_shgroup_uniform_vec4_copy(grp, "gpEditColor", gpd->line_color);
+
+ struct GPUBatch *geom = DRW_cache_gpencil_edit_lines_get(ob, pd->cfra);
+ DRW_shgroup_call_no_cull(pd->edit_gpencil_wires_grp, geom, ob);
+ }
+
+ if (pd->edit_gpencil_points_grp) {
+ const bool show_direction = (v3d->gp_flag & V3D_GP_SHOW_STROKE_DIRECTION) != 0;
+
+ DRWShadingGroup *grp = DRW_shgroup_create_sub(pd->edit_gpencil_points_grp);
+ DRW_shgroup_uniform_float_copy(grp, "doStrokeEndpoints", show_direction);
+
+ struct GPUBatch *geom = DRW_cache_gpencil_edit_points_get(ob, pd->cfra);
+ DRW_shgroup_call_no_cull(grp, geom, ob);
+ }
+}
+
+static void overlay_gpencil_draw_stroke_color_name(bGPDlayer *UNUSED(gpl),
+ bGPDframe *UNUSED(gpf),
+ bGPDstroke *gps,
+ void *thunk)
+{
+ Object *ob = (Object *)thunk;
+ Material *ma = BKE_object_material_get(ob, gps->mat_nr + 1);
+ if (ma == NULL) {
+ return;
+ }
+ MaterialGPencilStyle *gp_style = ma->gp_style;
+ /* skip stroke if it doesn't have any valid data */
+ if ((gps->points == NULL) || (gps->totpoints < 1) || (gp_style == NULL)) {
+ return;
+ }
+ /* check if the color is visible */
+ if (gp_style->flag & GP_MATERIAL_HIDE) {
+ return;
+ }
+ /* only if selected */
+ if (gps->flag & GP_STROKE_SELECT) {
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ /* Draw name at the first selected point. */
+ if (pt->flag & GP_SPOINT_SELECT) {
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+
+ int theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
+ uchar color[4];
+ UI_GetThemeColor4ubv(theme_id, color);
+
+ float fpt[3];
+ mul_v3_m4v3(fpt, ob->obmat, &pt->x);
+
+ struct DRWTextStore *dt = DRW_text_cache_ensure();
+ DRW_text_cache_add(dt,
+ fpt,
+ ma->id.name + 2,
+ strlen(ma->id.name + 2),
+ 10,
+ 0,
+ DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR,
+ color);
+ break;
+ }
+ }
+ }
+}
+
+static void OVERLAY_gpencil_color_names(Object *ob)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ int cfra = DEG_get_ctime(draw_ctx->depsgraph);
+
+ BKE_gpencil_visible_stroke_iter(
+ ob, NULL, overlay_gpencil_draw_stroke_color_name, ob, false, cfra);
+}
+
+void OVERLAY_gpencil_cache_populate(OVERLAY_Data *vedata, Object *ob)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+
+ bGPdata *gpd = (bGPdata *)ob->data;
+ if (gpd == NULL) {
+ return;
+ }
+
+ if (GPENCIL_ANY_MODE(gpd)) {
+ OVERLAY_edit_gpencil_cache_populate(vedata, ob);
+ }
+
+ /* don't show object extras in set's */
+ if ((ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI)) == 0) {
+ if ((v3d->gp_flag & V3D_GP_SHOW_MATERIAL_NAME) && (ob->mode == OB_MODE_EDIT_GPENCIL) &&
+ DRW_state_show_text()) {
+ OVERLAY_gpencil_color_names(ob);
+ }
+ }
+}
+
+void OVERLAY_gpencil_draw(OVERLAY_Data *vedata)
+{
+ OVERLAY_PassList *psl = vedata->psl;
+
+ if (psl->gpencil_canvas_ps) {
+ DRW_draw_pass(psl->gpencil_canvas_ps);
+ }
+}
+
+void OVERLAY_edit_gpencil_draw(OVERLAY_Data *vedata)
+{
+ OVERLAY_PassList *psl = vedata->psl;
+
+ if (psl->edit_gpencil_gizmos_ps) {
+ DRW_draw_pass(psl->edit_gpencil_gizmos_ps);
+ }
+
+ if (psl->edit_gpencil_ps) {
+ DRW_draw_pass(psl->edit_gpencil_ps);
+ }
+}
diff --git a/source/blender/draw/engines/overlay/overlay_motion_path.c b/source/blender/draw/engines/overlay/overlay_motion_path.c
index 555e0084c49..29eb4fd12a4 100644
--- a/source/blender/draw/engines/overlay/overlay_motion_path.c
+++ b/source/blender/draw/engines/overlay/overlay_motion_path.c
@@ -155,7 +155,7 @@ static void motion_path_cache(OVERLAY_Data *vedata,
DRW_shgroup_uniform_bool_copy(grp, "selected", selected);
DRW_shgroup_uniform_vec3_copy(grp, "customColor", color);
/* Only draw the required range. */
- DRW_shgroup_call_range(grp, mpath_batch_line_get(mpath), start_index, len);
+ DRW_shgroup_call_range(grp, NULL, mpath_batch_line_get(mpath), start_index, len);
}
/* Draw points. */
@@ -167,7 +167,7 @@ static void motion_path_cache(OVERLAY_Data *vedata,
DRW_shgroup_uniform_bool_copy(grp, "showKeyFrames", show_keyframes);
DRW_shgroup_uniform_vec3_copy(grp, "customColor", color);
/* Only draw the required range. */
- DRW_shgroup_call_range(grp, mpath_batch_points_get(mpath), start_index, len);
+ DRW_shgroup_call_range(grp, NULL, mpath_batch_points_get(mpath), start_index, len);
}
/* Draw frame numbers at each frame-step value. */
diff --git a/source/blender/draw/engines/overlay/overlay_outline.c b/source/blender/draw/engines/overlay/overlay_outline.c
index 63738b3c214..e77a0a143a9 100644
--- a/source/blender/draw/engines/overlay/overlay_outline.c
+++ b/source/blender/draw/engines/overlay/overlay_outline.c
@@ -23,13 +23,67 @@
#include "DRW_render.h"
#include "BKE_global.h"
+#include "BKE_gpencil.h"
-#include "DNA_lightprobe_types.h"
+#include "BKE_object.h"
+
+#include "DNA_gpencil_types.h"
#include "UI_resources.h"
#include "overlay_private.h"
+/* Returns the normal plane in ndc space. */
+static void gpencil_depth_plane(Object *ob, float r_plane[4])
+{
+ /* TODO put that into private data. */
+ float viewinv[4][4];
+ DRW_view_viewmat_get(NULL, viewinv, true);
+ float *camera_z_axis = viewinv[2];
+ float *camera_pos = viewinv[3];
+
+ /* Find the normal most likely to represent the gpObject. */
+ /* TODO: This does not work quite well if you use
+ * strokes not aligned with the object axes. Maybe we could try to
+ * compute the minimum axis of all strokes. But this would be more
+ * computationaly heavy and should go into the GPData evaluation. */
+ BoundBox *bbox = BKE_object_boundbox_get(ob);
+ /* Convert bbox to matrix */
+ float mat[4][4], size[3], center[3];
+ BKE_boundbox_calc_size_aabb(bbox, size);
+ BKE_boundbox_calc_center_aabb(bbox, center);
+ unit_m4(mat);
+ copy_v3_v3(mat[3], center);
+ /* Avoid division by 0.0 later. */
+ add_v3_fl(size, 1e-8f);
+ rescale_m4(mat, size);
+ /* BBox space to World. */
+ mul_m4_m4m4(mat, ob->obmat, mat);
+ /* BBox center in world space. */
+ copy_v3_v3(center, mat[3]);
+ /* View Vector. */
+ if (DRW_view_is_persp_get(NULL)) {
+ /* BBox center to camera vector. */
+ sub_v3_v3v3(r_plane, camera_pos, mat[3]);
+ }
+ else {
+ copy_v3_v3(r_plane, camera_z_axis);
+ }
+ /* World to BBox space. */
+ invert_m4(mat);
+ /* Normalize the vector in BBox space. */
+ mul_mat3_m4_v3(mat, r_plane);
+ normalize_v3(r_plane);
+
+ transpose_m4(mat);
+ /* mat is now a "normal" matrix which will transform
+ * BBox space normal to world space. */
+ mul_mat3_m4_v3(mat, r_plane);
+ normalize_v3(r_plane);
+
+ plane_from_point_normal_v3(r_plane, center, r_plane);
+}
+
void OVERLAY_outline_init(OVERLAY_Data *vedata)
{
OVERLAY_FramebufferList *fbl = vedata->fbl;
@@ -79,6 +133,11 @@ void OVERLAY_outline_cache_init(OVERLAY_Data *vedata)
pd->outlines_grp = grp = DRW_shgroup_create(sh_geom, psl->outlines_prepass_ps);
DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0);
+
+ GPUShader *sh_gpencil = OVERLAY_shader_outline_prepass_gpencil();
+
+ pd->outlines_gpencil_grp = grp = DRW_shgroup_create(sh_gpencil, psl->outlines_prepass_ps);
+ DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0);
}
/* outlines_prepass_ps is still needed for selection of probes. */
@@ -107,6 +166,98 @@ void OVERLAY_outline_cache_init(OVERLAY_Data *vedata)
}
}
+typedef struct iterData {
+ Object *ob;
+ DRWShadingGroup *stroke_grp;
+ DRWShadingGroup *fill_grp;
+ int cfra;
+ float plane[4];
+} iterData;
+
+static void gp_layer_cache_populate(bGPDlayer *gpl,
+ bGPDframe *UNUSED(gpf),
+ bGPDstroke *UNUSED(gps),
+ void *thunk)
+{
+ iterData *iter = (iterData *)thunk;
+ bGPdata *gpd = (bGPdata *)iter->ob->data;
+
+ const bool is_screenspace = (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS) != 0;
+ const bool is_stroke_order_3d = (gpd->draw_mode == GP_DRAWMODE_3D);
+
+ float object_scale = mat4_to_scale(iter->ob->obmat);
+ /* Negate thickness sign to tag that strokes are in screen space.
+ * Convert to world units (by default, 1 meter = 2000 px). */
+ float thickness_scale = (is_screenspace) ? -1.0f : (gpd->pixfactor / 2000.0f);
+
+ DRWShadingGroup *grp = iter->stroke_grp = DRW_shgroup_create_sub(iter->stroke_grp);
+ DRW_shgroup_uniform_bool_copy(grp, "strokeOrder3d", is_stroke_order_3d);
+ DRW_shgroup_uniform_vec2_copy(grp, "sizeViewportInv", DRW_viewport_invert_size_get());
+ DRW_shgroup_uniform_vec2_copy(grp, "sizeViewport", DRW_viewport_size_get());
+ DRW_shgroup_uniform_float_copy(grp, "thicknessScale", object_scale);
+ DRW_shgroup_uniform_float_copy(grp, "thicknessOffset", (float)gpl->line_change);
+ DRW_shgroup_uniform_float_copy(grp, "thicknessWorldScale", thickness_scale);
+ DRW_shgroup_uniform_vec4_copy(grp, "gpDepthPlane", iter->plane);
+}
+
+static void gp_stroke_cache_populate(bGPDlayer *UNUSED(gpl),
+ bGPDframe *UNUSED(gpf),
+ bGPDstroke *gps,
+ void *thunk)
+{
+ iterData *iter = (iterData *)thunk;
+
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(iter->ob, gps->mat_nr + 1);
+
+ bool hide_material = (gp_style->flag & GP_MATERIAL_HIDE) != 0;
+ bool show_stroke = (gp_style->flag & GP_MATERIAL_STROKE_SHOW) != 0;
+ // TODO: What about simplify Fill?
+ bool show_fill = (gps->tot_triangles > 0) && (gp_style->flag & GP_MATERIAL_FILL_SHOW) != 0;
+
+ if (hide_material) {
+ return;
+ }
+
+ if (show_fill) {
+ struct GPUBatch *geom = DRW_cache_gpencil_fills_get(iter->ob, iter->cfra);
+ int vfirst = gps->runtime.fill_start * 3;
+ int vcount = gps->tot_triangles * 3;
+ DRW_shgroup_call_range(iter->fill_grp, iter->ob, geom, vfirst, vcount);
+ }
+
+ if (show_stroke) {
+ struct GPUBatch *geom = DRW_cache_gpencil_strokes_get(iter->ob, iter->cfra);
+ /* Start one vert before to have gl_InstanceID > 0 (see shader). */
+ int vfirst = gps->runtime.stroke_start - 1;
+ /* Include "potential" cyclic vertex and start adj vertex (see shader). */
+ int vcount = gps->totpoints + 1 + 1;
+ DRW_shgroup_call_instance_range(iter->stroke_grp, iter->ob, geom, vfirst, vcount);
+ }
+}
+
+static void OVERLAY_outline_gpencil(OVERLAY_PrivateData *pd, Object *ob)
+{
+ /* No outlines in edit mode. */
+ bGPdata *gpd = (bGPdata *)ob->data;
+ if (gpd && GPENCIL_ANY_MODE(gpd)) {
+ return;
+ }
+
+ iterData iter = {
+ .ob = ob,
+ .stroke_grp = pd->outlines_gpencil_grp,
+ .fill_grp = DRW_shgroup_create_sub(pd->outlines_gpencil_grp),
+ .cfra = pd->cfra,
+ };
+
+ if (gpd->draw_mode == GP_DRAWMODE_2D) {
+ gpencil_depth_plane(ob, iter.plane);
+ }
+
+ BKE_gpencil_visible_stroke_iter(
+ ob, gp_layer_cache_populate, gp_stroke_cache_populate, &iter, false, pd->cfra);
+}
+
void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata,
Object *ob,
OVERLAY_DupliData *dupli,
@@ -123,6 +274,11 @@ void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata,
return;
}
+ if (ob->type == OB_GPENCIL) {
+ OVERLAY_outline_gpencil(pd, ob);
+ return;
+ }
+
if (dupli && !init_dupli) {
geom = dupli->outline_geom;
shgroup = dupli->outline_shgrp;
diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h
index 185df723301..167a8e940df 100644
--- a/source/blender/draw/engines/overlay/overlay_private.h
+++ b/source/blender/draw/engines/overlay/overlay_private.h
@@ -60,6 +60,8 @@ typedef struct OVERLAY_PassList {
DRWPass *clipping_frustum_ps;
DRWPass *edit_curve_wire_ps[2];
DRWPass *edit_curve_handle_ps;
+ DRWPass *edit_gpencil_ps;
+ DRWPass *edit_gpencil_gizmos_ps;
DRWPass *edit_lattice_ps;
DRWPass *edit_mesh_depth_ps[2];
DRWPass *edit_mesh_verts_ps[2];
@@ -76,6 +78,7 @@ typedef struct OVERLAY_PassList {
DRWPass *extra_blend_ps;
DRWPass *extra_centers_ps;
DRWPass *extra_grid_ps;
+ DRWPass *gpencil_canvas_ps;
DRWPass *facing_ps;
DRWPass *grid_ps;
DRWPass *image_background_ps;
@@ -219,6 +222,8 @@ typedef struct OVERLAY_PrivateData {
DRWShadingGroup *edit_curve_points_grp;
DRWShadingGroup *edit_lattice_points_grp;
DRWShadingGroup *edit_lattice_wires_grp;
+ DRWShadingGroup *edit_gpencil_points_grp;
+ DRWShadingGroup *edit_gpencil_wires_grp;
DRWShadingGroup *edit_mesh_depth_grp[2];
DRWShadingGroup *edit_mesh_faces_grp[2];
DRWShadingGroup *edit_mesh_faces_cage_grp[2];
@@ -238,6 +243,7 @@ typedef struct OVERLAY_PrivateData {
DRWShadingGroup *motion_path_lines_grp;
DRWShadingGroup *motion_path_points_grp;
DRWShadingGroup *outlines_grp;
+ DRWShadingGroup *outlines_gpencil_grp;
DRWShadingGroup *paint_surf_grp;
DRWShadingGroup *paint_wire_grp;
DRWShadingGroup *paint_wire_selected_grp;
@@ -277,6 +283,7 @@ typedef struct OVERLAY_PrivateData {
float xray_opacity;
short v3d_flag; /* TODO move to View3DOverlay */
short v3d_gridflag; /* TODO move to View3DOverlay */
+ int cfra;
DRWState clipping_state;
OVERLAY_ShadingData shdata;
@@ -419,6 +426,12 @@ void OVERLAY_edit_curve_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_edit_surf_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_edit_curve_draw(OVERLAY_Data *vedata);
+void OVERLAY_edit_gpencil_cache_init(OVERLAY_Data *vedata);
+void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata);
+void OVERLAY_gpencil_cache_populate(OVERLAY_Data *vedata, Object *ob);
+void OVERLAY_gpencil_draw(OVERLAY_Data *vedata);
+void OVERLAY_edit_gpencil_draw(OVERLAY_Data *vedata);
+
void OVERLAY_edit_lattice_cache_init(OVERLAY_Data *vedata);
void OVERLAY_edit_lattice_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_lattice_cache_populate(OVERLAY_Data *vedata, Object *ob);
@@ -446,7 +459,6 @@ void OVERLAY_extra_centers_draw(OVERLAY_Data *vedata);
void OVERLAY_camera_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_empty_cache_populate(OVERLAY_Data *vedata, Object *ob);
-void OVERLAY_gpencil_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_light_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_lightprobe_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_speaker_cache_populate(OVERLAY_Data *vedata, Object *ob);
@@ -547,6 +559,9 @@ GPUShader *OVERLAY_shader_depth_only(void);
GPUShader *OVERLAY_shader_edit_curve_handle(void);
GPUShader *OVERLAY_shader_edit_curve_point(void);
GPUShader *OVERLAY_shader_edit_curve_wire(void);
+GPUShader *OVERLAY_shader_edit_gpencil_guide_point(void);
+GPUShader *OVERLAY_shader_edit_gpencil_point(void);
+GPUShader *OVERLAY_shader_edit_gpencil_wire(void);
GPUShader *OVERLAY_shader_edit_lattice_point(void);
GPUShader *OVERLAY_shader_edit_lattice_wire(void);
GPUShader *OVERLAY_shader_edit_mesh_analysis(void);
@@ -564,12 +579,14 @@ GPUShader *OVERLAY_shader_extra_wire(bool use_object);
GPUShader *OVERLAY_shader_extra_loose_point(void);
GPUShader *OVERLAY_shader_extra_point(void);
GPUShader *OVERLAY_shader_facing(void);
+GPUShader *OVERLAY_shader_gpencil_canvas(void);
GPUShader *OVERLAY_shader_grid(void);
GPUShader *OVERLAY_shader_image(void);
GPUShader *OVERLAY_shader_motion_path_line(void);
GPUShader *OVERLAY_shader_motion_path_vert(void);
GPUShader *OVERLAY_shader_uniform_color(void);
GPUShader *OVERLAY_shader_outline_prepass(bool use_wire);
+GPUShader *OVERLAY_shader_outline_prepass_gpencil(void);
GPUShader *OVERLAY_shader_extra_grid(void);
GPUShader *OVERLAY_shader_outline_detect(void);
GPUShader *OVERLAY_shader_paint_face(void);
diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c
index d33ef239198..86d5f58957e 100644
--- a/source/blender/draw/engines/overlay/overlay_shader.c
+++ b/source/blender/draw/engines/overlay/overlay_shader.c
@@ -54,6 +54,9 @@ extern char datatoc_edit_curve_handle_geom_glsl[];
extern char datatoc_edit_curve_handle_vert_glsl[];
extern char datatoc_edit_curve_point_vert_glsl[];
extern char datatoc_edit_curve_wire_vert_glsl[];
+extern char datatoc_edit_gpencil_canvas_vert_glsl[];
+extern char datatoc_edit_gpencil_guide_vert_glsl[];
+extern char datatoc_edit_gpencil_vert_glsl[];
extern char datatoc_edit_lattice_point_vert_glsl[];
extern char datatoc_edit_lattice_wire_vert_glsl[];
extern char datatoc_edit_mesh_common_lib_glsl[];
@@ -113,6 +116,8 @@ extern char datatoc_gpu_shader_flat_color_frag_glsl[];
extern char datatoc_gpu_shader_point_varying_color_varying_outline_aa_frag_glsl[];
extern char datatoc_gpu_shader_common_obinfos_lib_glsl[];
+extern char datatoc_gpencil_common_lib_glsl[];
+
extern char datatoc_common_colormanagement_lib_glsl[];
extern char datatoc_common_fullscreen_vert_glsl[];
extern char datatoc_common_fxaa_lib_glsl[];
@@ -138,6 +143,9 @@ typedef struct OVERLAY_Shaders {
GPUShader *edit_curve_handle;
GPUShader *edit_curve_point;
GPUShader *edit_curve_wire;
+ GPUShader *edit_gpencil_guide_point;
+ GPUShader *edit_gpencil_point;
+ GPUShader *edit_gpencil_wire;
GPUShader *edit_lattice_point;
GPUShader *edit_lattice_wire;
GPUShader *edit_mesh_vert;
@@ -159,11 +167,13 @@ typedef struct OVERLAY_Shaders {
GPUShader *extra_lightprobe_grid;
GPUShader *extra_loose_point;
GPUShader *facing;
+ GPUShader *gpencil_canvas;
GPUShader *grid;
GPUShader *image;
GPUShader *motion_path_line;
GPUShader *motion_path_vert;
GPUShader *outline_prepass;
+ GPUShader *outline_prepass_gpencil;
GPUShader *outline_prepass_wire;
GPUShader *outline_detect;
GPUShader *paint_face;
@@ -557,6 +567,58 @@ GPUShader *OVERLAY_shader_edit_curve_wire(void)
return sh_data->edit_curve_wire;
}
+GPUShader *OVERLAY_shader_edit_gpencil_guide_point(void)
+{
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
+ if (!sh_data->edit_gpencil_guide_point) {
+ sh_data->edit_gpencil_guide_point = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){datatoc_common_view_lib_glsl,
+ datatoc_edit_gpencil_guide_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_gpu_shader_point_varying_color_frag_glsl, NULL},
+ });
+ }
+ return sh_data->edit_gpencil_guide_point;
+}
+
+GPUShader *OVERLAY_shader_edit_gpencil_point(void)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
+ if (!sh_data->edit_gpencil_point) {
+ sh_data->edit_gpencil_point = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg->lib,
+ datatoc_common_globals_lib_glsl,
+ datatoc_common_view_lib_glsl,
+ datatoc_edit_gpencil_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_gpu_shader_point_varying_color_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg->def, "#define USE_POINTS\n", NULL},
+ });
+ }
+ return sh_data->edit_gpencil_point;
+}
+
+GPUShader *OVERLAY_shader_edit_gpencil_wire(void)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
+ if (!sh_data->edit_gpencil_wire) {
+ sh_data->edit_gpencil_wire = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg->lib,
+ datatoc_common_globals_lib_glsl,
+ datatoc_common_view_lib_glsl,
+ datatoc_edit_gpencil_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_gpu_shader_3D_smooth_color_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg->def, NULL},
+ });
+ }
+ return sh_data->edit_gpencil_wire;
+}
+
GPUShader *OVERLAY_shader_edit_lattice_point(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
@@ -883,6 +945,21 @@ GPUShader *OVERLAY_shader_facing(void)
return sh_data->facing;
}
+GPUShader *OVERLAY_shader_gpencil_canvas(void)
+{
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
+ if (!sh_data->gpencil_canvas) {
+ sh_data->gpencil_canvas = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){datatoc_common_globals_lib_glsl,
+ datatoc_common_view_lib_glsl,
+ datatoc_edit_gpencil_canvas_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_common_view_lib_glsl, datatoc_extra_frag_glsl, NULL},
+ });
+ }
+ return sh_data->gpencil_canvas;
+}
+
GPUShader *OVERLAY_shader_grid(void)
{
OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
@@ -998,6 +1075,32 @@ GPUShader *OVERLAY_shader_outline_prepass(bool use_wire)
return use_wire ? sh_data->outline_prepass_wire : sh_data->outline_prepass;
}
+GPUShader *OVERLAY_shader_outline_prepass_gpencil(void)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
+ OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
+ if (!sh_data->outline_prepass_gpencil) {
+ sh_data->outline_prepass_gpencil = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_gpencil_common_lib_glsl,
+ datatoc_gpu_shader_common_obinfos_lib_glsl,
+ datatoc_outline_prepass_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_common_view_lib_glsl,
+ datatoc_gpencil_common_lib_glsl,
+ datatoc_outline_prepass_frag_glsl,
+ NULL},
+ .defs = (const char *[]){sh_cfg->def,
+ "#define USE_GPENCIL\n",
+ "#define UNIFORM_RESOURCE_ID\n",
+ NULL},
+ });
+ }
+ return sh_data->outline_prepass_gpencil;
+}
+
GPUShader *OVERLAY_shader_outline_detect(void)
{
OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c
index 5dbdc71dae1..4df9faace18 100644
--- a/source/blender/draw/engines/overlay/overlay_wireframe.c
+++ b/source/blender/draw/engines/overlay/overlay_wireframe.c
@@ -201,7 +201,11 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
shgrp = pd->wires_grp[is_xray][use_coloring];
}
- if (use_sculpt_pbvh) {
+ if (ob->type == OB_GPENCIL) {
+ /* TODO (fclem) Make GPencil objects have correct boundbox. */
+ DRW_shgroup_call_no_cull(shgrp, geom, ob);
+ }
+ else if (use_sculpt_pbvh) {
DRW_shgroup_call_sculpt(shgrp, ob, true, false, false);
}
else {
diff --git a/source/blender/draw/engines/overlay/shaders/edit_gpencil_canvas_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_gpencil_canvas_vert.glsl
new file mode 100644
index 00000000000..5aa7fe78e4e
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/edit_gpencil_canvas_vert.glsl
@@ -0,0 +1,35 @@
+
+uniform vec4 color;
+uniform vec3 xAxis;
+uniform vec3 yAxis;
+uniform vec3 origin;
+uniform int halfLineCount;
+
+flat out vec4 finalColor;
+flat out vec2 edgeStart;
+noperspective out vec2 edgePos;
+
+void main()
+{
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
+ vec2 pos;
+ pos.x = float(gl_VertexID % 2);
+ pos.y = float(gl_VertexID / 2) / float(halfLineCount - 1);
+
+ if (pos.y > 1.0) {
+ pos.xy = pos.yx;
+ pos.x -= 1.0 + 1.0 / float(halfLineCount - 1);
+ }
+
+ pos -= 0.5;
+
+ vec3 world_pos = xAxis * pos.x + yAxis * pos.y + origin;
+
+ gl_Position = point_world_to_ndc(world_pos);
+
+ finalColor = color;
+
+ /* Convert to screen position [0..sizeVp]. */
+ edgePos = edgeStart = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy;
+}
diff --git a/source/blender/draw/engines/overlay/shaders/edit_gpencil_guide_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_gpencil_guide_vert.glsl
new file mode 100644
index 00000000000..ef68b0f4e6f
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/edit_gpencil_guide_vert.glsl
@@ -0,0 +1,14 @@
+uniform vec4 pColor;
+uniform float pSize;
+uniform vec3 pPosition;
+
+out vec4 finalColor;
+
+void main()
+{
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
+ gl_Position = point_world_to_ndc(pPosition);
+ finalColor = pColor;
+ gl_PointSize = pSize;
+}
diff --git a/source/blender/draw/engines/overlay/shaders/edit_gpencil_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_gpencil_vert.glsl
new file mode 100644
index 00000000000..cb03ad44615
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/edit_gpencil_vert.glsl
@@ -0,0 +1,103 @@
+
+uniform float normalSize;
+uniform bool doMultiframe;
+uniform bool doStrokeEndpoints;
+uniform bool hideSelect;
+uniform bool doWeightColor;
+uniform float gpEditOpacity;
+uniform vec4 gpEditColor;
+uniform sampler1D weightTex;
+
+in vec3 pos;
+in float ma;
+in uint vflag;
+in float weight;
+
+out vec4 finalColor;
+
+void discard_vert()
+{
+ /* We set the vertex at the camera origin to generate 0 fragments. */
+ gl_Position = vec4(0.0, 0.0, -3e36, 0.0);
+}
+
+#define GP_EDIT_POINT_SELECTED (1u << 0u)
+#define GP_EDIT_STROKE_SELECTED (1u << 1u)
+#define GP_EDIT_MULTIFRAME (1u << 2u)
+#define GP_EDIT_STROKE_START (1u << 3u)
+#define GP_EDIT_STROKE_END (1u << 4u)
+
+#ifdef USE_POINTS
+# define colorUnselect colorGpencilVertex
+# define colorSelect colorGpencilVertexSelect
+#else
+# define colorUnselect gpEditColor
+# define colorSelect (hideSelect ? colorUnselect : colorGpencilVertexSelect)
+#endif
+
+vec3 weight_to_rgb(float t)
+{
+ if (t < 0.0) {
+ /* No weight */
+ return colorUnselect.rgb;
+ }
+ else if (t > 1.0) {
+ /* Error color */
+ return vec3(1.0, 0.0, 1.0);
+ }
+ else {
+ return texture(weightTex, t).rgb;
+ }
+}
+
+void main()
+{
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
+ vec3 world_pos = point_object_to_world(pos);
+ gl_Position = point_world_to_ndc(world_pos);
+
+ bool is_multiframe = (vflag & GP_EDIT_MULTIFRAME) != 0u;
+ bool is_stroke_sel = (vflag & GP_EDIT_STROKE_SELECTED) != 0u;
+ bool is_point_sel = (vflag & GP_EDIT_POINT_SELECTED) != 0u;
+
+ if (doWeightColor) {
+ finalColor.rgb = weight_to_rgb(weight);
+ finalColor.a = gpEditOpacity;
+ }
+ else {
+ finalColor = (is_point_sel) ? colorSelect : colorUnselect;
+ finalColor.a *= gpEditOpacity;
+ }
+
+#ifdef USE_POINTS
+ gl_PointSize = sizeVertex * 2.0;
+
+ if (doStrokeEndpoints && !doWeightColor) {
+ bool is_stroke_start = (vflag & GP_EDIT_STROKE_START) != 0u;
+ bool is_stroke_end = (vflag & GP_EDIT_STROKE_END) != 0u;
+
+ if (is_stroke_start) {
+ gl_PointSize *= 2.0;
+ finalColor.rgb = vec3(0.0, 1.0, 0.0);
+ }
+ else if (is_stroke_end) {
+ gl_PointSize *= 1.5;
+ finalColor.rgb = vec3(1.0, 0.0, 0.0);
+ }
+ }
+
+ if ((!is_stroke_sel && !doWeightColor) || (!doMultiframe && is_multiframe)) {
+ discard_vert();
+ }
+#endif
+
+ /* Discard unwanted padding vertices. */
+ if (ma == -1.0 || (is_multiframe && !doMultiframe)) {
+ discard_vert();
+ }
+
+#ifdef USE_WORLD_CLIP_PLANES
+ world_clip_planes_calc_clip_distance(world_pos);
+#endif
+}
diff --git a/source/blender/draw/engines/overlay/shaders/outline_prepass_frag.glsl b/source/blender/draw/engines/overlay/shaders/outline_prepass_frag.glsl
index f6e3724eb51..85f79e94263 100644
--- a/source/blender/draw/engines/overlay/shaders/outline_prepass_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/outline_prepass_frag.glsl
@@ -1,10 +1,46 @@
+uniform vec4 gpDepthPlane;
+
flat in uint objectId;
/* using uint because 16bit uint can contain more ids than int. */
out uint outId;
+vec3 ray_plane_intersection(vec3 ray_ori, vec3 ray_dir, vec4 plane)
+{
+ float d = dot(plane.xyz, ray_dir);
+ vec3 plane_co = plane.xyz * (-plane.w / dot(plane.xyz, plane.xyz));
+ vec3 h = ray_ori - plane_co;
+ float lambda = -dot(plane.xyz, h) / ((abs(d) < 1e-8) ? 1e-8 : d);
+ return ray_ori + ray_dir * lambda;
+}
+
void main()
{
- outId = objectId;
+#ifdef USE_GPENCIL
+ if (stroke_round_cap_mask(strokePt1, strokePt2, strokeAspect, strokeThickness, strokeHardeness) <
+ 0.001) {
+ discard;
+ }
+
+ if (depth != -1.0) {
+ /* Stroke order 2D. */
+ bool is_persp = ProjectionMatrix[3][3] == 0.0;
+ vec2 uvs = vec2(gl_FragCoord.xy) * sizeViewportInv;
+ vec3 pos_ndc = vec3(uvs, gl_FragCoord.z) * 2.0 - 1.0;
+ vec4 pos_world = ViewProjectionMatrixInverse * vec4(pos_ndc, 1.0);
+ vec3 pos = pos_world.xyz / pos_world.w;
+
+ vec3 ray_ori = pos;
+ vec3 ray_dir = (is_persp) ? (ViewMatrixInverse[3].xyz - pos) : ViewMatrixInverse[2].xyz;
+ vec3 isect = ray_plane_intersection(ray_ori, ray_dir, gpDepthPlane);
+ vec4 ndc = point_world_to_ndc(isect);
+ gl_FragDepth = (ndc.z / ndc.w) * 0.5 + 0.5;
+ }
+ else {
+ gl_FragDepth = gl_FragCoord.z;
+ }
+#endif
+
+ outId = uint(objectId);
}
diff --git a/source/blender/draw/engines/overlay/shaders/outline_prepass_vert.glsl b/source/blender/draw/engines/overlay/shaders/outline_prepass_vert.glsl
index 984e55b0c46..a2021759196 100644
--- a/source/blender/draw/engines/overlay/shaders/outline_prepass_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/outline_prepass_vert.glsl
@@ -1,7 +1,9 @@
uniform bool isTransform;
+#ifndef USE_GPENCIL
in vec3 pos;
+#endif
#ifdef USE_GEOM
out vec3 vPos;
@@ -47,11 +49,19 @@ uint outline_colorid_get(void)
void main()
{
+#ifdef USE_GPENCIL
+ gpencil_vertex();
+# ifdef USE_WORLD_CLIP_PLANES
+ vec3 world_pos = point_object_to_world(pos1.xyz);
+# endif
+
+#else
vec3 world_pos = point_object_to_world(pos);
-#ifdef USE_GEOM
+ gl_Position = point_world_to_ndc(world_pos);
+# ifdef USE_GEOM
vPos = point_world_to_view(world_pos);
+# endif
#endif
- gl_Position = point_world_to_ndc(world_pos);
/* Small bias to always be on top of the geom. */
gl_Position.z -= 1e-3;
diff --git a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl
index 31ac9a2b181..1abac302cda 100644
--- a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl
@@ -101,8 +101,10 @@ void wire_object_color_get(out vec3 rim_col, out vec3 wire_col)
void main()
{
+ bool no_attrib = all(equal(nor, vec3(0)));
+ vec3 wnor = no_attrib ? ViewMatrixInverse[2].xyz : normalize(normal_object_to_world(nor));
+
vec3 wpos = point_object_to_world(pos);
- vec3 wnor = normalize(normal_object_to_world(nor));
bool is_persp = (ProjectionMatrix[3][3] == 0.0);
vec3 V = (is_persp) ? normalize(ViewMatrixInverse[3].xyz - wpos) : ViewMatrixInverse[2].xyz;
@@ -147,7 +149,7 @@ void main()
#endif
/* Cull flat edges below threshold. */
- if (get_edge_sharpness(wd) < 0.0) {
+ if (!no_attrib && (get_edge_sharpness(wd) < 0.0)) {
edgeStart = vec2(-1.0);
}