diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index f2f211d1db9..49b84b41744 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -1268,14 +1268,14 @@ void workbench_deferred_draw_scene(WORKBENCH_Data *vedata) DRW_draw_pass(psl->composite_pass); } + /* 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); + /* 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); - DRWState state = DRW_STATE_DEPTH_EQUAL | DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS; DRW_pass_state_set(psl->ghost_prepass_pass, state); DRW_pass_state_set(psl->ghost_prepass_hair_pass, state); diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index eccf2b1a0f0..612a3901ca0 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -674,7 +674,7 @@ void workbench_forward_draw_background(WORKBENCH_Data *UNUSED(vedata)) DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); DRW_stats_group_start("Clear depth"); GPU_framebuffer_bind(dfbl->default_fb); - GPU_framebuffer_clear_depth(dfbl->default_fb, clear_depth); + GPU_framebuffer_clear_depth_stencil(dfbl->default_fb, clear_depth, 0xFF); DRW_stats_group_end(); } diff --git a/source/blender/draw/modes/overlay_mode.c b/source/blender/draw/modes/overlay_mode.c index aaaeefa81c9..ae5c0064cde 100644 --- a/source/blender/draw/modes/overlay_mode.c +++ b/source/blender/draw/modes/overlay_mode.c @@ -59,6 +59,8 @@ typedef struct OVERLAY_StorageList { typedef struct OVERLAY_PassList { struct DRWPass *face_orientation_pass; struct DRWPass *face_wireframe_pass; + struct DRWPass *face_wireframe_only_pass; + struct DRWPass *face_wireframe_xray_pass; } OVERLAY_PassList; typedef struct OVERLAY_Data { @@ -72,11 +74,12 @@ typedef struct OVERLAY_Data { typedef struct OVERLAY_PrivateData { DRWShadingGroup *face_orientation_shgrp; DRWShadingGroup *face_wires_shgrp; + DRWShadingGroup *face_wires_xray_shgrp; DRWView *view_wires; BLI_mempool *wire_color_mempool; View3DOverlay overlay; float wire_step_param; - bool ghost_stencil_test; + bool clear_stencil; bool show_overlays; } OVERLAY_PrivateData; /* Transient data */ @@ -117,7 +120,8 @@ static void overlay_engine_init(void *vedata) /* Alloc transient pointers */ stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__); } - stl->g_data->ghost_stencil_test = false; + + stl->g_data->clear_stencil = (draw_ctx->v3d->shading.type > OB_SOLID); const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; @@ -169,6 +173,13 @@ static void overlay_engine_init(void *vedata) stl->g_data->view_wires = DRW_view_create_with_zoffset(draw_ctx->rv3d, 0.5f); } +static void geometry_shader_uniforms(DRWShadingGroup *shgrp) +{ + DRW_shgroup_uniform_float_copy(shgrp, "wireSize", U.pixelsize * 0.5f); + DRW_shgroup_uniform_vec2(shgrp, "viewportSize", DRW_viewport_size_get(), 1); + DRW_shgroup_uniform_vec2(shgrp, "viewportSizeInv", DRW_viewport_invert_size_get(), 1); +} + static void overlay_cache_init(void *vedata) { OVERLAY_Data *data = vedata; @@ -215,27 +226,28 @@ static void overlay_cache_init(void *vedata) { /* Wireframe */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | - DRW_STATE_FIRST_VERTEX_CONVENTION; - float wire_size = U.pixelsize * 0.5f; - const bool use_select = (DRW_state_is_select() || DRW_state_is_depth()); GPUShader *face_wires_sh = use_select ? sh_data->select_wireframe : sh_data->face_wireframe; - psl->face_wireframe_pass = DRW_pass_create("Face Wires", state); - + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_STENCIL_EQUAL | DRW_STATE_FIRST_VERTEX_CONVENTION; + psl->face_wireframe_pass = DRW_pass_create("Wires", state); g_data->face_wires_shgrp = DRW_shgroup_create(face_wires_sh, psl->face_wireframe_pass); - DRW_shgroup_uniform_float( - g_data->face_wires_shgrp, "wireStepParam", &g_data->wire_step_param, 1); + + DRWState state_xray = DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_STENCIL | + DRW_STATE_DEPTH_GREATER_EQUAL | DRW_STATE_STENCIL_NEQUAL | + DRW_STATE_FIRST_VERTEX_CONVENTION; + psl->face_wireframe_xray_pass = DRW_pass_create("Wires Only Xray", state_xray); + g_data->face_wires_xray_shgrp = DRW_shgroup_create(face_wires_sh, + psl->face_wireframe_xray_pass); + if (use_select || USE_GEOM_SHADER_WORKAROUND) { - DRW_shgroup_uniform_float_copy(g_data->face_wires_shgrp, "wireSize", wire_size); - DRW_shgroup_uniform_vec2( - g_data->face_wires_shgrp, "viewportSize", DRW_viewport_size_get(), 1); - DRW_shgroup_uniform_vec2( - g_data->face_wires_shgrp, "viewportSizeInv", DRW_viewport_invert_size_get(), 1); + geometry_shader_uniforms(g_data->face_wires_shgrp); + geometry_shader_uniforms(g_data->face_wires_xray_shgrp); } if (rv3d->rflag & RV3D_CLIPPING) { DRW_shgroup_state_enable(g_data->face_wires_shgrp, DRW_STATE_CLIP_PLANES); + DRW_shgroup_state_enable(g_data->face_wires_xray_shgrp, DRW_STATE_CLIP_PLANES); } g_data->wire_step_param = stl->g_data->overlay.wireframe_threshold - 254.0f / 255.0f; @@ -383,19 +395,21 @@ static void overlay_cache_populate(void *vedata, Object *ob) const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d); const bool all_wires = (ob->dtx & OB_DRAW_ALL_EDGES); const bool is_wire = (ob->dt < OB_SOLID); + const bool is_xray = (ob->dtx & OB_DRAWXRAY); const bool use_coloring = (pd->show_overlays && !is_edit_mode && !use_sculpt_pbvh && !has_edit_mesh_cage); - const int stencil_mask = (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF; - float *rim_col, *wire_col; DRWShadingGroup *shgrp = NULL; - overlay_wire_color_get(v3d, pd, ob, use_coloring, &rim_col, &wire_col); - struct GPUBatch *geom; geom = DRW_cache_object_face_wireframe_get(ob); if (geom || use_sculpt_pbvh) { - shgrp = DRW_shgroup_create_sub(pd->face_wires_shgrp); + if (is_wire && is_xray) { + shgrp = DRW_shgroup_create_sub(pd->face_wires_xray_shgrp); + } + else { + shgrp = DRW_shgroup_create_sub(pd->face_wires_shgrp); + } float wire_step_param = 10.0f; if (!use_sculpt_pbvh) { @@ -404,9 +418,12 @@ static void overlay_cache_populate(void *vedata, Object *ob) DRW_shgroup_uniform_float_copy(shgrp, "wireStepParam", wire_step_param); if (!(DRW_state_is_select() || DRW_state_is_depth())) { - DRW_shgroup_stencil_mask(shgrp, stencil_mask); + float *rim_col, *wire_col; + overlay_wire_color_get(v3d, pd, ob, use_coloring, &rim_col, &wire_col); DRW_shgroup_uniform_vec3(shgrp, "wireColor", wire_col, 1); DRW_shgroup_uniform_vec3(shgrp, "rimColor", rim_col, 1); + DRW_shgroup_stencil_mask(shgrp, + (is_xray && (is_wire || !pd->clear_stencil)) ? 0x00 : 0xFF); } if (use_sculpt_pbvh) { @@ -421,35 +438,6 @@ static void overlay_cache_populate(void *vedata, Object *ob) (*dupli_data)->shgrp = shgrp; (*dupli_data)->geom = geom; } - - if (is_wire && shgrp != NULL) { - /* If object is wireframe, don't try to use stencil test. */ - DRW_shgroup_state_disable(shgrp, DRW_STATE_STENCIL_EQUAL); - - if (ob->dtx & OB_DRAWXRAY) { - DRW_shgroup_state_disable(shgrp, DRW_STATE_DEPTH_LESS_EQUAL); - } - } - else if ((ob->dtx & OB_DRAWXRAY) && shgrp != NULL) { - pd->ghost_stencil_test = true; - } - } - } -} - -static void overlay_cache_finish(void *vedata) -{ - OVERLAY_Data *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 && !XRAY_FLAG_ENABLED(v3d)) { - if (stl->g_data->ghost_stencil_test) { - DRW_pass_state_add(psl->face_wireframe_pass, DRW_STATE_STENCIL_EQUAL); } } } @@ -464,9 +452,18 @@ static void overlay_draw_scene(void *vedata) if (DRW_state_is_fbo()) { GPU_framebuffer_bind(dfbl->default_fb); + + /* In material/rendered mode, Stencil has not be rendered correctly. + * Clear it to avoid problems.*/ + if (stl->g_data->clear_stencil) { + GPU_framebuffer_clear_stencil(dfbl->default_fb, 0xFF); + } } DRW_draw_pass(psl->face_orientation_pass); + /* Do a depth prepass to lower the depth where the xray wire objects can pass through */ + DRW_draw_pass(psl->face_wireframe_xray_pass); + /* This is replaced by the next code block */ // MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl); @@ -479,9 +476,20 @@ static void overlay_draw_scene(void *vedata) GPU_framebuffer_blit( dfbl->default_fb, 0, dfbl->multisample_fb, 0, GPU_DEPTH_BIT | GPU_STENCIL_BIT); DRW_stats_query_end(); + + /* Redo the prepass so we ge nice AA lines. */ + DRW_draw_pass(psl->face_wireframe_xray_pass); } DRW_view_set_active(stl->g_data->view_wires); + + DRW_pass_state_remove(psl->face_wireframe_xray_pass, + DRW_STATE_DEPTH_GREATER_EQUAL | DRW_STATE_STENCIL_NEQUAL); + DRW_pass_state_add(psl->face_wireframe_xray_pass, + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_STENCIL_ALWAYS); + DRW_draw_pass(psl->face_wireframe_xray_pass); + DRW_draw_pass(psl->face_wireframe_pass); DRW_view_set_active(NULL); @@ -519,7 +527,7 @@ DrawEngineType draw_engine_overlay_type = { &overlay_engine_free, &overlay_cache_init, &overlay_cache_populate, - &overlay_cache_finish, + NULL, NULL, &overlay_draw_scene, NULL,