Changeset View
Changeset View
Standalone View
Standalone View
src/scenegraph/shaders/shadowedbordertexture.frag
- This file was moved from src/scenegraph/shadowedborderrectangle_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 | #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; | ||
21 | uniform sampler2D textureSource; | ||||
24 | 22 | | |||
23 | #ifdef CORE_PROFILE | ||||
25 | in lowp vec2 uv; | 24 | in lowp vec2 uv; | ||
26 | | ||||
27 | out lowp vec4 out_color; | 25 | out lowp vec4 out_color; | ||
26 | #else | ||||
27 | varying lowp vec2 uv; | ||||
28 | #endif | ||||
28 | 29 | | |||
29 | const lowp float minimum_shadow_radius = 0.05; | 30 | const lowp float minimum_shadow_radius = 0.05; | ||
30 | const lowp float smoothing = 0.001; | | |||
31 | | ||||
32 | // Calculate the distance to a rectangle with rounded corners. | | |||
33 | // \param point The point to calculate the distance of. | | |||
34 | // \param rect The rectangle to calculate the distance of. | | |||
35 | // \param translation The amount of translation to apply to the rectangle. | | |||
36 | // \param radius A vec4 with the radius of each corner. Order is top right, bottom right, top left, bottom left. | | |||
37 | lowp float sdf_rounded_rectangle(in lowp vec2 point, in lowp vec2 rect, in lowp vec2 translation, in lowp vec4 radius) | | |||
38 | { | | |||
39 | radius.xy = (point.x > 0.0) ? radius.xy : radius.zw; | | |||
40 | radius.x = (point.y > 0.0) ? radius.x : radius.y; | | |||
41 | lowp vec2 d = abs(point - translation) - rect + radius.x; | | |||
42 | return min(max(d.x, d.y), 0.0) + length(max(d, 0.0)) - radius.x; | | |||
43 | } | | |||
44 | 31 | | |||
45 | // Render an sdf value into a color. | 32 | // Tiny abstraction around texture() to deal with Core profile differences. | ||
46 | lowp vec4 sdf_render(in lowp float sdf, in lowp vec4 sourceColor, in lowp vec4 sdfColor, in lowp float sdfAlpha) | 33 | lowp vec4 sample_texture(in sampler2D texture_source, in lowp vec2 uv) | ||
47 | { | 34 | { | ||
48 | lowp float g = fwidth(sdf); | 35 | #ifdef CORE_PROFILE | ||
49 | return mix(sourceColor, sdfColor, sdfAlpha * (1.0 - smoothstep(smoothing - g, smoothing + g, sdf))); | 36 | return texture(texture_source, uv); | ||
37 | #else | ||||
38 | return texture2D(texture_source, uv); | ||||
39 | #endif | ||||
50 | } | 40 | } | ||
51 | 41 | | |||
52 | void main() | 42 | void main() | ||
53 | { | 43 | { | ||
54 | // Scaling factor that is the inverse of the amount of scaling applied to the geometry. | 44 | // Scaling factor that is the inverse of the amount of scaling applied to the geometry. | ||
55 | lowp float inverse_scale = 1.0 / (1.0 + size + length(offset) * 2.0); | 45 | lowp float inverse_scale = 1.0 / (1.0 + size + length(offset) * 2.0); | ||
56 | 46 | | |||
57 | // Correction factor to round the corners of a larger shadow. | 47 | // Correction factor to round the corners of a larger shadow. | ||
58 | // We want to account for size in regards to shadow radius, so that a larger shadow is | 48 | // We want to account for size in regards to shadow radius, so that a larger shadow is | ||
59 | // more rounded, but only if we are not already rounding the corners due to corner radius. | 49 | // more rounded, but only if we are not already rounding the corners due to corner radius. | ||
60 | lowp float size_factor = 0.5 * (minimum_shadow_radius / max(radius, minimum_shadow_radius)); | 50 | lowp float size_factor = 0.5 * (minimum_shadow_radius / max(radius, minimum_shadow_radius)); | ||
61 | | ||||
62 | lowp float shadow_radius = radius + size * size_factor; | 51 | lowp float shadow_radius = radius + size * size_factor; | ||
63 | 52 | | |||
64 | lowp vec4 col = vec4(0.0); | 53 | lowp vec4 col = vec4(0.0); | ||
65 | 54 | | |||
66 | // Calculate the shadow's distance field. | 55 | // Calculate the shadow's distance field. | ||
67 | lowp float shadow = sdf_rounded_rectangle(uv, aspect * inverse_scale, offset * 2.0 * inverse_scale, vec4(shadow_radius * inverse_scale)); | 56 | lowp float shadow = sdf_rounded_rectangle(uv - offset * 2.0 * inverse_scale, aspect * inverse_scale, vec4(shadow_radius * inverse_scale)); | ||
68 | // Render it, interpolating the color over the distance. | 57 | // Render it, interpolating the color over the distance. | ||
69 | col = mix(col, shadowColor * sign(size), 1.0 - smoothstep(-size * 0.5, size * 0.5, shadow)); | 58 | col = mix(col, shadowColor * sign(size), 1.0 - smoothstep(-size * 0.5, size * 0.5, shadow)); | ||
70 | 59 | | |||
71 | // Scale corrected corner radius | 60 | // Scale corrected corner radius | ||
72 | lowp vec4 corner_radius = vec4(radius * inverse_scale); | 61 | lowp vec4 corner_radius = vec4(radius * inverse_scale); | ||
73 | 62 | | |||
74 | // Calculate the outer rectangle distance field. | 63 | // Calculate the outer rectangle distance field. | ||
75 | lowp float outer_rect = sdf_rounded_rectangle(uv, aspect * inverse_scale, vec2(0.0), corner_radius); | 64 | lowp float outer_rect = sdf_rounded_rectangle(uv, aspect * inverse_scale, corner_radius); | ||
76 | 65 | | |||
77 | // First, remove anything that was rendered by the shadow if it is inside the rectangle. | 66 | // First, remove anything that was rendered by the shadow if it is inside the rectangle. | ||
78 | // This allows us to use colors with alpha without rendering artifacts. | 67 | // This allows us to use colors with alpha without rendering artifacts. | ||
79 | col = sdf_render(outer_rect, col, vec4(0.0), 1.0); | 68 | col = sdf_render(outer_rect, col, vec4(0.0)); | ||
80 | 69 | | |||
81 | // Then, render it again but this time with the proper color and properly alpha blended. | 70 | // Then, render it again but this time with the proper color and properly alpha blended. | ||
82 | col = sdf_render(outer_rect, col, borderColor, 1.0); | 71 | col = sdf_render(outer_rect, col, borderColor); | ||
83 | 72 | | |||
84 | // Calculate the inner rectangle distance field. | 73 | // Calculate the inner rectangle distance field. | ||
85 | // This uses a reduced corner radius because the inner corners need to be smaller than the outer corners. | 74 | // This uses a reduced corner radius because the inner corners need to be smaller than the outer corners. | ||
86 | lowp vec4 inner_radius = vec4((radius - borderWidth * 2.0) * inverse_scale); | 75 | lowp vec4 inner_radius = vec4((radius - borderWidth * 2.0) * inverse_scale); | ||
87 | lowp float inner_rect = sdf_rounded_rectangle(uv, (aspect - borderWidth * 2.0) * inverse_scale, vec2(0.0), inner_radius); | 76 | lowp float inner_rect = sdf_rounded_rectangle(uv, (aspect - borderWidth * 2.0) * inverse_scale, inner_radius); | ||
88 | 77 | | |||
89 | // Like above, but this time cut out the inner rectangle. | 78 | // Like above, but this time cut out the inner rectangle. | ||
90 | col = sdf_render(inner_rect, col, vec4(0.0), 1.0); | 79 | col = sdf_render(inner_rect, col, vec4(0.0)); | ||
91 | 80 | | |||
92 | // Finally, render the inner rectangle. | 81 | // Finally, render the inner rectangle. | ||
93 | col = sdf_render(inner_rect, col, color, 1.0); | 82 | col = sdf_render(inner_rect, col, color); | ||
83 | | ||||
84 | inner_rect = sdf_rounded_rectangle(uv, (aspect - borderWidth * 2.0 + 0.005) * inverse_scale, inner_radius); | ||||
85 | | ||||
86 | // Sample the texture, then blend it on top of the background color. | ||||
87 | lowp vec2 texture_uv = ((uv / aspect) + (1.0 * inverse_scale)) / (2.0 * inverse_scale); | ||||
88 | lowp vec4 texture_color = sample_texture(textureSource, texture_uv); | ||||
89 | col = sdf_render(inner_rect, col, texture_color, texture_color.a, sdf_default_smoothing / 2.0); | ||||
94 | 90 | | |||
91 | #ifdef CORE_PROFILE | ||||
95 | out_color = col * opacity; | 92 | out_color = col * opacity; | ||
93 | #else | ||||
94 | gl_FragColor = col * opacity; | ||||
95 | #endif | ||||
96 | } | 96 | } |