@solidtv/renderer 1.5.6 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/core/CoreNode.js +2 -2
- package/dist/src/core/CoreNode.js.map +1 -1
- package/dist/src/core/CoreTextureManager.d.ts +31 -0
- package/dist/src/core/CoreTextureManager.js +87 -6
- package/dist/src/core/CoreTextureManager.js.map +1 -1
- package/dist/src/core/Stage.js +11 -2
- package/dist/src/core/Stage.js.map +1 -1
- package/dist/src/core/lib/WebGlContextWrapper.d.ts +17 -1
- package/dist/src/core/lib/WebGlContextWrapper.js +21 -0
- package/dist/src/core/lib/WebGlContextWrapper.js.map +1 -1
- package/dist/src/core/lib/colorParser.d.ts +4 -1
- package/dist/src/core/lib/colorParser.js +16 -6
- package/dist/src/core/lib/colorParser.js.map +1 -1
- package/dist/src/core/platforms/web/WebPlatform.js +60 -50
- package/dist/src/core/platforms/web/WebPlatform.js.map +1 -1
- package/dist/src/core/renderers/canvas/CanvasRenderer.d.ts +4 -0
- package/dist/src/core/renderers/canvas/CanvasRenderer.js +28 -13
- package/dist/src/core/renderers/canvas/CanvasRenderer.js.map +1 -1
- package/dist/src/core/renderers/canvas/CanvasShaderNode.js +1 -0
- package/dist/src/core/renderers/canvas/CanvasShaderNode.js.map +1 -1
- package/dist/src/core/renderers/webgl/SdfRenderOp.js +2 -2
- package/dist/src/core/renderers/webgl/SdfRenderOp.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlRenderer.d.ts +43 -0
- package/dist/src/core/renderers/webgl/WebGlRenderer.js +109 -10
- package/dist/src/core/renderers/webgl/WebGlRenderer.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlShaderProgram.js +21 -13
- package/dist/src/core/renderers/webgl/WebGlShaderProgram.js.map +1 -1
- package/dist/src/core/renderers/webgl/internal/ShaderUtils.d.ts +8 -3
- package/dist/src/core/renderers/webgl/internal/ShaderUtils.js +12 -11
- package/dist/src/core/renderers/webgl/internal/ShaderUtils.js.map +1 -1
- package/dist/src/core/shaders/canvas/Rounded.js +3 -3
- package/dist/src/core/shaders/canvas/Rounded.js.map +1 -1
- package/dist/src/core/shaders/canvas/RoundedWithShadow.js +3 -3
- package/dist/src/core/shaders/canvas/RoundedWithShadow.js.map +1 -1
- package/dist/src/core/shaders/canvas/utils/render.js +3 -3
- package/dist/src/core/shaders/canvas/utils/render.js.map +1 -1
- package/dist/src/core/shaders/webgl/Border.js +12 -11
- package/dist/src/core/shaders/webgl/Border.js.map +1 -1
- package/dist/src/core/shaders/webgl/HolePunch.js +12 -5
- package/dist/src/core/shaders/webgl/HolePunch.js.map +1 -1
- package/dist/src/core/shaders/webgl/LinearGradient.js +3 -19
- package/dist/src/core/shaders/webgl/LinearGradient.js.map +1 -1
- package/dist/src/core/shaders/webgl/RadialGradient.js +3 -20
- package/dist/src/core/shaders/webgl/RadialGradient.js.map +1 -1
- package/dist/src/core/shaders/webgl/RadialProgress.js +15 -23
- package/dist/src/core/shaders/webgl/RadialProgress.js.map +1 -1
- package/dist/src/core/shaders/webgl/RoundedWithBorder.js +35 -32
- package/dist/src/core/shaders/webgl/RoundedWithBorder.js.map +1 -1
- package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js +58 -45
- package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js.map +1 -1
- package/dist/src/core/shaders/webgl/RoundedWithShadow.js +15 -13
- package/dist/src/core/shaders/webgl/RoundedWithShadow.js.map +1 -1
- package/dist/src/core/shaders/webgl/Shadow.js +4 -5
- package/dist/src/core/shaders/webgl/Shadow.js.map +1 -1
- package/dist/src/core/text-rendering/SdfTextRenderer.js +23 -10
- package/dist/src/core/text-rendering/SdfTextRenderer.js.map +1 -1
- package/dist/src/core/text-rendering/TextLayoutEngine.js +14 -2
- package/dist/src/core/text-rendering/TextLayoutEngine.js.map +1 -1
- package/dist/src/main-api/Renderer.d.ts +28 -5
- package/dist/src/main-api/Renderer.js +5 -1
- package/dist/src/main-api/Renderer.js.map +1 -1
- package/dist/src/utils.js +1 -1
- package/dist/src/utils.js.map +1 -1
- package/dist/tsconfig.dist.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/core/CoreNode.ts +2 -2
- package/src/core/CoreTextureManager.test.ts +147 -0
- package/src/core/CoreTextureManager.ts +97 -8
- package/src/core/Stage.renderListUpdate.test.ts +73 -0
- package/src/core/Stage.ts +13 -1
- package/src/core/lib/WebGlContextWrapper.test.ts +23 -1
- package/src/core/lib/WebGlContextWrapper.ts +23 -1
- package/src/core/lib/colorParser.test.ts +46 -0
- package/src/core/lib/colorParser.ts +17 -6
- package/src/core/platforms/web/WebPlatform.ts +63 -52
- package/src/core/renderers/canvas/CanvasRenderer.test.ts +230 -0
- package/src/core/renderers/canvas/CanvasRenderer.ts +29 -15
- package/src/core/renderers/canvas/CanvasShaderNode.test.ts +73 -0
- package/src/core/renderers/canvas/CanvasShaderNode.ts +1 -0
- package/src/core/renderers/webgl/SdfRenderOp.ts +2 -2
- package/src/core/renderers/webgl/WebGlRenderer.reuseRenderOp.test.ts +122 -0
- package/src/core/renderers/webgl/WebGlRenderer.sdfBuffer.test.ts +302 -0
- package/src/core/renderers/webgl/WebGlRenderer.ts +151 -11
- package/src/core/renderers/webgl/WebGlShaderProgram.reuseRenderOp.test.ts +150 -0
- package/src/core/renderers/webgl/WebGlShaderProgram.ts +27 -15
- package/src/core/renderers/webgl/WebGlShaderProgram.uniformDedup.test.ts +4 -2
- package/src/core/renderers/webgl/internal/ShaderUtils.test.ts +124 -0
- package/src/core/renderers/webgl/internal/ShaderUtils.ts +14 -13
- package/src/core/shaders/canvas/Rounded.ts +3 -3
- package/src/core/shaders/canvas/RoundedWithShadow.ts +3 -3
- package/src/core/shaders/canvas/utils/render.ts +3 -3
- package/src/core/shaders/webgl/Border.ts +12 -11
- package/src/core/shaders/webgl/HolePunch.ts +12 -5
- package/src/core/shaders/webgl/LinearGradient.ts +3 -19
- package/src/core/shaders/webgl/RadialGradient.ts +3 -20
- package/src/core/shaders/webgl/RadialProgress.ts +15 -23
- package/src/core/shaders/webgl/RoundedWithBorder.ts +35 -32
- package/src/core/shaders/webgl/RoundedWithBorderAndShadow.ts +58 -45
- package/src/core/shaders/webgl/RoundedWithShadow.ts +15 -13
- package/src/core/shaders/webgl/Shadow.ts +4 -5
- package/src/core/text-rendering/SdfTextRenderer.test.ts +177 -0
- package/src/core/text-rendering/SdfTextRenderer.ts +38 -10
- package/src/core/text-rendering/TextLayoutEngine.ts +15 -2
- package/src/core/text-rendering/tests/TextLayoutEngine.test.ts +99 -0
- package/src/main-api/Renderer.ts +35 -6
- package/src/utils.ts +1 -1
|
@@ -57,9 +57,9 @@ export function roundedRectWithBorder(
|
|
|
57
57
|
|
|
58
58
|
//draw node content first
|
|
59
59
|
ctx.save();
|
|
60
|
-
|
|
61
|
-
roundRect(
|
|
62
|
-
ctx.clip(
|
|
60
|
+
ctx.beginPath();
|
|
61
|
+
roundRect(ctx, x, y, width, height, radius);
|
|
62
|
+
ctx.clip();
|
|
63
63
|
renderContext();
|
|
64
64
|
ctx.restore();
|
|
65
65
|
|
|
@@ -135,24 +135,25 @@ export const Border: WebGlShaderType<BorderProps> = {
|
|
|
135
135
|
float outerDist = box(boxUv + v_outerBorderUv, v_outerSize - edgeWidth);
|
|
136
136
|
float innerDist = box(boxUv + v_innerBorderUv, v_innerSize - edgeWidth);
|
|
137
137
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
float innerAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, innerDist);
|
|
141
|
-
resultColor = mix(resultColor, u_borderColor, outerAlpha * u_borderColor.a);
|
|
142
|
-
resultColor = mix(resultColor, color, innerAlpha);
|
|
143
|
-
gl_FragColor = resultColor * u_alpha;
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
138
|
+
float outerAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, outerDist);
|
|
139
|
+
float innerAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, innerDist);
|
|
146
140
|
|
|
147
141
|
float nodeDist = box(boxUv, v_halfDimensions - edgeWidth);
|
|
148
142
|
float nodeAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, nodeDist);
|
|
149
143
|
|
|
150
144
|
float borderDist = max(-innerDist, outerDist);
|
|
151
145
|
float borderAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, borderDist);
|
|
152
|
-
resultColor = mix(resultColor, color, nodeAlpha);
|
|
153
|
-
resultColor = mix(resultColor, u_borderColor, borderAlpha * u_borderColor.a);
|
|
154
146
|
|
|
155
|
-
|
|
147
|
+
// Branchless gap select -- Mali 400 serializes uniform branches, so both
|
|
148
|
+
// composites are computed and mix()-selected on hasGap instead.
|
|
149
|
+
vec4 resNoGap = mix(resultColor, u_borderColor, outerAlpha * u_borderColor.a);
|
|
150
|
+
resNoGap = mix(resNoGap, color, innerAlpha);
|
|
151
|
+
|
|
152
|
+
vec4 resGap = mix(resultColor, color, nodeAlpha);
|
|
153
|
+
resGap = mix(resGap, u_borderColor, borderAlpha * u_borderColor.a);
|
|
154
|
+
|
|
155
|
+
float hasGap = step(0.0001, abs(u_borderGap));
|
|
156
|
+
gl_FragColor = mix(resNoGap, resGap, hasGap) * u_alpha;
|
|
156
157
|
}
|
|
157
158
|
`,
|
|
158
159
|
};
|
|
@@ -46,11 +46,18 @@ export const HolePunch: WebGlShaderType<HolePunchProps> = {
|
|
|
46
46
|
void main() {
|
|
47
47
|
vec4 color = texture2D(u_texture, v_textureCoords) * v_color;
|
|
48
48
|
vec2 p = (v_textureCoords.xy * u_dimensions.xy - u_pos) - u_size;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
float
|
|
49
|
+
|
|
50
|
+
// Branchless radius selection based on quadrant
|
|
51
|
+
// x: TL, y: TR, z: BR, w: BL
|
|
52
|
+
vec2 stepVal = step(vec2(0.0), p);
|
|
53
|
+
float r = mix(
|
|
54
|
+
mix(u_radius.x, u_radius.y, stepVal.x),
|
|
55
|
+
mix(u_radius.w, u_radius.z, stepVal.x),
|
|
56
|
+
stepVal.y
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
p = abs(p) - u_size + r;
|
|
60
|
+
float dist = min(max(p.x, p.y), 0.0) + length(max(p, 0.0)) - r + 2.0;
|
|
54
61
|
float roundedAlpha = 1.0 - smoothstep(0.0, u_pixelRatio, dist);
|
|
55
62
|
gl_FragColor = mix(color, vec4(0.0), min(color.a, roundedAlpha));
|
|
56
63
|
}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
} from '../templates/LinearGradientTemplate.js';
|
|
7
7
|
import type { WebGlRenderer } from '../../renderers/webgl/WebGlRenderer.js';
|
|
8
8
|
import type { WebGlShaderType } from '../../renderers/webgl/WebGlShaderNode.js';
|
|
9
|
+
import { genGradientColors } from '../../renderers/webgl/internal/ShaderUtils.js';
|
|
9
10
|
|
|
10
11
|
export const LinearGradient: WebGlShaderType<LinearGradientProps> = {
|
|
11
12
|
props: LinearGradientTemplate.props,
|
|
@@ -56,7 +57,6 @@ export const LinearGradient: WebGlShaderType<LinearGradientProps> = {
|
|
|
56
57
|
# endif
|
|
57
58
|
|
|
58
59
|
#define MAX_STOPS ${props.colors.length}
|
|
59
|
-
#define LAST_STOP ${props.colors.length - 1}
|
|
60
60
|
|
|
61
61
|
uniform float u_alpha;
|
|
62
62
|
|
|
@@ -72,24 +72,8 @@ export const LinearGradient: WebGlShaderType<LinearGradientProps> = {
|
|
|
72
72
|
|
|
73
73
|
vec4 getGradientColor(float dist) {
|
|
74
74
|
dist = clamp(dist, 0.0, 1.0);
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
return u_colors[0];
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if(dist >= u_stops[LAST_STOP]) {
|
|
81
|
-
return u_colors[LAST_STOP];
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
for(int i = 0; i < LAST_STOP; i++) {
|
|
85
|
-
float left = u_stops[i];
|
|
86
|
-
float right = u_stops[i + 1];
|
|
87
|
-
if(dist >= left && dist <= right) {
|
|
88
|
-
float lDist = smoothstep(left, right, dist);
|
|
89
|
-
return mix(u_colors[i], u_colors[i + 1], lDist);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
return u_colors[LAST_STOP];
|
|
75
|
+
${genGradientColors(props.colors.length)}
|
|
76
|
+
return colorOut;
|
|
93
77
|
}
|
|
94
78
|
|
|
95
79
|
void main() {
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
} from '../templates/RadialGradientTemplate.js';
|
|
7
7
|
import type { WebGlShaderType } from '../../renderers/webgl/WebGlShaderNode.js';
|
|
8
8
|
import type { WebGlRenderer } from '../../renderers/webgl/WebGlRenderer.js';
|
|
9
|
+
import { genGradientColors } from '../../renderers/webgl/internal/ShaderUtils.js';
|
|
9
10
|
|
|
10
11
|
export const RadialGradient: WebGlShaderType<RadialGradientProps> = {
|
|
11
12
|
props: RadialGradientTemplate.props,
|
|
@@ -37,7 +38,6 @@ export const RadialGradient: WebGlShaderType<RadialGradientProps> = {
|
|
|
37
38
|
# endif
|
|
38
39
|
|
|
39
40
|
#define MAX_STOPS ${props.colors.length}
|
|
40
|
-
#define LAST_STOP ${props.colors.length - 1}
|
|
41
41
|
|
|
42
42
|
uniform float u_alpha;
|
|
43
43
|
uniform vec2 u_dimensions;
|
|
@@ -56,25 +56,8 @@ export const RadialGradient: WebGlShaderType<RadialGradientProps> = {
|
|
|
56
56
|
|
|
57
57
|
vec4 getGradientColor(float dist) {
|
|
58
58
|
dist = clamp(dist, 0.0, 1.0);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return u_colors[0];
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if(dist >= u_stops[LAST_STOP]) {
|
|
65
|
-
return u_colors[LAST_STOP];
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
for(int i = 0; i < LAST_STOP; i++) {
|
|
69
|
-
float left = u_stops[i];
|
|
70
|
-
float right = u_stops[i + 1];
|
|
71
|
-
if(dist >= left && dist <= right) {
|
|
72
|
-
float lDist = smoothstep(left, right, dist);
|
|
73
|
-
return mix(u_colors[i], u_colors[i + 1], lDist);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return u_colors[LAST_STOP];
|
|
59
|
+
${genGradientColors(props.colors.length)}
|
|
60
|
+
return colorOut;
|
|
78
61
|
}
|
|
79
62
|
|
|
80
63
|
void main() {
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
} from '../templates/RadialProgressTemplate.js';
|
|
7
7
|
import type { WebGlShaderType } from '../../renderers/webgl/WebGlShaderNode.js';
|
|
8
8
|
import type { WebGlRenderer } from '../../renderers/webgl/WebGlRenderer.js';
|
|
9
|
+
import { genGradientColors } from '../../renderers/webgl/internal/ShaderUtils.js';
|
|
9
10
|
|
|
10
11
|
export const RadialProgress: WebGlShaderType<RadialProgressProps> = {
|
|
11
12
|
props: RadialProgressTemplate.props,
|
|
@@ -57,7 +58,6 @@ export const RadialProgress: WebGlShaderType<RadialProgressProps> = {
|
|
|
57
58
|
# endif
|
|
58
59
|
|
|
59
60
|
#define MAX_STOPS ${maxStops}
|
|
60
|
-
#define LAST_STOP ${maxStops - 1}
|
|
61
61
|
#define CAP_ROUND ${props.cap}
|
|
62
62
|
#define HAS_TRACK ${props.trackColor !== 0 ? 1 : 0}
|
|
63
63
|
|
|
@@ -87,22 +87,8 @@ export const RadialProgress: WebGlShaderType<RadialProgressProps> = {
|
|
|
87
87
|
|
|
88
88
|
vec4 getGradientColor(float dist) {
|
|
89
89
|
dist = clamp(dist, 0.0, 1.0);
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
return u_colors[0];
|
|
93
|
-
}
|
|
94
|
-
if (dist >= u_stops[LAST_STOP]) {
|
|
95
|
-
return u_colors[LAST_STOP];
|
|
96
|
-
}
|
|
97
|
-
for (int i = 0; i < LAST_STOP; i++) {
|
|
98
|
-
float left = u_stops[i];
|
|
99
|
-
float right = u_stops[i + 1];
|
|
100
|
-
if (dist >= left && dist <= right) {
|
|
101
|
-
float lDist = smoothstep(left, right, dist);
|
|
102
|
-
return mix(u_colors[i], u_colors[i + 1], lDist);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
return u_colors[LAST_STOP];
|
|
90
|
+
${genGradientColors(maxStops)}
|
|
91
|
+
return colorOut;
|
|
106
92
|
}
|
|
107
93
|
|
|
108
94
|
// Coverage of a disc centered at \`c\` with radius \`r\` at pixel \`p\` (with 1px AA)
|
|
@@ -116,9 +102,13 @@ export const RadialProgress: WebGlShaderType<RadialProgressProps> = {
|
|
|
116
102
|
// Effective progress: when u_duration > 0 the shader self-animates from
|
|
117
103
|
// u_time, otherwise we use the static u_progress prop. countdown == 1
|
|
118
104
|
// drains (1 -> 0), countdown == 0 fills (0 -> 1).
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
105
|
+
// Branchless (Mali 400 serializes uniform branches): the mix()-guarded
|
|
106
|
+
// denominator keeps the division finite when u_duration == 0 -- a
|
|
107
|
+
// max()-clamped epsilon would overflow fp16 mediump to Inf/NaN.
|
|
108
|
+
float hasDuration = step(0.0001, u_duration);
|
|
109
|
+
float cyclePos = fract(u_time / mix(1.0, u_duration, hasDuration)) * hasDuration;
|
|
110
|
+
float animProgress = mix(cyclePos, 1.0 - cyclePos, step(0.5, u_countdown));
|
|
111
|
+
float progress = mix(u_progress, animProgress, hasDuration);
|
|
122
112
|
|
|
123
113
|
vec2 p = v_nodeCoords.xy * u_dimensions - u_center;
|
|
124
114
|
float dist = length(p);
|
|
@@ -135,7 +125,7 @@ export const RadialProgress: WebGlShaderType<RadialProgressProps> = {
|
|
|
135
125
|
|
|
136
126
|
// Filled arc coverage (1 if in filled arc, else 0). When progress >= 1 the
|
|
137
127
|
// whole ring is filled regardless of \`t\` -- guards against the mod() seam.
|
|
138
|
-
float arcCoverage =
|
|
128
|
+
float arcCoverage = max(step(1.0, progress), step(t, progress));
|
|
139
129
|
float fillCoverage = ringCoverage * arcCoverage;
|
|
140
130
|
|
|
141
131
|
#if CAP_ROUND
|
|
@@ -151,8 +141,10 @@ export const RadialProgress: WebGlShaderType<RadialProgressProps> = {
|
|
|
151
141
|
#endif
|
|
152
142
|
|
|
153
143
|
// Sample gradient. Normalize \`t\` to the *filled* portion so the gradient
|
|
154
|
-
// spans the visible arc end-to-end regardless of progress.
|
|
155
|
-
|
|
144
|
+
// spans the visible arc end-to-end regardless of progress. mix()-guarded
|
|
145
|
+
// denominator: safe at progress == 0 without fp16 overflow.
|
|
146
|
+
float hasProgress = step(0.000001, progress);
|
|
147
|
+
float gradT = clamp(t / mix(1.0, progress, hasProgress), 0.0, 1.0) * hasProgress;
|
|
156
148
|
vec4 fillCol = getGradientColor(gradT);
|
|
157
149
|
|
|
158
150
|
// Composite: track under fill (if track enabled), both gated by ringCoverage.
|
|
@@ -64,6 +64,15 @@ export const RoundedWithBorder: WebGlShaderType<RoundedWithBorderProps> = {
|
|
|
64
64
|
v_innerSize = vec2(0.0);
|
|
65
65
|
v_outerSize = vec2(0.0);
|
|
66
66
|
|
|
67
|
+
// Defaults for the zero-border case: the fragment shader is branchless
|
|
68
|
+
// and always evaluates the border SDFs, so every varying must carry a
|
|
69
|
+
// finite value (an unwritten varying is undefined and can poison the
|
|
70
|
+
// final mix() with NaN).
|
|
71
|
+
v_outerBorderUv = vec2(0.0);
|
|
72
|
+
v_innerBorderUv = vec2(0.0);
|
|
73
|
+
v_outerBorderRadius = u_radius;
|
|
74
|
+
v_innerBorderRadius = u_radius;
|
|
75
|
+
|
|
67
76
|
if(borderZero == 0.0) {
|
|
68
77
|
vec4 adjustedBorderWidth = u_borderWidth - 1.0 + clamp(u_borderWidth, -1.0, 1.0);
|
|
69
78
|
|
|
@@ -72,9 +81,6 @@ export const RoundedWithBorder: WebGlShaderType<RoundedWithBorderProps> = {
|
|
|
72
81
|
float borderBottom = adjustedBorderWidth.z;
|
|
73
82
|
float borderLeft = adjustedBorderWidth.w;
|
|
74
83
|
|
|
75
|
-
v_outerBorderUv = vec2(0.0);
|
|
76
|
-
v_innerBorderUv = vec2(0.0);
|
|
77
|
-
|
|
78
84
|
vec2 borderSize = vec2(borderRight + borderLeft, borderTop + borderBottom);
|
|
79
85
|
vec2 extraSize = borderSize * u_borderAlign;
|
|
80
86
|
float gapLeft = step(0.001, borderLeft) * u_borderGap;
|
|
@@ -159,52 +165,49 @@ export const RoundedWithBorder: WebGlShaderType<RoundedWithBorderProps> = {
|
|
|
159
165
|
varying vec4 v_outerBorderRadius;
|
|
160
166
|
varying vec2 v_halfDimensions;
|
|
161
167
|
|
|
168
|
+
// Branchless quadrant radius select (r: x TL, y TR, z BR, w BL) --
|
|
169
|
+
// Mali 400-class fragment pipelines serialize any branch, ternaries included.
|
|
170
|
+
float quadRadius(vec2 p, vec4 r) {
|
|
171
|
+
vec2 stepVal = step(vec2(0.0), p);
|
|
172
|
+
return mix(mix(r.x, r.y, stepVal.x), mix(r.w, r.z, stepVal.x), stepVal.y);
|
|
173
|
+
}
|
|
174
|
+
|
|
162
175
|
float roundedBox(vec2 p, vec2 s, vec4 r) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
return (min(max(q.x, q.y), 0.0) + length(max(q, 0.0))) - r.x;
|
|
176
|
+
float rad = quadRadius(p, r);
|
|
177
|
+
vec2 q = abs(p) - s + rad;
|
|
178
|
+
return (min(max(q.x, q.y), 0.0) + length(max(q, 0.0))) - rad;
|
|
167
179
|
}
|
|
168
180
|
|
|
169
181
|
void main() {
|
|
170
182
|
vec4 color = texture2D(u_texture, v_textureCoords) * v_color;
|
|
171
|
-
vec4 resultColor = vec4(0.0);
|
|
172
183
|
vec2 boxUv = v_nodeCoords.xy * u_dimensions - v_halfDimensions;
|
|
173
184
|
float borderZero = 1.0 - step(0.001, dot(abs(u_borderWidth), vec4(1.0)));
|
|
174
185
|
float edgeWidth = 1.0 / u_pixelRatio;
|
|
175
186
|
|
|
176
|
-
float nodeDist;
|
|
177
|
-
float nodeAlpha;
|
|
178
|
-
|
|
179
|
-
if(borderZero == 1.0) {
|
|
180
|
-
nodeDist = roundedBox(boxUv, v_halfDimensions - edgeWidth, u_radius);
|
|
181
|
-
nodeAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, nodeDist);
|
|
182
|
-
gl_FragColor = (color * nodeAlpha) * u_alpha;
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
187
|
+
float nodeDist = roundedBox(boxUv, v_halfDimensions - edgeWidth, u_radius);
|
|
188
|
+
float nodeAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, nodeDist);
|
|
185
189
|
|
|
186
190
|
float outerDist = roundedBox(boxUv + v_outerBorderUv, v_outerSize - edgeWidth, v_outerBorderRadius);
|
|
187
191
|
float innerDist = roundedBox(boxUv + v_innerBorderUv, v_innerSize - edgeWidth, v_innerBorderRadius);
|
|
188
|
-
|
|
189
|
-
if(u_borderGap == 0.0) {
|
|
190
|
-
float outerAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, outerDist);
|
|
191
|
-
float innerAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, innerDist);
|
|
192
|
-
resultColor = mix(resultColor, u_borderColor, outerAlpha * u_borderColor.a);
|
|
193
|
-
resultColor = mix(resultColor, color, innerAlpha);
|
|
194
|
-
gl_FragColor = resultColor * u_alpha;
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
nodeDist = roundedBox(boxUv, v_halfDimensions - edgeWidth, u_radius);
|
|
199
|
-
nodeAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, nodeDist);
|
|
192
|
+
float outerAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, outerDist);
|
|
200
193
|
float innerAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, innerDist);
|
|
201
|
-
float gapAlpha = max(0.0, innerAlpha - nodeAlpha);
|
|
202
194
|
|
|
195
|
+
float gapAlpha = max(0.0, innerAlpha - nodeAlpha);
|
|
203
196
|
float borderDist = max(-innerDist, outerDist);
|
|
204
197
|
float borderAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, borderDist);
|
|
205
198
|
|
|
206
|
-
|
|
207
|
-
|
|
199
|
+
// Branchless path select -- Mali 400 serializes uniform branches, so all
|
|
200
|
+
// three composites (no gap / gap / zero border) are computed and
|
|
201
|
+
// mix()-selected instead of if/else'd.
|
|
202
|
+
vec4 resNoGap = mix(vec4(0.0), u_borderColor, outerAlpha * u_borderColor.a);
|
|
203
|
+
resNoGap = mix(resNoGap, color, innerAlpha);
|
|
204
|
+
|
|
205
|
+
vec4 resGap = (color * nodeAlpha) + (u_fillColor * gapAlpha);
|
|
206
|
+
resGap = mix(resGap, u_borderColor, borderAlpha * u_borderColor.a);
|
|
207
|
+
|
|
208
|
+
float hasGap = step(0.0001, abs(u_borderGap));
|
|
209
|
+
vec4 resultColor = mix(resNoGap, resGap, hasGap);
|
|
210
|
+
resultColor = mix(resultColor, color * nodeAlpha, borderZero);
|
|
208
211
|
gl_FragColor = resultColor * u_alpha;
|
|
209
212
|
}
|
|
210
213
|
`,
|
|
@@ -71,6 +71,15 @@ export const RoundedWithBorderAndShadow: WebGlShaderType<RoundedWithBorderAndSha
|
|
|
71
71
|
v_innerSize = vec2(0.0);
|
|
72
72
|
v_outerSize = vec2(0.0);
|
|
73
73
|
|
|
74
|
+
// Defaults for the zero-border case: the fragment shader is branchless
|
|
75
|
+
// and always evaluates the border SDFs, so every varying must carry a
|
|
76
|
+
// finite value (an unwritten varying is undefined and can poison the
|
|
77
|
+
// final mix() with NaN).
|
|
78
|
+
v_outerBorderUv = vec2(0.0);
|
|
79
|
+
v_innerBorderUv = vec2(0.0);
|
|
80
|
+
v_outerBorderRadius = u_radius;
|
|
81
|
+
v_innerBorderRadius = u_radius;
|
|
82
|
+
|
|
74
83
|
if(borderZero == 0.0) {
|
|
75
84
|
vec4 adjustedBorderWidth = u_borderWidth - 1.0 + clamp(u_borderWidth, -1.0, 1.0);
|
|
76
85
|
|
|
@@ -79,9 +88,6 @@ export const RoundedWithBorderAndShadow: WebGlShaderType<RoundedWithBorderAndSha
|
|
|
79
88
|
float borderBottom = adjustedBorderWidth.z;
|
|
80
89
|
float borderLeft = adjustedBorderWidth.w;
|
|
81
90
|
|
|
82
|
-
v_outerBorderUv = vec2(0.0);
|
|
83
|
-
v_innerBorderUv = vec2(0.0);
|
|
84
|
-
|
|
85
91
|
vec2 borderSize = vec2(borderRight + borderLeft, borderTop + borderBottom);
|
|
86
92
|
vec2 extraSize = borderSize * u_borderAlign;
|
|
87
93
|
float gapLeft = step(0.001, borderLeft) * u_borderGap;
|
|
@@ -166,67 +172,74 @@ export const RoundedWithBorderAndShadow: WebGlShaderType<RoundedWithBorderAndSha
|
|
|
166
172
|
varying vec4 v_outerBorderRadius;
|
|
167
173
|
varying vec2 v_halfDimensions;
|
|
168
174
|
|
|
175
|
+
// Branchless quadrant radius select (r: x TL, y TR, z BR, w BL) --
|
|
176
|
+
// Mali 400-class fragment pipelines serialize any branch, ternaries included.
|
|
177
|
+
float quadRadius(vec2 p, vec4 r) {
|
|
178
|
+
vec2 stepVal = step(vec2(0.0), p);
|
|
179
|
+
return mix(mix(r.x, r.y, stepVal.x), mix(r.w, r.z, stepVal.x), stepVal.y);
|
|
180
|
+
}
|
|
181
|
+
|
|
169
182
|
float roundedBox(vec2 p, vec2 s, vec4 r) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
return (min(max(q.x, q.y), 0.0) + length(max(q, 0.0))) - r.x;
|
|
183
|
+
float rad = quadRadius(p, r);
|
|
184
|
+
vec2 q = abs(p) - s + rad;
|
|
185
|
+
return (min(max(q.x, q.y), 0.0) + length(max(q, 0.0))) - rad;
|
|
174
186
|
}
|
|
175
187
|
|
|
176
188
|
float shadowBox(vec2 p, vec2 s, vec4 r) {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
float dist = min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r.x;
|
|
189
|
+
float rad = quadRadius(p, r);
|
|
190
|
+
vec2 q = abs(p) - s + rad;
|
|
191
|
+
float dist = min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - rad;
|
|
181
192
|
return 1.0 - smoothstep(-u_shadow.w, u_shadow.w + u_shadow.z, dist);
|
|
182
193
|
}
|
|
183
194
|
|
|
184
195
|
void main() {
|
|
185
196
|
vec4 color = texture2D(u_texture, v_textureCoords) * v_color;
|
|
186
|
-
vec4 resultColor = vec4(0.0);
|
|
187
197
|
vec2 boxUv = v_nodeCoords.xy * u_dimensions - v_halfDimensions;
|
|
188
198
|
float borderZero = 1.0 - step(0.001, dot(abs(u_borderWidth), vec4(1.0)));
|
|
189
199
|
float edgeWidth = 1.0 / u_pixelRatio;
|
|
190
|
-
float nodeDist;
|
|
191
|
-
float nodeAlpha;
|
|
192
|
-
float shadowAlpha;
|
|
193
|
-
|
|
194
|
-
if(borderZero == 1.0) {
|
|
195
|
-
nodeDist = roundedBox(boxUv, v_halfDimensions - edgeWidth, u_radius);
|
|
196
|
-
nodeAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, nodeDist);
|
|
197
|
-
shadowAlpha = shadowBox(boxUv - u_shadow.xy, v_halfDimensions + u_shadow.w - edgeWidth, u_radius + u_shadow.z);
|
|
198
|
-
resultColor = mix(resultColor, u_shadowColor, shadowAlpha);
|
|
199
|
-
gl_FragColor = mix(resultColor, color, nodeAlpha) * u_alpha;
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
200
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
201
|
+
float nodeDist = roundedBox(boxUv, v_halfDimensions - edgeWidth, u_radius);
|
|
202
|
+
float nodeAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, nodeDist);
|
|
203
|
+
|
|
204
|
+
// Shadow geometry select, branchless: when the border grows the quad
|
|
205
|
+
// beyond the node (outer size exceeds half dimensions on either axis)
|
|
206
|
+
// the shadow hugs the outer border box, otherwise the node box. This
|
|
207
|
+
// replaces a varying-driven if/else (worst offender: diverges per
|
|
208
|
+
// fragment) with a step()/mix() parameter select into ONE shadowBox call.
|
|
209
|
+
// When borderZero, v_outerSize is vec2(0.0) so outerSel is 0 and the
|
|
210
|
+
// node-box parameters win, matching the old zero-border path.
|
|
211
|
+
float outerSel = max(
|
|
212
|
+
step(v_halfDimensions.x, v_outerSize.x),
|
|
213
|
+
step(v_halfDimensions.y, v_outerSize.y)
|
|
214
|
+
);
|
|
215
|
+
float shadowAlpha = shadowBox(
|
|
216
|
+
boxUv + v_outerBorderUv * outerSel - u_shadow.xy,
|
|
217
|
+
mix(v_halfDimensions, v_outerSize, outerSel) + u_shadow.w - edgeWidth,
|
|
218
|
+
mix(u_radius, v_outerBorderRadius, outerSel) + u_shadow.z
|
|
219
|
+
);
|
|
209
220
|
|
|
210
221
|
float outerDist = roundedBox(boxUv + v_outerBorderUv, v_outerSize - edgeWidth, v_outerBorderRadius);
|
|
211
222
|
float innerDist = roundedBox(boxUv + v_innerBorderUv, v_innerSize - edgeWidth, v_innerBorderRadius);
|
|
223
|
+
float outerAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, outerDist);
|
|
224
|
+
float innerAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, innerDist);
|
|
212
225
|
|
|
213
|
-
if(u_borderGap == 0.0) {
|
|
214
|
-
float outerAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, outerDist);
|
|
215
|
-
float innerAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, innerDist);
|
|
216
|
-
resultColor = mix(resultColor, u_shadowColor, shadowAlpha);
|
|
217
|
-
resultColor = mix(resultColor, u_borderColor, outerAlpha * u_borderColor.a);
|
|
218
|
-
resultColor = mix(resultColor, color, innerAlpha);
|
|
219
|
-
gl_FragColor = resultColor * u_alpha;
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
nodeDist = roundedBox(boxUv, v_halfDimensions - edgeWidth, u_radius);
|
|
224
|
-
nodeAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, nodeDist);
|
|
225
226
|
float borderDist = max(-innerDist, outerDist);
|
|
226
227
|
float borderAlpha = 1.0 - smoothstep(-0.5 * edgeWidth, 0.5 * edgeWidth, borderDist);
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
228
|
+
|
|
229
|
+
// Branchless path select -- Mali 400 serializes uniform branches, so all
|
|
230
|
+
// three composites (no gap / gap / zero border) are computed and
|
|
231
|
+
// mix()-selected instead of if/else'd.
|
|
232
|
+
vec4 shadowBase = u_shadowColor * shadowAlpha;
|
|
233
|
+
|
|
234
|
+
vec4 resNoGap = mix(shadowBase, u_borderColor, outerAlpha * u_borderColor.a);
|
|
235
|
+
resNoGap = mix(resNoGap, color, innerAlpha);
|
|
236
|
+
|
|
237
|
+
vec4 resFill = mix(shadowBase, color, nodeAlpha);
|
|
238
|
+
vec4 resGap = mix(resFill, u_borderColor, borderAlpha * u_borderColor.a);
|
|
239
|
+
|
|
240
|
+
float hasGap = step(0.0001, abs(u_borderGap));
|
|
241
|
+
vec4 resultColor = mix(resNoGap, resGap, hasGap);
|
|
242
|
+
resultColor = mix(resultColor, resFill, borderZero);
|
|
230
243
|
gl_FragColor = resultColor * u_alpha;
|
|
231
244
|
}
|
|
232
245
|
`,
|
|
@@ -98,18 +98,23 @@ export const RoundedWithShadow: WebGlShaderType<RoundedWithShadowProps> = {
|
|
|
98
98
|
varying vec4 v_shadowRadius;
|
|
99
99
|
varying vec2 v_shadowSmooth;
|
|
100
100
|
|
|
101
|
+
// Branchless quadrant radius select (r: x TL, y TR, z BR, w BL) --
|
|
102
|
+
// Mali 400-class fragment pipelines serialize any branch, ternaries included.
|
|
103
|
+
float quadRadius(vec2 p, vec4 r) {
|
|
104
|
+
vec2 stepVal = step(vec2(0.0), p);
|
|
105
|
+
return mix(mix(r.x, r.y, stepVal.x), mix(r.w, r.z, stepVal.x), stepVal.y);
|
|
106
|
+
}
|
|
107
|
+
|
|
101
108
|
float roundedBox(vec2 p, vec2 s, vec4 r) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
return (min(max(q.x, q.y), 0.0) + length(max(q, 0.0))) - r.x;
|
|
109
|
+
float rad = quadRadius(p, r);
|
|
110
|
+
vec2 q = abs(p) - s + rad;
|
|
111
|
+
return (min(max(q.x, q.y), 0.0) + length(max(q, 0.0))) - rad;
|
|
106
112
|
}
|
|
107
113
|
|
|
108
114
|
float shadowBox(vec2 p, vec2 s, vec4 r) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
float dist = min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r.x;
|
|
115
|
+
float rad = quadRadius(p, r);
|
|
116
|
+
vec2 q = abs(p) - s + rad;
|
|
117
|
+
float dist = min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - rad;
|
|
113
118
|
return 1.0 - smoothstep(v_shadowSmooth.x, v_shadowSmooth.y, dist);
|
|
114
119
|
}
|
|
115
120
|
|
|
@@ -119,11 +124,8 @@ export const RoundedWithShadow: WebGlShaderType<RoundedWithShadowProps> = {
|
|
|
119
124
|
float boxDist = roundedBox(v_boxUv, v_boxSize, u_radius);
|
|
120
125
|
float roundedAlpha = 1.0 - smoothstep(v_boxSmooth.x, v_boxSmooth.y, boxDist);
|
|
121
126
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
float shadowAlpha = shadowBox(v_shadowBox, v_shadowSize, v_shadowRadius);
|
|
125
|
-
resColor = u_shadow_color * shadowAlpha;
|
|
126
|
-
}
|
|
127
|
+
float shadowAlpha = shadowBox(v_shadowBox, v_shadowSize, v_shadowRadius);
|
|
128
|
+
vec4 resColor = u_shadow_color * (shadowAlpha * step(0.0001, u_shadow_color.a));
|
|
127
129
|
|
|
128
130
|
resColor = mix(resColor, color, min(color.a, roundedAlpha));
|
|
129
131
|
gl_FragColor = resColor * u_alpha;
|
|
@@ -106,11 +106,10 @@ export const Shadow: WebGlShaderType<ShadowProps> = {
|
|
|
106
106
|
float boxDist = box(v_boxUv, v_boxSize);
|
|
107
107
|
float boxAlpha = 1.0 - smoothstep(v_boxSmooth.x, v_boxSmooth.y, boxDist);
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
109
|
+
// Branchless alpha gate -- Mali 400 serializes uniform branches; the
|
|
110
|
+
// step() zeroes the shadow term exactly when u_color.a == 0.
|
|
111
|
+
float shadowDist = shadowBox(v_shadowBox, v_shadowSize, v_shadowRadius);
|
|
112
|
+
vec4 resColor = u_color * (shadowDist * step(0.0001, u_color.a));
|
|
114
113
|
|
|
115
114
|
resColor = mix(resColor, color, min(color.a, boxAlpha));
|
|
116
115
|
gl_FragColor = resColor * u_alpha;
|