Changeset View
Changeset View
Standalone View
Standalone View
src/scenegraph/shaders/shadowedborderrectangle.frag
- This file was moved from src/scenegraph/shadowedborderrectangle.frag.
1 | /* | 1 | /* | ||
---|---|---|---|---|---|
2 | * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl> | 2 | * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl> | ||
3 | * | 3 | * | ||
4 | * SPDX-License-Identifier: LGPL-2.0-or-later | 4 | * SPDX-License-Identifier: LGPL-2.0-or-later | ||
5 | */ | 5 | */ | ||
6 | 6 | | |||
7 | #line 7 | 7 | // See sdf.glsl for the SDF related functions. | ||
8 | | ||||
9 | // This is based on the 2D SDF functions provided by Inigo Quilez: | | |||
10 | // https://iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm | | |||
11 | 8 | | |||
12 | // This shader renders a rectangle with rounded corners and a shadow below it. | 9 | // This shader renders a rectangle with rounded corners and a shadow below it. | ||
13 | // In addition it renders a border around it. | 10 | // In addition it renders a border around it. | ||
14 | 11 | | |||
15 | uniform lowp float opacity; | 12 | uniform lowp float opacity; | ||
16 | uniform lowp float size; | 13 | uniform lowp float size; | ||
17 | uniform lowp float radius; | 14 | uniform lowp float radius; | ||
18 | uniform lowp vec4 color; | 15 | uniform lowp vec4 color; | ||
19 | uniform lowp vec4 shadowColor; | 16 | uniform lowp vec4 shadowColor; | ||
20 | uniform lowp vec2 offset; | 17 | uniform lowp vec2 offset; | ||
21 | uniform lowp vec2 aspect; | 18 | uniform lowp vec2 aspect; | ||
22 | uniform lowp float borderWidth; | 19 | uniform lowp float borderWidth; | ||
23 | uniform lowp vec4 borderColor; | 20 | uniform lowp vec4 borderColor; | ||
24 | 21 | | |||
22 | #ifdef CORE_PROFILE | ||||
23 | in lowp vec2 uv; | ||||
24 | out lowp vec4 out_color; | ||||
25 | #else | ||||
25 | varying lowp vec2 uv; | 26 | varying lowp vec2 uv; | ||
27 | #endif | ||||
26 | 28 | | |||
27 | const lowp float minimum_shadow_radius = 0.05; | 29 | const lowp float minimum_shadow_radius = 0.05; | ||
28 | const lowp float smoothing = 0.001; | | |||
29 | | ||||
30 | // Calculate the distance to a rectangle with rounded corners. | | |||
31 | // \param point The point to calculate the distance of. | | |||
32 | // \param rect The rectangle to calculate the distance of. | | |||
33 | // \param translation The amount of translation to apply to the rectangle. | | |||
34 | // \param radius A vec4 with the radius of each corner. Order is top right, bottom right, top left, bottom left. | | |||
35 | lowp float sdf_rounded_rectangle(in lowp vec2 point, in lowp vec2 rect, in lowp vec2 translation, in lowp vec4 radius) | | |||
36 | { | | |||
37 | radius.xy = (point.x > 0.0) ? radius.xy : radius.zw; | | |||
38 | radius.x = (point.y > 0.0) ? radius.x : radius.y; | | |||
39 | lowp vec2 d = abs(point - translation) - rect + radius.x; | | |||
40 | return min(max(d.x, d.y), 0.0) + length(max(d, 0.0)) - radius.x; | | |||
41 | } | | |||
42 | | ||||
43 | // Render an sdf value into a color. | | |||
44 | lowp vec4 sdf_render(in lowp float sdf, in lowp vec4 sourceColor, in lowp vec4 sdfColor, in lowp float sdfAlpha) | | |||
45 | { | | |||
46 | lowp float g = fwidth(sdf); | | |||
47 | return mix(sourceColor, sdfColor, sdfAlpha * (1.0 - smoothstep(smoothing - g, smoothing + g, sdf))); | | |||
48 | } | | |||
49 | 30 | | |||
50 | void main() | 31 | void main() | ||
51 | { | 32 | { | ||
52 | // Scaling factor that is the inverse of the amount of scaling applied to the geometry. | 33 | // Scaling factor that is the inverse of the amount of scaling applied to the geometry. | ||
53 | lowp float inverse_scale = 1.0 / (1.0 + size + length(offset) * 2.0); | 34 | lowp float inverse_scale = 1.0 / (1.0 + size + length(offset) * 2.0); | ||
54 | 35 | | |||
55 | // Correction factor to round the corners of a larger shadow. | 36 | // Correction factor to round the corners of a larger shadow. | ||
56 | // We want to account for size in regards to shadow radius, so that a larger shadow is | 37 | // We want to account for size in regards to shadow radius, so that a larger shadow is | ||
57 | // more rounded, but only if we are not already rounding the corners due to corner radius. | 38 | // more rounded, but only if we are not already rounding the corners due to corner radius. | ||
58 | lowp float size_factor = 0.5 * (minimum_shadow_radius / max(radius, minimum_shadow_radius)); | 39 | lowp float size_factor = 0.5 * (minimum_shadow_radius / max(radius, minimum_shadow_radius)); | ||
59 | | ||||
60 | lowp float shadow_radius = radius + size * size_factor; | 40 | lowp float shadow_radius = radius + size * size_factor; | ||
61 | 41 | | |||
62 | lowp vec4 col = vec4(0.0); | 42 | lowp vec4 col = vec4(0.0); | ||
63 | 43 | | |||
64 | // Calculate the shadow's distance field. | 44 | // Calculate the shadow's distance field. | ||
65 | lowp float shadow = sdf_rounded_rectangle(uv, aspect * inverse_scale, offset * 2.0 * inverse_scale, vec4(shadow_radius * inverse_scale)); | 45 | lowp float shadow = sdf_rounded_rectangle(uv - offset * 2.0 * inverse_scale, aspect * inverse_scale, vec4(shadow_radius * inverse_scale)); | ||
66 | // Render it, interpolating the color over the distance. | 46 | // Render it, interpolating the color over the distance. | ||
67 | col = mix(col, shadowColor * sign(size), 1.0 - smoothstep(-size * 0.5, size * 0.5, shadow)); | 47 | col = mix(col, shadowColor * sign(size), 1.0 - smoothstep(-size * 0.5, size * 0.5, shadow)); | ||
68 | 48 | | |||
69 | // Scale corrected corner radius | 49 | // Scale corrected corner radius | ||
70 | lowp vec4 corner_radius = vec4(radius * inverse_scale); | 50 | lowp vec4 corner_radius = vec4(radius * inverse_scale); | ||
71 | 51 | | |||
72 | // Calculate the outer rectangle distance field. | 52 | // Calculate the outer rectangle distance field. | ||
73 | lowp float outer_rect = sdf_rounded_rectangle(uv, aspect * inverse_scale, vec2(0.0), corner_radius); | 53 | lowp float outer_rect = sdf_rounded_rectangle(uv, aspect * inverse_scale, corner_radius); | ||
74 | 54 | | |||
75 | // First, remove anything that was rendered by the shadow if it is inside the rectangle. | 55 | // First, remove anything that was rendered by the shadow if it is inside the rectangle. | ||
76 | // This allows us to use colors with alpha without rendering artifacts. | 56 | // This allows us to use colors with alpha without rendering artifacts. | ||
77 | col = sdf_render(outer_rect, col, vec4(0.0), 1.0); | 57 | col = sdf_render(outer_rect, col, vec4(0.0)); | ||
78 | 58 | | |||
79 | // Then, render it again but this time with the proper color and properly alpha blended. | 59 | // Then, render it again but this time with the proper color and properly alpha blended. | ||
80 | col = sdf_render(outer_rect, col, borderColor, 1.0); | 60 | col = sdf_render(outer_rect, col, borderColor); | ||
81 | 61 | | |||
82 | // Calculate the inner rectangle distance field. | 62 | // Calculate the inner rectangle distance field. | ||
83 | // This uses a reduced corner radius because the inner corners need to be smaller than the outer corners. | 63 | // This uses a reduced corner radius because the inner corners need to be smaller than the outer corners. | ||
84 | lowp vec4 inner_radius = vec4((radius - borderWidth * 2.0) * inverse_scale); | 64 | lowp vec4 inner_radius = vec4((radius - borderWidth * 2.0) * inverse_scale); | ||
85 | lowp float inner_rect = sdf_rounded_rectangle(uv, (aspect - borderWidth * 2.0) * inverse_scale, vec2(0.0), inner_radius); | 65 | lowp float inner_rect = sdf_rounded_rectangle(uv, (aspect - borderWidth * 2.0) * inverse_scale, inner_radius); | ||
86 | 66 | | |||
87 | // Like above, but this time cut out the inner rectangle. | 67 | // Like above, but this time cut out the inner rectangle. | ||
88 | col = sdf_render(inner_rect, col, vec4(0.0), 1.0); | 68 | col = sdf_render(inner_rect, col, vec4(0.0)); | ||
89 | 69 | | |||
90 | // Finally, render the inner rectangle. | 70 | // Finally, render the inner rectangle. | ||
91 | col = sdf_render(inner_rect, col, color, 1.0); | 71 | col = sdf_render(inner_rect, col, color); | ||
92 | 72 | | |||
73 | #ifdef CORE_PROFILE | ||||
74 | out_color = col * opacity; | ||||
75 | #else | ||||
93 | gl_FragColor = col * opacity; | 76 | gl_FragColor = col * opacity; | ||
77 | #endif | ||||
94 | } | 78 | } |