diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index aee443895bf..1ef3737aab1 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -54,11 +54,13 @@ typedef struct OBJECT_PassList { struct DRWPass *non_meshes; struct DRWPass *ob_center; struct DRWPass *outlines; + struct DRWPass *outlines_search; struct DRWPass *outlines_expand; - struct DRWPass *outlines_blur1; - struct DRWPass *outlines_blur2; - struct DRWPass *outlines_blur3; - struct DRWPass *outlines_blur4; + struct DRWPass *outlines_fade1; + struct DRWPass *outlines_fade2; + struct DRWPass *outlines_fade3; + struct DRWPass *outlines_fade4; + struct DRWPass *outlines_fade5; struct DRWPass *outlines_resolve; struct DRWPass *bone_solid; struct DRWPass *bone_wire; @@ -149,7 +151,7 @@ static struct { static struct { struct GPUShader *outline_resolve_sh; - struct GPUShader *outline_expand_sh; + struct GPUShader *outline_detect_sh; struct GPUShader *outline_fade_sh; } e_data = {NULL}; /* Engine data */ @@ -178,8 +180,8 @@ static void OBJECT_engine_init(void) e_data.outline_resolve_sh = DRW_shader_create_fullscreen(datatoc_object_outline_resolve_frag_glsl, NULL); } - if (!e_data.outline_expand_sh) { - e_data.outline_expand_sh = DRW_shader_create_fullscreen(datatoc_object_outline_detect_frag_glsl, NULL); + if (!e_data.outline_detect_sh) { + e_data.outline_detect_sh = DRW_shader_create_fullscreen(datatoc_object_outline_detect_frag_glsl, NULL); } if (!e_data.outline_fade_sh) { @@ -191,8 +193,8 @@ static void OBJECT_engine_free(void) { if (e_data.outline_resolve_sh) DRW_shader_free(e_data.outline_resolve_sh); - if (e_data.outline_expand_sh) - DRW_shader_free(e_data.outline_expand_sh); + if (e_data.outline_detect_sh) + DRW_shader_free(e_data.outline_detect_sh); if (e_data.outline_fade_sh) DRW_shader_free(e_data.outline_fade_sh); } @@ -233,46 +235,79 @@ static void OBJECT_cache_init(void) { DRWState state = DRW_STATE_WRITE_COLOR; - psl->outlines_expand = DRW_pass_create("Outlines Expand Pass", state); - struct Batch *quad = DRW_cache_fullscreen_quad_get(); static float alphaOcclu = 0.35f; - static float alphaNear = 0.75f; - static float alphaFar = 0.5f; + static float one = 1.0f; + static float alpha1 = 5.0f / 6.0f; + static float alpha2 = 4.0f / 5.0f; + static float alpha3 = 3.0f / 4.0f; + static float alpha4 = 2.0f / 3.0f; + static float alpha5 = 1.0f / 2.0f; + static bool bTrue = true; + static bool bFalse = false; - DRWShadingGroup *grp = DRW_shgroup_create(e_data.outline_expand_sh, psl->outlines_expand); + psl->outlines_search = DRW_pass_create("Outlines Expand Pass", state); + + DRWShadingGroup *grp = DRW_shgroup_create(e_data.outline_detect_sh, psl->outlines_search); DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_color_tx, 0); DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1); DRW_shgroup_uniform_buffer(grp, "sceneDepth", &dtxl->depth, 2); DRW_shgroup_uniform_float(grp, "alphaOcclu", &alphaOcclu, 1); + DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); DRW_shgroup_call_add(grp, quad, NULL); - psl->outlines_blur1 = DRW_pass_create("Outlines Blur 1 Pass", state); + psl->outlines_expand = DRW_pass_create("Outlines Expand Pass", state); - grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_blur1); + grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_expand); DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_blur_tx, 0); - DRW_shgroup_uniform_float(grp, "alpha", &alphaNear, 1); + DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1); + DRW_shgroup_uniform_float(grp, "alpha", &one, 1); + DRW_shgroup_uniform_bool(grp, "doExpand", &bTrue, 1); DRW_shgroup_call_add(grp, quad, NULL); - psl->outlines_blur2 = DRW_pass_create("Outlines Blur 2 Pass", state); + psl->outlines_fade1 = DRW_pass_create("Outlines Fade 1 Pass", state); - grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_blur2); + grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_fade1); DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_color_tx, 0); - DRW_shgroup_uniform_float(grp, "alpha", &alphaNear, 1); + DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1); + DRW_shgroup_uniform_float(grp, "alpha", &alpha1, 1); + DRW_shgroup_uniform_bool(grp, "doExpand", &bFalse, 1); DRW_shgroup_call_add(grp, quad, NULL); - psl->outlines_blur3 = DRW_pass_create("Outlines Blur 3 Pass", state); + psl->outlines_fade2 = DRW_pass_create("Outlines Fade 2 Pass", state); - grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_blur3); + grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_fade2); DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_blur_tx, 0); - DRW_shgroup_uniform_float(grp, "alpha", &alphaFar, 1); + DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1); + DRW_shgroup_uniform_float(grp, "alpha", &alpha2, 1); + DRW_shgroup_uniform_bool(grp, "doExpand", &bFalse, 1); DRW_shgroup_call_add(grp, quad, NULL); - psl->outlines_blur4 = DRW_pass_create("Outlines Blur 4 Pass", state); + psl->outlines_fade3 = DRW_pass_create("Outlines Fade 3 Pass", state); - grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_blur4); + grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_fade3); DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_color_tx, 0); - DRW_shgroup_uniform_float(grp, "alpha", &alphaFar, 1); + DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1); + DRW_shgroup_uniform_float(grp, "alpha", &alpha3, 1); + DRW_shgroup_uniform_bool(grp, "doExpand", &bFalse, 1); + DRW_shgroup_call_add(grp, quad, NULL); + + psl->outlines_fade4 = DRW_pass_create("Outlines Fade 4 Pass", state); + + grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_fade4); + DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_blur_tx, 0); + DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1); + DRW_shgroup_uniform_float(grp, "alpha", &alpha4, 1); + DRW_shgroup_uniform_bool(grp, "doExpand", &bFalse, 1); + DRW_shgroup_call_add(grp, quad, NULL); + + psl->outlines_fade5 = DRW_pass_create("Outlines Fade 5 Pass", state); + + grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_fade5); + DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_color_tx, 0); + DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1); + DRW_shgroup_uniform_float(grp, "alpha", &alpha5, 1); + DRW_shgroup_uniform_bool(grp, "doExpand", &bFalse, 1); DRW_shgroup_call_add(grp, quad, NULL); } @@ -284,7 +319,6 @@ static void OBJECT_cache_init(void) DRWShadingGroup *grp = DRW_shgroup_create(e_data.outline_resolve_sh, psl->outlines_resolve); DRW_shgroup_uniform_buffer(grp, "outlineBluredColor", &txl->outlines_blur_tx, 0); - DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1); DRW_shgroup_call_add(grp, quad, NULL); } @@ -743,39 +777,53 @@ static void OBJECT_draw_scene(void) OBJECT_Data *ved = DRW_viewport_engine_data_get("ObjectMode"); OBJECT_PassList *psl = ved->psl; OBJECT_FramebufferList *fbl = ved->fbl; + OBJECT_TextureList *txl = ved->txl; DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - DRW_draw_pass(psl->bone_wire); - DRW_draw_pass(psl->bone_solid); - DRW_draw_pass(psl->non_meshes); - DRW_draw_pass(psl->ob_center); - /* Render filled polygon on a separate framebuffer */ DRW_framebuffer_bind(fbl->outlines); DRW_framebuffer_clear(true, true, false, clearcol, 1.0f); DRW_draw_pass(psl->outlines); - /* Expand filled color by 1px and modulate if occluded */ + /* detach textures */ + DRW_framebuffer_texture_detach(txl->outlines_depth_tx); + + /* Search outline pixels */ DRW_framebuffer_bind(fbl->blur); - DRW_draw_pass(psl->outlines_expand); + DRW_draw_pass(psl->outlines_search); /* Expand and fade gradually */ DRW_framebuffer_bind(fbl->outlines); - DRW_draw_pass(psl->outlines_blur1); + DRW_draw_pass(psl->outlines_expand); DRW_framebuffer_bind(fbl->blur); - DRW_draw_pass(psl->outlines_blur2); + DRW_draw_pass(psl->outlines_fade1); - // DRW_framebuffer_bind(fbl->outlines); - // DRW_draw_pass(psl->outlines_blur3); + DRW_framebuffer_bind(fbl->outlines); + DRW_draw_pass(psl->outlines_fade2); - // DRW_framebuffer_bind(fbl->blur); - // DRW_draw_pass(psl->outlines_blur4); + DRW_framebuffer_bind(fbl->blur); + DRW_draw_pass(psl->outlines_fade3); + + DRW_framebuffer_bind(fbl->outlines); + DRW_draw_pass(psl->outlines_fade4); + + DRW_framebuffer_bind(fbl->blur); + DRW_draw_pass(psl->outlines_fade5); + + /* reattach */ + DRW_framebuffer_texture_attach(fbl->outlines, txl->outlines_depth_tx, 0); /* Combine with scene buffer */ DRW_framebuffer_bind(dfbl->default_fb); DRW_draw_pass(psl->outlines_resolve); + + /* This needs to be drawn after the oultine */ + DRW_draw_pass(psl->bone_wire); + DRW_draw_pass(psl->bone_solid); + DRW_draw_pass(psl->non_meshes); + DRW_draw_pass(psl->ob_center); } void OBJECT_collection_settings_create(CollectionEngineSettings *ces) diff --git a/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl b/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl index fc40a7dd1d1..0d6173cf4f2 100644 --- a/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl +++ b/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl @@ -8,14 +8,24 @@ uniform sampler2D outlineDepth; uniform sampler2D sceneDepth; uniform float alphaOcclu; +uniform vec2 viewportSize; -void search_outline(ivec2 uv, ivec2 offset, vec4 ref_col, inout bool outline) +void search_outline(ivec2 uv, ivec2 offset, vec4 ref_col, inout bool ref_occlu, inout bool outline) { if (!outline) { vec4 color = texelFetchOffset(outlineColor, uv, 0, offset).rgba; if (color != ref_col) { outline = true; } + else { + float depth = texelFetchOffset(outlineDepth, uv, 0, offset).r; + float scene_depth = texelFetchOffset(sceneDepth, uv, 0, offset).r; + bool occlu = (depth > scene_depth); + + if (occlu != ref_occlu && !ref_occlu) { + outline = true; + } + } } } @@ -24,25 +34,35 @@ void main() ivec2 uv = ivec2(gl_FragCoord.xy); vec4 ref_col = texelFetch(outlineColor, uv, 0).rgba; + float depth = texelFetch(outlineDepth, uv, 0).r; + /* Modulate color if occluded */ + float scene_depth = texelFetch(sceneDepth, uv, 0).r; + + bool ref_occlu = (depth > scene_depth); + bool outline = false; - search_outline(uv, ivec2( 1, 0), ref_col, outline); - search_outline(uv, ivec2( 0, 1), ref_col, outline); - search_outline(uv, ivec2(-1, 0), ref_col, outline); - search_outline(uv, ivec2( 0, -1), ref_col, outline); + if (float(uv.x) < viewportSize.x - 1.0) + search_outline(uv, ivec2( 1, 0), ref_col, ref_occlu, outline); + + if (float(uv.y) < viewportSize.x - 1.0) + search_outline(uv, ivec2( 0, 1), ref_col, ref_occlu, outline); + + if (float(uv.x) > 0) + search_outline(uv, ivec2(-1, 0), ref_col, ref_occlu, outline); + + if (float(uv.y) > 0) + search_outline(uv, ivec2( 0, -1), ref_col, ref_occlu, outline); + + FragColor = ref_col; /* We Hit something ! */ if (outline) { - FragColor = ref_col; - /* Modulate color if occluded */ - float depth = texelFetch(outlineDepth, uv, 0).r; - float scene_depth = texelFetch(sceneDepth, uv, 0).r; - /* TODO bias in linear depth not exponential */ - if (depth > scene_depth) { + if (ref_occlu) { FragColor.a *= alphaOcclu; } } else { - FragColor = vec4(0.0); + FragColor.a = 0.0; } } diff --git a/source/blender/draw/modes/shaders/object_outline_expand_frag.glsl b/source/blender/draw/modes/shaders/object_outline_expand_frag.glsl index 73b9e7f1f0c..b57c4f5ea0e 100644 --- a/source/blender/draw/modes/shaders/object_outline_expand_frag.glsl +++ b/source/blender/draw/modes/shaders/object_outline_expand_frag.glsl @@ -4,66 +4,42 @@ in vec4 uvcoordsvar; out vec4 FragColor; uniform sampler2D outlineColor; -#ifdef DEPTH_TEST uniform sampler2D outlineDepth; -uniform sampler2D sceneDepth; -#endif uniform float alpha; +uniform bool doExpand; -#define ALPHA_OCCLU 0.4 - -void search_outline(ivec2 uv, ivec2 offset, inout float weight, inout vec4 col_accum) +void search_outline(ivec2 uv, ivec2 offset, inout bool found_edge) { - vec4 color = texelFetchOffset(outlineColor, uv, 0, offset).rgba; - if (color.a != 0.0) { -#ifdef DEPTH_TEST - /* Modulate color if occluded */ - /* TODO bias in linear depth not exponential */ - float depth = texelFetchOffset(outlineDepth, uv, 0, offset).r; - float scene_depth = texelFetchOffset(sceneDepth, uv, 0, offset).r; - if (depth > scene_depth) { - color *= ALPHA_OCCLU; + if (!found_edge) { + vec4 color = texelFetchOffset(outlineColor, uv, 0, offset).rgba; + if (color.a != 0.0) { + if (doExpand || color.a != 1.0) { + FragColor = color; + found_edge = true; + } } -#endif - col_accum += color; - weight += 1.0; } } void main() { ivec2 uv = ivec2(gl_FragCoord.xy); - // vec2 uv = uvcoordsvar.xy + 0.5 / viewportSize; FragColor = texelFetch(outlineColor, uv, 0).rgba; + float depth = texelFetch(outlineDepth, uv, 0).r; - if (FragColor.a != 0.0){ -#ifdef DEPTH_TEST - /* Modulate color if occluded */ - float depth = texelFetch(outlineDepth, uv, 0).r; - float scene_depth = texelFetch(sceneDepth, uv, 0).r; - /* TODO bias in linear depth not exponential */ - if (depth > scene_depth) { - FragColor *= ALPHA_OCCLU; - } -#endif + if (FragColor.a != 0.0 || (depth == 1.0 && !doExpand)) return; - } - float weight = 0.0; - vec4 col = vec4(0.0); - - search_outline(uv, ivec2( 1, 0), weight, col); - search_outline(uv, ivec2( 0, 1), weight, col); - search_outline(uv, ivec2(-1, 0), weight, col); - search_outline(uv, ivec2( 0, -1), weight, col); + bool found_edge = false; + search_outline(uv, ivec2( 1, 0), found_edge); + search_outline(uv, ivec2( 0, 1), found_edge); + search_outline(uv, ivec2(-1, 0), found_edge); + search_outline(uv, ivec2( 0, -1), found_edge); /* We Hit something ! */ - if (weight != 0.0) { - FragColor = col / weight; + if (found_edge) { + /* only change alpha */ FragColor.a *= alpha; } - else { - FragColor = vec4(0.0); - } } diff --git a/source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl b/source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl index 12f375369b8..3937828eca2 100644 --- a/source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl +++ b/source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl @@ -4,14 +4,8 @@ in vec4 uvcoordsvar; out vec4 FragColor; uniform sampler2D outlineBluredColor; -uniform sampler2D outlineDepth; void main() { FragColor = texture(outlineBluredColor, uvcoordsvar.st).rgba; - - /* Modulate fill color */ - // float depth = texture(outlineDepth, uvcoordsvar.st).r; - // if (depth != 1.0) - // FragColor.a *= 0.1; }