diff options
Diffstat (limited to 'source/blender/draw/modes/shaders/object_outline_detect_frag.glsl')
-rw-r--r-- | source/blender/draw/modes/shaders/object_outline_detect_frag.glsl | 35 |
1 files changed, 26 insertions, 9 deletions
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 a7e68485b86..771b6bcdc2e 100644 --- a/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl +++ b/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl @@ -40,8 +40,8 @@ void main() #ifdef GL_ARB_texture_gather vec2 texel_size = 1.0 / vec2(textureSize(outlineId, 0).xy); - vec2 uv1 = gl_FragCoord.xy * texel_size - texel_size; - vec2 uv2 = gl_FragCoord.xy * texel_size; + vec2 uv1 = ceil(gl_FragCoord.xy) * texel_size - texel_size; + vec2 uv2 = ceil(gl_FragCoord.xy) * texel_size; /* Samples order is CW starting from top left. */ uvec4 tmp1 = textureGather(outlineId, uv1); @@ -52,19 +52,36 @@ void main() #else uvec4 id; uint ref_id = texelFetch(outlineId, texel, 0).r; - id.x = texelFetchOffset(outlineId, texel, 0, ivec2( 1, 0)).r; - id.y = texelFetchOffset(outlineId, texel, 0, ivec2( 0, 1)).r; - id.z = texelFetchOffset(outlineId, texel, 0, ivec2(-1, 0)).r; - id.w = texelFetchOffset(outlineId, texel, 0, ivec2( 0, -1)).r; + id.x = texelFetchOffset(outlineId, texel, 0, ivec2(-1, 0)).r; + id.y = texelFetchOffset(outlineId, texel, 0, ivec2( 0, -1)).r; + id.z = texelFetchOffset(outlineId, texel, 0, ivec2( 0, 1)).r; + id.w = texelFetchOffset(outlineId, texel, 0, ivec2( 1, 0)).r; #endif - float ref_depth = texelFetch(outlineDepth, texel, 0).r; - float scene_depth = texelFetch(sceneDepth, texel, 0).r; + bool outline = any(notEqual(id, uvec4(ref_id))); + + ivec2 depth_texel = texel; + /* If texel is an outline but has no valid id ... + * replace id and depth texel by a valid one. + * This keeps the outline thickness consistent everywhere. */ + if (ref_id == 0u && outline) { + depth_texel = (id.x != 0u) ? texel + ivec2(-1, 0) : depth_texel; + depth_texel = (id.y != 0u) ? texel + ivec2( 0, -1) : depth_texel; + depth_texel = (id.z != 0u) ? texel + ivec2( 0, 1) : depth_texel; + depth_texel = (id.w != 0u) ? texel + ivec2( 1, 0) : depth_texel; + + ref_id = (id.x != 0u) ? id.x : ref_id; + ref_id = (id.y != 0u) ? id.y : ref_id; + ref_id = (id.z != 0u) ? id.z : ref_id; + ref_id = (id.w != 0u) ? id.w : ref_id; + } + + float ref_depth = texelFetch(outlineDepth, depth_texel, 0).r; + float scene_depth = texelFetch(sceneDepth, depth_texel, 0).r; /* Avoid bad cases of zfighting for occlusion only. */ const float epsilon = 3.0 / 8388608.0; bool occluded = (ref_depth > scene_depth + epsilon); - bool outline = any(notEqual(id, uvec4(ref_id))); FragColor = convert_id_to_color(int(ref_id)); FragColor.a *= (occluded) ? alphaOcclu : 1.0; |