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