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
path: root/source
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2020-03-26 17:36:15 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-03-26 17:55:16 +0300
commite000dcb8490880d6d49aa91588c457612685e9f1 (patch)
treea1872556d19a2751455ab803cb13d00318ee63b8 /source
parent458f50ba73bcd233176f9afadc3273acf05e4f53 (diff)
Overlay: Wireframe: New method to avoid zfighting with geometry
This new method is only enabled if Overlay Smooth Wire is enabled. This method gives really nice results but has some downside: - Require a depth copy or loose the ability to write wire depth to the depth buffer and have correct depth ordering of wires. This patch use the former, with its associated cost. - Require some depth sampling and prevent early depth test (i.e: has some performance impact). - Has some relatively minor instability with geometry that are perpendicular to the view and intersecting with other geometry. Pros: - Compared to a fullpass approach this is surely going to have less performance impact and much higher quality. - Removes the additional vertex offset. (see T74961) - Fixes all half edges z-fighting. {F8428014} {F8428015} Reviewed By: brecht Differential Revision: https://developer.blender.org/D7233
Diffstat (limited to 'source')
-rw-r--r--source/blender/draw/engines/overlay/overlay_antialiasing.c50
-rw-r--r--source/blender/draw/engines/overlay/overlay_engine.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_private.h5
-rw-r--r--source/blender/draw/engines/overlay/overlay_shader.c19
-rw-r--r--source/blender/draw/engines/overlay/overlay_wireframe.c8
-rw-r--r--source/blender/draw/engines/overlay/shaders/wireframe_frag.glsl30
-rw-r--r--source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl9
7 files changed, 96 insertions, 27 deletions
diff --git a/source/blender/draw/engines/overlay/overlay_antialiasing.c b/source/blender/draw/engines/overlay/overlay_antialiasing.c
index 0b7637aa098..e13d27032d5 100644
--- a/source/blender/draw/engines/overlay/overlay_antialiasing.c
+++ b/source/blender/draw/engines/overlay/overlay_antialiasing.c
@@ -113,16 +113,6 @@ 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)
@@ -168,6 +158,7 @@ void OVERLAY_antialiasing_cache_finish(OVERLAY_Data *vedata)
{
OVERLAY_FramebufferList *fbl = vedata->fbl;
OVERLAY_TextureList *txl = vedata->txl;
+ OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
@@ -191,6 +182,22 @@ void OVERLAY_antialiasing_cache_finish(OVERLAY_Data *vedata)
GPU_ATTACHMENT_TEXTURE(dtxl->color_overlay),
GPU_ATTACHMENT_TEXTURE(txl->overlay_line_tx)});
}
+
+ pd->antialiasing.do_depth_copy = !DRW_pass_is_empty(psl->wireframe_ps) ||
+ (pd->xray_enabled && pd->xray_opacity > 0.0f);
+ pd->antialiasing.do_depth_infront_copy = !DRW_pass_is_empty(psl->wireframe_xray_ps);
+
+ const bool do_wireframe = pd->antialiasing.do_depth_copy ||
+ pd->antialiasing.do_depth_infront_copy;
+ if (pd->xray_enabled || do_wireframe) {
+ 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_start(OVERLAY_Data *vedata)
@@ -217,18 +224,31 @@ 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->antialiasing.do_depth_copy) {
+ /* 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);
+ }
+
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_depth_infront_copy(OVERLAY_Data *vedata)
+{
+ OVERLAY_FramebufferList *fbl = vedata->fbl;
+ OVERLAY_PrivateData *pd = vedata->stl->pd;
+
+ if (DRW_state_is_fbo() && pd->antialiasing.do_depth_infront_copy) {
+ /* We copy the depth of the rendered geometry to be able to compare to the overlays depth. */
+ GPU_framebuffer_blit(
+ fbl->overlay_in_front_fb, 0, fbl->overlay_xray_depth_copy_fb, 0, GPU_DEPTH_BIT);
+ }
+}
+
void OVERLAY_xray_fade_draw(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 adbcd3c7f28..97f6b91b7a9 100644
--- a/source/blender/draw/engines/overlay/overlay_engine.c
+++ b/source/blender/draw/engines/overlay/overlay_engine.c
@@ -466,6 +466,8 @@ static void OVERLAY_draw_scene(void *vedata)
OVERLAY_xray_fade_draw(vedata);
OVERLAY_grid_draw(vedata);
+ OVERLAY_xray_depth_infront_copy(vedata);
+
if (DRW_state_is_fbo()) {
GPU_framebuffer_bind(fbl->overlay_line_in_front_fb);
}
diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h
index 7cc83c76857..bd9583c6a5f 100644
--- a/source/blender/draw/engines/overlay/overlay_private.h
+++ b/source/blender/draw/engines/overlay/overlay_private.h
@@ -293,6 +293,8 @@ typedef struct OVERLAY_PrivateData {
struct {
bool enabled;
+ bool do_depth_copy;
+ bool do_depth_infront_copy;
} antialiasing;
struct {
bool show_handles;
@@ -411,6 +413,7 @@ 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);
+void OVERLAY_xray_depth_infront_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);
@@ -613,7 +616,7 @@ GPUShader *OVERLAY_shader_particle_shape(void);
GPUShader *OVERLAY_shader_pointcloud_dot(void);
GPUShader *OVERLAY_shader_sculpt_mask(void);
GPUShader *OVERLAY_shader_volume_velocity(bool use_needle);
-GPUShader *OVERLAY_shader_wireframe(void);
+GPUShader *OVERLAY_shader_wireframe(bool custom_bias);
GPUShader *OVERLAY_shader_wireframe_select(void);
GPUShader *OVERLAY_shader_xray_fade(void);
diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c
index 0b2f98294ec..8b70a0982af 100644
--- a/source/blender/draw/engines/overlay/overlay_shader.c
+++ b/source/blender/draw/engines/overlay/overlay_shader.c
@@ -192,7 +192,7 @@ typedef struct OVERLAY_Shaders {
GPUShader *volume_velocity_needle_sh;
GPUShader *volume_velocity_sh;
GPUShader *wireframe_select;
- GPUShader *wireframe;
+ GPUShader *wireframe[2];
GPUShader *xray_fade;
} OVERLAY_Shaders;
@@ -1372,24 +1372,29 @@ GPUShader *OVERLAY_shader_wireframe_select(void)
return sh_data->wireframe_select;
}
-GPUShader *OVERLAY_shader_wireframe(void)
+GPUShader *OVERLAY_shader_wireframe(bool custom_bias)
{
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->wireframe) {
- sh_data->wireframe = GPU_shader_create_from_arrays({
+ if (!sh_data->wireframe[custom_bias]) {
+ sh_data->wireframe[custom_bias] = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg->lib,
datatoc_common_view_lib_glsl,
datatoc_common_globals_lib_glsl,
datatoc_gpu_shader_common_obinfos_lib_glsl,
datatoc_wireframe_vert_glsl,
NULL},
- .frag = (const char *[]){datatoc_common_view_lib_glsl, datatoc_wireframe_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg->def, NULL},
+ .frag = (const char *[]){datatoc_common_view_lib_glsl,
+ datatoc_common_globals_lib_glsl,
+ datatoc_wireframe_frag_glsl,
+ NULL},
+ .defs = (const char *[]){sh_cfg->def,
+ custom_bias ? "#define CUSTOM_DEPTH_BIAS\n" : NULL,
+ NULL},
});
}
- return sh_data->wireframe;
+ return sh_data->wireframe[custom_bias];
}
GPUShader *OVERLAY_shader_xray_fade(void)
diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c
index 17b412b143c..27f3f4ae9af 100644
--- a/source/blender/draw/engines/overlay/overlay_wireframe.c
+++ b/source/blender/draw/engines/overlay/overlay_wireframe.c
@@ -51,6 +51,7 @@ void OVERLAY_wireframe_init(OVERLAY_Data *vedata)
void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
+ OVERLAY_TextureList *txl = vedata->txl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
const DRWContextState *draw_ctx = DRW_context_state_get();
DRWShadingGroup *grp = NULL;
@@ -66,12 +67,14 @@ void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata)
const bool use_select = (DRW_state_is_select() || DRW_state_is_depth());
GPUShader *wires_sh = use_select ? OVERLAY_shader_wireframe_select() :
- OVERLAY_shader_wireframe();
+ OVERLAY_shader_wireframe(pd->antialiasing.enabled);
for (int xray = 0; xray < (is_material_shmode ? 1 : 2); xray++) {
DRWState state = DRW_STATE_FIRST_VERTEX_CONVENTION | DRW_STATE_WRITE_COLOR |
DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
DRWPass *pass;
+ GPUTexture **depth_tx = (pd->xray_enabled || pd->xray_opacity > 0.0f) ? &txl->temp_depth_tx :
+ &txl->dummy_depth_tx;
if (xray == 0) {
DRW_PASS_CREATE(psl->wireframe_ps, state | pd->clipping_state);
@@ -85,6 +88,7 @@ void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata)
for (int use_coloring = 0; use_coloring < 2; use_coloring++) {
pd->wires_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass);
DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tx);
DRW_shgroup_uniform_float_copy(grp, "wireStepParam", pd->shdata.wire_step_param);
DRW_shgroup_uniform_bool_copy(grp, "useColoring", use_coloring);
DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0);
@@ -92,10 +96,12 @@ void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata)
DRW_shgroup_uniform_bool_copy(grp, "isRandomColor", is_random_color);
pd->wires_all_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass);
+ DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tx);
DRW_shgroup_uniform_float_copy(grp, "wireStepParam", 1.0f);
}
pd->wires_sculpt_grp[xray] = grp = DRW_shgroup_create(wires_sh, pass);
+ DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tx);
DRW_shgroup_uniform_float_copy(grp, "wireStepParam", 10.0f);
DRW_shgroup_uniform_bool_copy(grp, "useColoring", false);
}
diff --git a/source/blender/draw/engines/overlay/shaders/wireframe_frag.glsl b/source/blender/draw/engines/overlay/shaders/wireframe_frag.glsl
index edfe720da0c..b5442dc1b0b 100644
--- a/source/blender/draw/engines/overlay/shaders/wireframe_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/wireframe_frag.glsl
@@ -1,4 +1,7 @@
+/* Scene Depth texture copy for manual depth test. */
+uniform sampler2D depthTex;
+
flat in vec2 edgeStart;
#ifndef SELECT_EDGES
@@ -21,5 +24,32 @@ void main()
lineOutput = pack_line_data(gl_FragCoord.xy, edgeStart, edgePos);
fragColor.rgb = finalColor;
fragColor.a = 1.0;
+
+# ifdef CUSTOM_DEPTH_BIAS
+ vec2 dir = lineOutput.xy * 2.0 - 1.0;
+ bool dir_horiz = abs(dir.x) > abs(dir.y);
+
+ vec2 uv = gl_FragCoord.xy * sizeViewportInv.xy;
+ float depth_occluder = texture(depthTex, uv).r;
+ float depth_min = depth_occluder;
+
+ if (dir_horiz) {
+ depth_min = min(depth_min, texture(depthTex, uv + vec2(-sizeViewportInv.x, 0.0)).r);
+ depth_min = min(depth_min, texture(depthTex, uv + vec2(sizeViewportInv.x, 0.0)).r);
+ }
+ else {
+ depth_min = min(depth_min, texture(depthTex, uv + vec2(0, -sizeViewportInv.y)).r);
+ depth_min = min(depth_min, texture(depthTex, uv + vec2(0, sizeViewportInv.y)).r);
+ }
+
+ float delta = abs(depth_occluder - depth_min);
+
+ if (gl_FragCoord.z < (depth_occluder + delta) && gl_FragCoord.z > depth_occluder) {
+ gl_FragDepth = depth_occluder;
+ }
+ else {
+ gl_FragDepth = gl_FragCoord.z;
+ }
+# endif
#endif
}
diff --git a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl
index 001c128e4ac..3fefe2cc0bf 100644
--- a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl
@@ -110,19 +110,22 @@ void main()
vec3 V = (is_persp) ? normalize(ViewMatrixInverse[3].xyz - wpos) : ViewMatrixInverse[2].xyz;
float facing = dot(wnor, V);
+
+ gl_Position = point_world_to_ndc(wpos);
+
+#ifndef CUSTOM_DEPTH_BIAS
float facing_ratio = clamp(1.0 - facing * facing, 0.0, 1.0);
float flip = sign(facing); /* Flip when not facing the normal (i.e.: backfacing). */
float curvature = (1.0 - wd * 0.75); /* Avoid making things worse for curvy areas. */
vec3 wofs = wnor * (facing_ratio * curvature * flip);
wofs = normal_world_to_view(wofs);
- gl_Position = point_world_to_ndc(wpos);
-
/* Push vertex half a pixel (maximum) in normal direction. */
gl_Position.xy += wofs.xy * sizeViewportInv.xy * gl_Position.w;
/* Push the vertex towards the camera. Helps a bit. */
- gl_Position.z -= facing_ratio * curvature * 1.0e-5 * gl_Position.w;
+ gl_Position.z -= facing_ratio * curvature * 1.0e-6 * gl_Position.w;
+#endif
/* Convert to screen position [0..sizeVp]. */
edgeStart = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy;