From ed21506f2634a863c4ebfddf75754c9adb66ca3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Mon, 24 Feb 2020 01:19:08 +0100 Subject: Overlay: Remove Xray dithering noise We now use a better smoother technique that uses correct alpha blending. This is possible now that we render overlays in a separate buffer. --- source/blender/draw/CMakeLists.txt | 1 + .../draw/engines/overlay/overlay_antialiasing.c | 55 +++++++++++++++++++++- .../blender/draw/engines/overlay/overlay_engine.c | 3 ++ .../blender/draw/engines/overlay/overlay_private.h | 6 +++ .../blender/draw/engines/overlay/overlay_shader.c | 14 ++++++ .../engines/overlay/shaders/xray_fade_frag.glsl | 15 ++++++ .../draw/engines/workbench/workbench_forward.c | 2 +- 7 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 source/blender/draw/engines/overlay/shaders/xray_fade_frag.glsl (limited to 'source/blender') diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 07a8bba5023..e130ade91cf 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -392,6 +392,7 @@ data_to_c_simple(engines/overlay/shaders/sculpt_mask_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/volume_velocity_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/wireframe_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/wireframe_frag.glsl SRC) +data_to_c_simple(engines/overlay/shaders/xray_fade_frag.glsl SRC) list(APPEND INC ) diff --git a/source/blender/draw/engines/overlay/overlay_antialiasing.c b/source/blender/draw/engines/overlay/overlay_antialiasing.c index b8e39e3f0a9..0b7637aa098 100644 --- a/source/blender/draw/engines/overlay/overlay_antialiasing.c +++ b/source/blender/draw/engines/overlay/overlay_antialiasing.c @@ -68,7 +68,10 @@ void OVERLAY_antialiasing_init(OVERLAY_Data *vedata) DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); /* Small texture which will have very small impact on rendertime. */ - DRW_texture_ensure_2d(&txl->dummy_depth_tx, 1, 1, GPU_DEPTH_COMPONENT24, 0); + if (txl->dummy_depth_tx == NULL) { + float pixel[1] = {1.0f}; + txl->dummy_depth_tx = DRW_texture_create_2d(1, 1, GPU_DEPTH_COMPONENT24, 0, pixel); + } if (!DRW_state_is_fbo()) { pd->antialiasing.enabled = false; @@ -110,6 +113,16 @@ void OVERLAY_antialiasing_init(OVERLAY_Data *vedata) GPU_ATTACHMENT_TEXTURE(color_tex), GPU_ATTACHMENT_TEXTURE(line_tex), }); + + if (pd->xray_enabled) { + DRW_texture_ensure_fullscreen_2d(&txl->temp_depth_tx, GPU_DEPTH24_STENCIL8, 0); + + GPU_framebuffer_ensure_config(&fbl->overlay_xray_depth_copy_fb, + { + GPU_ATTACHMENT_TEXTURE(txl->temp_depth_tx), + GPU_ATTACHMENT_NONE, + }); + } } void OVERLAY_antialiasing_cache_init(OVERLAY_Data *vedata) @@ -137,6 +150,18 @@ void OVERLAY_antialiasing_cache_init(OVERLAY_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "lineTex", &txl->overlay_line_tx); DRW_shgroup_call_procedural_triangles(grp, NULL, 1); } + + /* A bit out of place... not related to antialiasing. */ + if (pd->xray_enabled) { + DRW_PASS_CREATE(psl->xray_fade_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_MUL); + + sh = OVERLAY_shader_xray_fade(); + grp = DRW_shgroup_create(sh, psl->xray_fade_ps); + DRW_shgroup_uniform_texture_ref(grp, "depthTex", &dtxl->depth); + DRW_shgroup_uniform_texture_ref(grp, "xrayDepthTex", &txl->temp_depth_tx); + DRW_shgroup_uniform_float_copy(grp, "opacity", 1.0f - pd->xray_opacity); + DRW_shgroup_call_procedural_triangles(grp, NULL, 1); + } } void OVERLAY_antialiasing_cache_finish(OVERLAY_Data *vedata) @@ -187,6 +212,34 @@ void OVERLAY_antialiasing_start(OVERLAY_Data *vedata) } } +void OVERLAY_xray_depth_copy(OVERLAY_Data *vedata) +{ + OVERLAY_FramebufferList *fbl = vedata->fbl; + OVERLAY_PrivateData *pd = vedata->stl->pd; + + if (DRW_state_is_fbo() && pd->xray_enabled) { + if (pd->xray_opacity > 0.0f) { + /* We copy the depth of the rendered geometry to be able to compare to the overlays depth. */ + GPU_framebuffer_blit( + fbl->overlay_default_fb, 0, fbl->overlay_xray_depth_copy_fb, 0, GPU_DEPTH_BIT); + } + /* We then clear to not occlude the overlays directly. */ + GPU_framebuffer_bind(fbl->overlay_default_fb); + GPU_framebuffer_clear_depth(fbl->overlay_default_fb, 1.0f); + } +} + +void OVERLAY_xray_fade_draw(OVERLAY_Data *vedata) +{ + OVERLAY_PassList *psl = vedata->psl; + OVERLAY_PrivateData *pd = vedata->stl->pd; + + if (DRW_state_is_fbo() && pd->xray_enabled && pd->xray_opacity > 0.0f) { + /* Partially occlude overlays using the geometry depth pass. */ + DRW_draw_pass(psl->xray_fade_ps); + } +} + void OVERLAY_antialiasing_end(OVERLAY_Data *vedata) { OVERLAY_PassList *psl = vedata->psl; diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c index c41fc274f17..a8d2c4c6cf0 100644 --- a/source/blender/draw/engines/overlay/overlay_engine.c +++ b/source/blender/draw/engines/overlay/overlay_engine.c @@ -75,6 +75,7 @@ static void OVERLAY_engine_init(void *vedata) pd->wireframe_mode = (v3d->shading.type == OB_WIRE); pd->clipping_state = RV3D_CLIPPING_ENABLED(v3d, rv3d) ? DRW_STATE_CLIP_PLANES : 0; + pd->xray_opacity = XRAY_ALPHA(v3d); 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); @@ -410,6 +411,7 @@ static void OVERLAY_draw_scene(void *vedata) } OVERLAY_outline_draw(vedata); + OVERLAY_xray_depth_copy(vedata); if (DRW_state_is_fbo()) { GPU_framebuffer_bind(fbl->overlay_default_fb); @@ -433,6 +435,7 @@ static void OVERLAY_draw_scene(void *vedata) GPU_framebuffer_bind(fbl->overlay_color_only_fb); } + OVERLAY_xray_fade_draw(vedata); OVERLAY_grid_draw(vedata); if (DRW_state_is_fbo()) { diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h index 4cd3877f21f..185df723301 100644 --- a/source/blender/draw/engines/overlay/overlay_private.h +++ b/source/blender/draw/engines/overlay/overlay_private.h @@ -35,6 +35,7 @@ typedef struct OVERLAY_FramebufferList { struct GPUFrameBuffer *overlay_color_only_fb; struct GPUFrameBuffer *overlay_in_front_fb; struct GPUFrameBuffer *overlay_line_in_front_fb; + struct GPUFrameBuffer *overlay_xray_depth_copy_fb; struct GPUFrameBuffer *outlines_prepass_fb; struct GPUFrameBuffer *outlines_resolve_fb; } OVERLAY_FramebufferList; @@ -94,6 +95,7 @@ typedef struct OVERLAY_PassList { DRWPass *sculpt_mask_ps; DRWPass *wireframe_ps; DRWPass *wireframe_xray_ps; + DRWPass *xray_fade_ps; } OVERLAY_PassList; /* Data used by GLSL shader. To be used as UBO. */ @@ -272,6 +274,7 @@ typedef struct OVERLAY_PrivateData { bool hide_overlays; bool xray_enabled; bool xray_enabled_and_not_wire; + float xray_opacity; short v3d_flag; /* TODO move to View3DOverlay */ short v3d_gridflag; /* TODO move to View3DOverlay */ DRWState clipping_state; @@ -391,6 +394,8 @@ void OVERLAY_antialiasing_cache_init(OVERLAY_Data *vedata); void OVERLAY_antialiasing_cache_finish(OVERLAY_Data *vedata); void OVERLAY_antialiasing_start(OVERLAY_Data *vedata); void OVERLAY_antialiasing_end(OVERLAY_Data *vedata); +void OVERLAY_xray_fade_draw(OVERLAY_Data *vedata); +void OVERLAY_xray_depth_copy(OVERLAY_Data *vedata); bool OVERLAY_armature_is_pose_mode(Object *ob, const struct DRWContextState *draw_ctx); void OVERLAY_armature_cache_init(OVERLAY_Data *vedata); @@ -579,6 +584,7 @@ GPUShader *OVERLAY_shader_sculpt_mask(void); GPUShader *OVERLAY_shader_volume_velocity(bool use_needle); GPUShader *OVERLAY_shader_wireframe(void); GPUShader *OVERLAY_shader_wireframe_select(void); +GPUShader *OVERLAY_shader_xray_fade(void); OVERLAY_InstanceFormats *OVERLAY_shader_instance_formats_get(void); diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c index 6b8c5b23e58..d33ef239198 100644 --- a/source/blender/draw/engines/overlay/overlay_shader.c +++ b/source/blender/draw/engines/overlay/overlay_shader.c @@ -103,6 +103,7 @@ extern char datatoc_sculpt_mask_vert_glsl[]; extern char datatoc_volume_velocity_vert_glsl[]; extern char datatoc_wireframe_vert_glsl[]; extern char datatoc_wireframe_frag_glsl[]; +extern char datatoc_xray_fade_frag_glsl[]; extern char datatoc_gpu_shader_depth_only_frag_glsl[]; extern char datatoc_gpu_shader_point_varying_color_frag_glsl[]; @@ -179,6 +180,7 @@ typedef struct OVERLAY_Shaders { GPUShader *volume_velocity_sh; GPUShader *wireframe_select; GPUShader *wireframe; + GPUShader *xray_fade; } OVERLAY_Shaders; static struct { @@ -1265,6 +1267,18 @@ GPUShader *OVERLAY_shader_wireframe(void) return sh_data->wireframe; } +GPUShader *OVERLAY_shader_xray_fade(void) +{ + OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; + if (!sh_data->xray_fade) { + sh_data->xray_fade = GPU_shader_create_from_arrays({ + .vert = (const char *[]){datatoc_common_fullscreen_vert_glsl, NULL}, + .frag = (const char *[]){datatoc_xray_fade_frag_glsl, NULL}, + }); + } + return sh_data->xray_fade; +} + static OVERLAY_InstanceFormats g_formats = {NULL}; OVERLAY_InstanceFormats *OVERLAY_shader_instance_formats_get(void) diff --git a/source/blender/draw/engines/overlay/shaders/xray_fade_frag.glsl b/source/blender/draw/engines/overlay/shaders/xray_fade_frag.glsl new file mode 100644 index 00000000000..b6a5c8d895c --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/xray_fade_frag.glsl @@ -0,0 +1,15 @@ + +uniform sampler2D depthTex; +uniform sampler2D xrayDepthTex; +uniform float opacity; + +in vec4 uvcoordsvar; + +out vec4 fragColor; + +void main() +{ + float depth = texture(depthTex, uvcoordsvar.xy).r; + float depth_xray = texture(xrayDepthTex, uvcoordsvar.xy).r; + fragColor = vec4((depth < 1.0 && depth > depth_xray) ? opacity : 1.0); +} diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index b8e9f9b8428..fff01f9618c 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -460,7 +460,7 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) int state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS; psl->checker_depth_pass = DRW_pass_create("Checker Depth", state); grp = DRW_shgroup_create(e_data.checker_depth_sh, psl->checker_depth_pass); - DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); + // DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); DRW_shgroup_uniform_float_copy(grp, "threshold", blend_threshold); DRW_shgroup_uniform_float_copy(grp, "offset", noise_offset); } -- cgit v1.2.3