diff options
Diffstat (limited to 'source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl')
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl | 81 |
1 files changed, 74 insertions, 7 deletions
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl index bdc87baf924..05fbae53e18 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl @@ -1,11 +1,62 @@ uniform vec3 checkerColorAndSize; -noperspective in vec4 finalColor; +noperspective in vec2 uvInterp; noperspective in float butCo; flat in float discardFac; +flat in float shadeTri; +flat in vec2 outRectSize; +flat in vec4 outRoundCorners; +noperspective in vec4 innerColor; +flat in vec4 borderColor; +flat in vec4 embossColor; +flat in float lineWidth; out vec4 fragColor; +vec3 compute_masks(vec2 uv) +{ + bool upper_half = uv.y > outRectSize.y * 0.5; + bool right_half = uv.x > outRectSize.x * 0.5; + float corner_rad; + + vec2 uv_sdf = uv; + if (right_half) { + uv_sdf.x = outRectSize.x - uv_sdf.x; + } + if (upper_half) { + uv_sdf.y = outRectSize.y - uv_sdf.y; + corner_rad = right_half ? outRoundCorners.z : outRoundCorners.w; + } + else { + corner_rad = right_half ? outRoundCorners.y : outRoundCorners.x; + } + + /* Signed distance field from the corner (in pixel). + * inner_sdf is sharp and outer_sdf is rounded. */ + uv_sdf -= corner_rad; + float inner_sdf = max(0.0, min(uv_sdf.x, uv_sdf.y)); + float outer_sdf = -length(min(uv_sdf, 0.0)); + float sdf = inner_sdf + outer_sdf + corner_rad; + + /* Fade emboss at the border. */ + float emboss_size = clamp((upper_half) ? 0.0 : (uv.x / corner_rad), 0.0, 1.0); + + /* Clamp line width to be at least 1px wide. This can happen if the projection matrix + * has been scaled (i.e: Node editor)... */ + float line_width = (lineWidth > 0.0) ? max(fwidth(uv.x), lineWidth) : 0.0; + + const float aa_radius = 0.5; + vec3 masks; + masks.x = smoothstep(-aa_radius, aa_radius, sdf); + masks.y = smoothstep(-aa_radius, aa_radius, sdf - line_width); + masks.z = smoothstep(-aa_radius, aa_radius, sdf + line_width * emboss_size); + + /* Compose masks together to avoid having too much alpha. */ + masks.zx = max(vec2(0.0), masks.zx - masks.xy); + + return masks; +} + vec4 do_checkerboard() { float size = checkerColorAndSize.z; @@ -25,16 +76,32 @@ void main() discard; } - fragColor = finalColor; - - if (butCo > 0.5) { - vec4 checker = do_checkerboard(); - fragColor = mix(checker, fragColor, fragColor.a); - } + vec3 masks = compute_masks(uvInterp); if (butCo > 0.0) { + /* Alpha checker widget. */ + if (butCo > 0.5) { + vec4 checker = do_checkerboard(); + fragColor = mix(checker, innerColor, innerColor.a); + } + else { + /* Set alpha to 1.0. */ + fragColor = innerColor; + } fragColor.a = 1.0; } + else { + /* Premultiply here. */ + fragColor = innerColor * vec4(innerColor.aaa, 1.0); + } + fragColor *= masks.y; + fragColor += masks.x * borderColor; + fragColor += masks.z * embossColor; + + /* Un-premult because the blend equation is already doing the mult. */ + if (fragColor.a > 0.0) { + fragColor.rgb /= fragColor.a; + } fragColor = blender_srgb_to_framebuffer_space(fragColor); } |