diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2018-08-15 18:43:39 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2018-08-17 00:57:59 +0300 |
commit | c761153f64e714d2ce4d4fdf2edc671719771501 (patch) | |
tree | 9be7a8e4d385b38ba2a0e778b98a2b7c72ff5535 /source | |
parent | 32e57fe4e76576c9fd628486d0845fd83bb8c51f (diff) |
Overlays: Support for wireframes and edit mode overlay on xray objects
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/draw/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/draw/engines/workbench/workbench_deferred.c | 19 | ||||
-rw-r--r-- | source/blender/draw/modes/edit_mesh_mode.c | 55 | ||||
-rw-r--r-- | source/blender/draw/modes/object_mode.c | 2 | ||||
-rw-r--r-- | source/blender/draw/modes/overlay_mode.c | 51 | ||||
-rw-r--r-- | source/blender/draw/modes/shaders/edit_mesh_overlay_ghost_clear_vert.glsl | 7 |
6 files changed, 114 insertions, 21 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 916688cadc3..434f0179333 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -270,6 +270,7 @@ data_to_c_simple(modes/shaders/edit_mesh_overlay_geom_edge.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_loosevert_vert.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_facedot_frag.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_facedot_vert.glsl SRC) +data_to_c_simple(modes/shaders/edit_mesh_overlay_ghost_clear_vert.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_mix_frag.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_facefill_vert.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_facefill_frag.glsl SRC) diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index ecffade45c3..696393a6ae1 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -923,8 +923,8 @@ void workbench_deferred_draw_scene(WORKBENCH_Data *vedata) if (GHOST_ENABLED(psl)) { /* We need to set the stencil buffer to 0 where Ghost objects * else they will get shadow and even badly shadowed. */ - DRW_pass_state_set(psl->ghost_prepass_pass, DRW_STATE_WRITE_STENCIL); - DRW_pass_state_set(psl->ghost_prepass_hair_pass, DRW_STATE_WRITE_STENCIL); + DRW_pass_state_set(psl->ghost_prepass_pass, DRW_STATE_DEPTH_EQUAL | DRW_STATE_WRITE_STENCIL); + DRW_pass_state_set(psl->ghost_prepass_hair_pass, DRW_STATE_DEPTH_EQUAL | DRW_STATE_WRITE_STENCIL); DRW_draw_pass(psl->ghost_prepass_pass); DRW_draw_pass(psl->ghost_prepass_hair_pass); @@ -940,6 +940,21 @@ void workbench_deferred_draw_scene(WORKBENCH_Data *vedata) DRW_draw_pass(psl->composite_pass); } + /* TODO(fclem): only enable when needed (when there is overlays). */ + if (GHOST_ENABLED(psl)) { + /* In order to not draw on top of ghost objects, we clear the stencil + * to 0xFF and the ghost object to 0x00 and only draw overlays on top if + * stencil is not 0. */ + GPU_framebuffer_bind(dfbl->depth_only_fb); + GPU_framebuffer_clear_stencil(dfbl->depth_only_fb, 0xFF); + + DRW_pass_state_set(psl->ghost_prepass_pass, DRW_STATE_DEPTH_EQUAL | DRW_STATE_WRITE_STENCIL); + DRW_pass_state_set(psl->ghost_prepass_hair_pass, DRW_STATE_DEPTH_EQUAL | DRW_STATE_WRITE_STENCIL); + + DRW_draw_pass(psl->ghost_prepass_pass); + DRW_draw_pass(psl->ghost_prepass_hair_pass); + } + if (wpd->volumes_do) { GPU_framebuffer_bind(fbl->volume_fb); DRW_draw_pass(psl->volume_pass); diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c index 67a424b8081..98fd1b249be 100644 --- a/source/blender/draw/modes/edit_mesh_mode.c +++ b/source/blender/draw/modes/edit_mesh_mode.c @@ -53,7 +53,7 @@ extern char datatoc_edit_mesh_overlay_geom_edge_glsl[]; extern char datatoc_edit_mesh_overlay_loosevert_vert_glsl[]; extern char datatoc_edit_mesh_overlay_facedot_frag_glsl[]; extern char datatoc_edit_mesh_overlay_facedot_vert_glsl[]; -extern char datatoc_edit_mesh_overlay_mix_vert_glsl[]; +extern char datatoc_edit_mesh_overlay_ghost_clear_vert_glsl[]; extern char datatoc_edit_mesh_overlay_mix_frag_glsl[]; extern char datatoc_edit_mesh_overlay_facefill_vert_glsl[]; extern char datatoc_edit_mesh_overlay_facefill_frag_glsl[]; @@ -67,6 +67,7 @@ extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; typedef struct EDIT_MESH_PassList { struct DRWPass *vcolor_faces; struct DRWPass *depth_hidden_wire; + struct DRWPass *ghost_clear_depth; struct DRWPass *edit_face_overlay; struct DRWPass *edit_face_occluded; struct DRWPass *mix_occlude; @@ -76,6 +77,7 @@ typedef struct EDIT_MESH_PassList { typedef struct EDIT_MESH_FramebufferList { struct GPUFrameBuffer *occlude_wire_fb; + struct GPUFrameBuffer *ghost_wire_fb; } EDIT_MESH_FramebufferList; typedef struct EDIT_MESH_StorageList { @@ -109,6 +111,7 @@ static struct { GPUShader *normals_loop_sh; GPUShader *normals_sh; GPUShader *depth_sh; + GPUShader *ghost_clear_depth_sh; /* temp buffer texture */ struct GPUTexture *occlude_wire_depth_tx; struct GPUTexture *occlude_wire_color_tx; @@ -134,6 +137,8 @@ typedef struct EDIT_MESH_PrivateData { DRWShadingGroup *facedot_occluded_shgrp; DRWShadingGroup *facefill_occluded_shgrp; + int ghost_ob; + int edit_ob; bool do_zbufclip; } EDIT_MESH_PrivateData; /* Transient data */ @@ -300,6 +305,10 @@ static void EDIT_MESH_engine_init(void *vedata) if (!e_data.depth_sh) { e_data.depth_sh = DRW_shader_create_3D_depth_only(); } + if (!e_data.ghost_clear_depth_sh) { + e_data.ghost_clear_depth_sh = DRW_shader_create(datatoc_edit_mesh_overlay_ghost_clear_vert_glsl, + NULL, NULL, NULL); + } } static DRWPass *edit_mesh_create_overlay_pass( @@ -362,7 +371,8 @@ static void EDIT_MESH_cache_init(void *vedata) /* Alloc transient pointers */ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); } - + stl->g_data->ghost_ob = 0; + stl->g_data->edit_ob = 0; const bool xray_enabled = ((draw_ctx->v3d->shading.flag & V3D_SHADING_XRAY) != 0) && (draw_ctx->v3d->shading.type < OB_MATERIAL); @@ -392,6 +402,17 @@ static void EDIT_MESH_cache_init(void *vedata) } { + /* Depth clearing for ghosting. */ + psl->ghost_clear_depth = DRW_pass_create( + "Ghost Depth Clear", + DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_STENCIL_NEQUAL); + + DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.ghost_clear_depth_sh, psl->ghost_clear_depth); + DRW_shgroup_stencil_mask(shgrp, 0x00); + DRW_shgroup_call_add(shgrp, DRW_cache_fullscreen_quad_get(), NULL); + } + + { /* Normals */ psl->normals = DRW_pass_create( "Edit Mesh Normals Pass", @@ -412,7 +433,7 @@ static void EDIT_MESH_cache_init(void *vedata) if (!stl->g_data->do_zbufclip) { psl->edit_face_overlay = edit_mesh_create_overlay_pass( - &face_mod, DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WRITE_DEPTH | DRW_STATE_BLEND, + &face_mod, DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND, &stl->g_data->face_overlay_shgrp, &stl->g_data->ledges_overlay_shgrp, &stl->g_data->lverts_overlay_shgrp, &stl->g_data->facedot_overlay_shgrp); } @@ -538,6 +559,9 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob) stl->g_data->lverts_overlay_shgrp, NULL, NULL); } + stl->g_data->ghost_ob += (ob->dtx & OB_DRAWXRAY) ? 1 : 0; + stl->g_data->edit_ob += 1; + /* 3D text overlay */ if (me->drawflag & (ME_DRAWEXTRA_EDGELEN | ME_DRAWEXTRA_FACEAREA | @@ -560,6 +584,7 @@ static void EDIT_MESH_draw_scene(void *vedata) EDIT_MESH_StorageList *stl = ((EDIT_MESH_Data *)vedata)->stl; EDIT_MESH_FramebufferList *fbl = ((EDIT_MESH_Data *)vedata)->fbl; DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); DRW_draw_pass(psl->vcolor_faces); @@ -582,6 +607,30 @@ static void EDIT_MESH_draw_scene(void *vedata) } else { DRW_draw_pass(psl->normals); + + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + + if (v3d->shading.type == OB_SOLID && (v3d->shading.flag & V3D_SHADING_XRAY) == 0) { + if (stl->g_data->ghost_ob == 1 && stl->g_data->edit_ob == 1) { + /* In the case of single ghost object edit (common case for retopology): + * we duplicate the depht+stencil buffer and clear all depth to 1.0f where + * the stencil buffer is no 0x00. */ + const float *viewport_size = DRW_viewport_size_get(); + const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + struct GPUTexture *ghost_depth_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_DEPTH24_STENCIL8, &draw_engine_edit_mesh_type); + GPU_framebuffer_ensure_config(&fbl->ghost_wire_fb, { + GPU_ATTACHMENT_TEXTURE(ghost_depth_tx), + GPU_ATTACHMENT_TEXTURE(dtxl->color), + }); + + GPU_framebuffer_blit(dfbl->depth_only_fb, 0, fbl->ghost_wire_fb, 0, GPU_DEPTH_BIT | GPU_STENCIL_BIT); + GPU_framebuffer_bind(fbl->ghost_wire_fb); + + DRW_draw_pass(psl->ghost_clear_depth); + } + } + DRW_draw_pass(psl->edit_face_overlay); } } diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index cc4142529ec..7e74e5f9629 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -2553,7 +2553,7 @@ static void OBJECT_cache_populate(void *vedata, Object *ob) const bool hide_object_extra = (v3d->overlay.flag & V3D_OVERLAY_HIDE_OBJECT_XTRAS) != 0; if (do_outlines) { - if ((ob != draw_ctx->object_edit) && !((ob == draw_ctx->obact) && (draw_ctx->object_mode & OB_MODE_ALL_PAINT))) { + if (!BKE_object_is_in_editmode(ob) && !((ob == draw_ctx->obact) && (draw_ctx->object_mode & OB_MODE_ALL_PAINT))) { struct GPUBatch *geom; const bool xray_enabled = ((v3d->shading.flag & V3D_SHADING_XRAY) != 0) && (v3d->shading.type < OB_MATERIAL); diff --git a/source/blender/draw/modes/overlay_mode.c b/source/blender/draw/modes/overlay_mode.c index e3c986bde5a..fffbd60b5d4 100644 --- a/source/blender/draw/modes/overlay_mode.c +++ b/source/blender/draw/modes/overlay_mode.c @@ -56,6 +56,7 @@ typedef struct OVERLAY_PrivateData { DRWShadingGroup *face_orientation_shgrp; View3DOverlay overlay; float wire_step_param[2]; + bool ghost_stencil_test; } OVERLAY_PrivateData; /* Transient data */ /* *********** STATIC *********** */ @@ -87,6 +88,7 @@ static void overlay_engine_init(void *vedata) /* Alloc transient pointers */ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); } + stl->g_data->ghost_stencil_test = false; if (!e_data.face_orientation_sh) { /* Face orientation */ @@ -146,20 +148,22 @@ static void overlay_cache_init(void *vedata) : e_data.face_wireframe_pretty_sh; DRWShadingGroup *shgrp = DRW_shgroup_create(stl->g_data->wire_sh, psl->face_wireframe_pass); DRW_shgroup_uniform_vec2(shgrp, "viewportSize", DRW_viewport_size_get(), 1); - DRW_shgroup_uniform_vec2(shgrp, "wireStepParam", stl->g_data->wire_step_param, 1); - - /** - * The wireframe threshold ranges from 0.0 to 1.0 - * When 1.0 we show all the edges, when 0.5 we show as many as 2.7. - * - * If we wanted 0.0 to match 2.7, factor would need to be 0.003f. - * The range controls the falloff effect. If range was 0.0f we would get a hard cut (as in 2.7). - * That said we are using a different algorithm so the results will always differ. - */ - const float factor = 0.0045f; - const float range = 0.00125f; - stl->g_data->wire_step_param[1] = (1.0f - factor) + stl->g_data->overlay.wireframe_threshold * factor; - stl->g_data->wire_step_param[0] = stl->g_data->wire_step_param[1] + range; + if (stl->g_data->overlay.wireframe_threshold < 1.0f) { + /** + * The wireframe threshold ranges from 0.0 to 1.0 + * When 1.0 we show all the edges, when 0.5 we show as many as 2.7. + * + * If we wanted 0.0 to match 2.7, factor would need to be 0.003f. + * The range controls the falloff effect. If range was 0.0f we would get a hard cut (as in 2.7). + * That said we are using a different algorithm so the results will always differ. + */ + const float factor = 0.0045f; + const float range = 0.00125f; + stl->g_data->wire_step_param[1] = (1.0f - factor) + stl->g_data->overlay.wireframe_threshold * factor; + stl->g_data->wire_step_param[0] = stl->g_data->wire_step_param[1] + range; + + DRW_shgroup_uniform_vec2(shgrp, "wireStepParam", stl->g_data->wire_step_param, 1); + } } } @@ -193,6 +197,7 @@ static void overlay_cache_populate(void *vedata, Object *ob) rim_col = (ob == draw_ctx->obact) ? ts.colorActive : ts.colorSelect; } DRWShadingGroup *shgrp = DRW_shgroup_create(stl->g_data->wire_sh, psl->face_wireframe_pass); + DRW_shgroup_stencil_mask(shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF); DRW_shgroup_uniform_texture(shgrp, "vertData", verts); DRW_shgroup_uniform_texture(shgrp, "faceIds", faceids); DRW_shgroup_uniform_vec3(shgrp, "wireColor", ts.colorWire, 1); @@ -201,10 +206,26 @@ static void overlay_cache_populate(void *vedata, Object *ob) } } } + + if (ob->dtx & OB_DRAWXRAY) { + stl->g_data->ghost_stencil_test = true; + } } -static void overlay_cache_finish(void *UNUSED(vedata)) +static void overlay_cache_finish(void *vedata) { + OVERLAY_Data * data = (OVERLAY_Data *)vedata; + OVERLAY_PassList *psl = data->psl; + OVERLAY_StorageList *stl = data->stl; + + const DRWContextState *ctx = DRW_context_state_get(); + View3D *v3d = ctx->v3d; + + /* only in solid mode */ + if (v3d->shading.type == OB_SOLID && (v3d->shading.flag & V3D_SHADING_XRAY) == 0) { + if (stl->g_data->ghost_stencil_test) + DRW_pass_state_add(psl->face_wireframe_pass, DRW_STATE_STENCIL_EQUAL); + } } static void overlay_draw_scene(void *vedata) diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_ghost_clear_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_ghost_clear_vert.glsl new file mode 100644 index 00000000000..3fd4d263aa2 --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_ghost_clear_vert.glsl @@ -0,0 +1,7 @@ + +in vec2 pos; + +void main() +{ + gl_Position = vec4(pos, 1.0, 1.0); +} |