Skip to content

Commit e3a5671

Browse files
authored
Fix/v3 grad shaders (#657)
Changed the way gradients are calculated, someone from the calculated stumbled upon precision issues and I found out the current version had multiple issues. Here's the fix!
2 parents da2ea38 + 7b72097 commit e3a5671

File tree

4 files changed

+76
-31
lines changed

4 files changed

+76
-31
lines changed

src/core/shaders/webgl/LinearGradient.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,17 @@ export const LinearGradient: WebGlShaderType<LinearGradientProps> = {
4949
# endif
5050
5151
#define PI 3.14159265359
52+
#define MAX_STOPS ${props.colors.length}
53+
#define LAST_STOP ${props.colors.length - 1}
5254
5355
uniform float u_alpha;
5456
uniform vec2 u_dimensions;
5557
5658
uniform sampler2D u_texture;
5759
5860
uniform float u_angle;
59-
uniform float u_stops[${props.stops.length}];
60-
uniform vec4 u_colors[${props.colors.length}];
61+
uniform float u_stops[MAX_STOPS];
62+
uniform vec4 u_colors[MAX_STOPS];
6163
6264
varying vec4 v_color;
6365
varying vec2 v_textureCoords;
@@ -66,6 +68,27 @@ export const LinearGradient: WebGlShaderType<LinearGradientProps> = {
6668
return d * vec2(cos(angle), sin(angle)) + (u_dimensions * 0.5);
6769
}
6870
71+
vec4 getGradientColor(float dist) {
72+
dist = clamp(dist, 0.0, 1.0);
73+
74+
if(dist <= u_stops[0]) {
75+
return u_colors[0];
76+
}
77+
78+
if(dist >= u_stops[LAST_STOP]) {
79+
return u_colors[LAST_STOP];
80+
}
81+
82+
for(int i = 0; i < LAST_STOP; i++) {
83+
float left = u_stops[i];
84+
float right = u_stops[i + 1];
85+
if(dist >= left && dist <= right) {
86+
float lDist = smoothstep(left, right, dist);
87+
return mix(u_colors[i], u_colors[i + 1], lDist);
88+
}
89+
}
90+
}
91+
6992
void main() {
7093
vec4 color = texture2D(u_texture, v_textureCoords) * v_color;
7194
float a = u_angle;
@@ -74,7 +97,7 @@ export const LinearGradient: WebGlShaderType<LinearGradientProps> = {
7497
vec2 t = calcPoint(lineDist * 0.5, a + PI);
7598
vec2 gradVec = t - f;
7699
float dist = dot(v_textureCoords.xy * u_dimensions - f, gradVec) / dot(gradVec, gradVec);
77-
${genGradientColors(props.stops.length)}
100+
vec4 colorOut = getGradientColor(dist);
78101
gl_FragColor = mix(color, colorOut, clamp(colorOut.a, 0.0, 1.0));
79102
}
80103
`;

src/core/shaders/webgl/RadialGradient.ts

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@ import {
2121
RadialGradientTemplate,
2222
type RadialGradientProps,
2323
} from '../templates/RadialGradientTemplate.js';
24-
import { genGradientColors } from '../../renderers/webgl/internal/ShaderUtils.js';
25-
import type { WebGlRenderer } from '../../renderers/webgl/WebGlRenderer.js';
2624
import type { WebGlShaderType } from '../../renderers/webgl/WebGlShaderNode.js';
25+
import type { WebGlRenderer } from '../../renderers/webgl/WebGlRenderer.js';
2726

2827
export const RadialGradient: WebGlShaderType<RadialGradientProps> = {
2928
props: RadialGradientTemplate.props,
@@ -48,38 +47,61 @@ export const RadialGradient: WebGlShaderType<RadialGradientProps> = {
4847
},
4948
fragment(renderer: WebGlRenderer, props: RadialGradientProps) {
5049
return `
51-
# ifdef GL_FRAGMENT_PRECISION_HIGH
52-
precision highp float;
53-
# else
54-
precision mediump float;
55-
# endif
50+
# ifdef GL_FRAGMENT_PRECISION_HIGH
51+
precision highp float;
52+
# else
53+
precision mediump float;
54+
# endif
5655
57-
#define PI 3.14159265359
56+
#define MAX_STOPS ${props.colors.length}
57+
#define LAST_STOP ${props.colors.length - 1}
5858
59-
uniform float u_alpha;
60-
uniform vec2 u_dimensions;
59+
uniform float u_alpha;
60+
uniform vec2 u_dimensions;
6161
62-
uniform sampler2D u_texture;
62+
uniform sampler2D u_texture;
6363
64-
uniform vec2 u_projection;
65-
uniform vec2 u_size;
66-
uniform float u_stops[${props.stops.length}];
67-
uniform vec4 u_colors[${props.colors.length}];
64+
uniform vec2 u_projection;
65+
uniform vec2 u_size;
66+
uniform float u_stops[MAX_STOPS];
67+
uniform vec4 u_colors[MAX_STOPS];
6868
69-
varying vec4 v_color;
70-
varying vec2 v_textureCoords;
69+
varying vec4 v_color;
70+
varying vec2 v_textureCoords;
7171
72-
vec2 calcPoint(float d, float angle) {
73-
return d * vec2(cos(angle), sin(angle)) + (u_dimensions * 0.5);
74-
}
72+
vec2 calcPoint(float d, float angle) {
73+
return d * vec2(cos(angle), sin(angle)) + (u_dimensions * 0.5);
74+
}
7575
76-
void main() {
77-
vec4 color = texture2D(u_texture, v_textureCoords) * v_color;
78-
vec2 point = v_textureCoords.xy * u_dimensions;
79-
float dist = length((point - u_projection) / u_size);
80-
${genGradientColors(props.stops.length)}
81-
gl_FragColor = mix(color, colorOut, clamp(colorOut.a, 0.0, 1.0));
82-
}
83-
`;
76+
vec4 getGradientColor(float dist) {
77+
dist = clamp(dist, 0.0, 1.0);
78+
79+
if(dist <= u_stops[0]) {
80+
return u_colors[0];
81+
}
82+
83+
if(dist >= u_stops[LAST_STOP]) {
84+
return u_colors[LAST_STOP];
85+
}
86+
87+
for(int i = 0; i < LAST_STOP; i++) {
88+
float left = u_stops[i];
89+
float right = u_stops[i + 1];
90+
if(dist >= left && dist <= right) {
91+
float lDist = smoothstep(left, right, dist);
92+
return mix(u_colors[i], u_colors[i + 1], lDist);
93+
}
94+
}
95+
}
96+
97+
void main() {
98+
vec4 color = texture2D(u_texture, v_textureCoords) * v_color;
99+
vec2 point = v_textureCoords.xy * u_dimensions;
100+
float dist = length((point - u_projection) / u_size);
101+
102+
vec4 colorOut = getGradientColor(dist);
103+
gl_FragColor = mix(color, colorOut, clamp(colorOut.a, 0.0, 1.0));
104+
}
105+
`;
84106
},
85107
};
4.38 KB
Loading
-5.78 KB
Loading

0 commit comments

Comments
 (0)