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
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2020-06-22 20:57:53 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-06-22 20:57:53 +0300
commit15dda0115c783805753119984decb4d9249b1f01 (patch)
treec2d674f83d02edd6eb694c2510dbe1aaff510fe7 /source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl
parent3cea42ce29cb986cf9614d9b712d72915d52e546 (diff)
UI: Widget: Replace geometry by fragment shader drawing
This means all the antiailasing is done inside the fragment shader. We use a Signed Distance Field to draw the 2D rounded boxes. This ensure the best quality for AA. This reduce the averge Batch for widget to 16 verts instead of ~600 and reduce overshading a lot. Theme Emboss alpha and tria alpha needs to be changed after this refactor. The shadow drawing is left unchanged and still use geometry. Reviewed By: Severin Differential Revision: https://developer.blender.org/D7833
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.glsl81
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);
}