Changeset View
Changeset View
Standalone View
Standalone View
src/scenegraph/shaders/shadowedrectangle.frag
- This file was moved from src/scenegraph/shadowedrectangle_core.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 | // This is based on the 2D SDF functions provided by Inigo Quilez: | 7 | // See sdf.glsl for the SDF related functions. | ||
8 | // https://iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm | | |||
9 | 8 | | |||
10 | // 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. | ||
11 | 10 | | |||
12 | uniform lowp float opacity; | 11 | uniform lowp float opacity; | ||
13 | uniform lowp float size; | 12 | uniform lowp float size; | ||
14 | uniform lowp float radius; | 13 | uniform lowp float radius; | ||
15 | uniform lowp vec4 color; | 14 | uniform lowp vec4 color; | ||
16 | uniform lowp vec4 shadowColor; | 15 | uniform lowp vec4 shadowColor; | ||
17 | uniform lowp vec2 offset; | 16 | uniform lowp vec2 offset; | ||
18 | uniform lowp vec2 aspect; | 17 | uniform lowp vec2 aspect; | ||
19 | 18 | | |||
19 | #ifdef CORE_PROFILE | ||||
20 | in lowp vec2 uv; | 20 | in lowp vec2 uv; | ||
21 | | ||||
22 | out lowp vec4 out_color; | 21 | out lowp vec4 out_color; | ||
22 | #else | ||||
23 | varying lowp vec2 uv; | ||||
24 | #endif | ||||
23 | 25 | | |||
24 | const lowp float minimum_shadow_radius = 0.05; | 26 | const lowp float minimum_shadow_radius = 0.05; | ||
25 | 27 | | |||
26 | // Calculate the distance to a rectangle with rounded corners. | | |||
27 | // \param point The point to calculate the distance of. | | |||
28 | // \param rect The rectangle to calculate the distance of. | | |||
29 | // \param translation The amount of translation to apply to the rectangle. | | |||
30 | // \param radius A vec4 with the radius of each corner. Order is top right, bottom right, top left, bottom left. | | |||
31 | lowp float sdf_rounded_rectangle(in lowp vec2 point, in lowp vec2 rect, in lowp vec2 translation, in lowp vec4 radius) | | |||
32 | { | | |||
33 | radius.xy = (point.x > 0.0) ? radius.xy : radius.zw; | | |||
34 | radius.x = (point.y > 0.0) ? radius.x : radius.y; | | |||
35 | lowp vec2 d = abs(point - translation) - rect + radius.x; | | |||
36 | return min(max(d.x, d.y), 0.0) + length(max(d, 0.0)) - radius.x; | | |||
37 | } | | |||
38 | | ||||
39 | void main() | 28 | void main() | ||
40 | { | 29 | { | ||
41 | // Scaling factor that is the inverse of the amount of scaling applied to the geometry. | 30 | // Scaling factor that is the inverse of the amount of scaling applied to the geometry. | ||
42 | lowp float inverse_scale = 1.0 / (1.0 + size + length(offset) * 2.0); | 31 | lowp float inverse_scale = 1.0 / (1.0 + size + length(offset) * 2.0); | ||
43 | 32 | | |||
44 | // Correction factor to round the corners of a larger shadow. | 33 | // Correction factor to round the corners of a larger shadow. | ||
45 | // We want to account for size in regards to shadow radius, so that a larger shadow is | 34 | // We want to account for size in regards to shadow radius, so that a larger shadow is | ||
46 | // more rounded, but only if we are not already rounding the corners due to corner radius. | 35 | // more rounded, but only if we are not already rounding the corners due to corner radius. | ||
47 | lowp float size_factor = 0.5 * (minimum_shadow_radius / max(radius, minimum_shadow_radius)); | 36 | lowp float size_factor = 0.5 * (minimum_shadow_radius / max(radius, minimum_shadow_radius)); | ||
48 | 37 | lowp float shadow_radius = radius + size * size_factor; | |||
49 | lowp float shadowRadius = radius + size * size_factor; | | |||
50 | 38 | | |||
51 | lowp vec4 col = vec4(0.0); | 39 | lowp vec4 col = vec4(0.0); | ||
52 | 40 | | |||
53 | // Calculate the shadow's distance field. | 41 | // Calculate the shadow's distance field. | ||
54 | lowp float shadow = sdf_rounded_rectangle(uv, aspect * inverse_scale, offset * 2.0 * inverse_scale, vec4(shadowRadius * inverse_scale)); | 42 | lowp float shadow = sdf_rounded_rectangle(uv - offset * 2.0 * inverse_scale, aspect * inverse_scale, vec4(shadow_radius * inverse_scale)); | ||
55 | // Render it, interpolating the color over the distance. | 43 | // Render it, interpolating the color over the distance. | ||
56 | col = mix(col, shadowColor * sign(size), 1.0 - smoothstep(-size * 0.5, size * 0.5, shadow)); | 44 | col = mix(col, shadowColor * sign(size), 1.0 - smoothstep(-size * 0.5, size * 0.5, shadow)); | ||
57 | 45 | | |||
58 | // Calculate the main rectangle distance field. | 46 | // Calculate the main rectangle distance field. | ||
59 | lowp float rect = sdf_rounded_rectangle(uv, aspect * inverse_scale, vec2(0.0), vec4(radius * inverse_scale)); | 47 | lowp float rect = sdf_rounded_rectangle(uv, aspect * inverse_scale, vec4(radius * inverse_scale)); | ||
60 | | ||||
61 | lowp float g = fwidth(rect); | | |||
62 | 48 | | |||
63 | // First, remove anything that was rendered by the shadow if it is inside the rectangle. | 49 | // First, remove anything that was rendered by the shadow if it is inside the rectangle. | ||
64 | // This allows us to use colors with alpha without rendering artifacts. | 50 | // This allows us to use colors with alpha without rendering artifacts. | ||
65 | col = mix(col, vec4(0.0), 1.0 - smoothstep(0.001 - g, 0.001 + g, rect)); | 51 | col = sdf_render(rect, col, vec4(0.0)); | ||
66 | 52 | | |||
67 | // Then, render it again but this time with the proper color and properly alpha blended. | 53 | // Then, render it again but this time with the proper color and properly alpha blended. | ||
68 | col = mix(col, color, 1.0 - smoothstep(0.001 - g, 0.001 + g, rect)); | 54 | col = sdf_render(rect, col, color); | ||
69 | 55 | | |||
56 | #ifdef CORE_PROFILE | ||||
70 | out_color = col * opacity; | 57 | out_color = col * opacity; | ||
58 | #else | ||||
59 | gl_FragColor = col * opacity; | ||||
60 | #endif | ||||
71 | } | 61 | } |