Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 1 addition & 18 deletions src/core/shaders/canvas/LinearGradient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,7 @@ export const LinearGradient: CanvasShaderType<
y0: line * Math.sin(angle) + nHeight * 0.5,
x1: line * Math.cos(angle + Math.PI) + nWidth * 0.5,
y1: line * Math.sin(angle + Math.PI) + nHeight * 0.5,
colors: this.props!.colors.map((value, i, arr) => {
const alpha = (value >>> 24) & 0xff;
if (alpha === 0) {
let nearestRGB = value & 0x00ffffff;
for (let step = 1; step < arr.length; step++) {
if (i - step >= 0 && ((arr[i - step]! >>> 24) & 0xff) > 0) {
nearestRGB = arr[i - step]! & 0x00ffffff;
break;
}
if (i + step < arr.length && ((arr[i + step]! >>> 24) & 0xff) > 0) {
nearestRGB = arr[i + step]! & 0x00ffffff;
break;
}
}
value = (value & 0xff000000) | nearestRGB;
}
return this.toColorString(value);
}),
colors: this.props!.colors.map((value) => this.toColorString(value)),
};
},
render(ctx, node, renderContext) {
Expand Down
71 changes: 21 additions & 50 deletions src/core/shaders/webgl/LinearGradient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,51 +22,6 @@ export const LinearGradient: WebGlShaderType<LinearGradientProps> = {
getCacheMarkers(props: LinearGradientProps) {
return `colors:${props.colors.length}`;
},
vertex: `
# ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
# else
precision mediump float;
# endif

attribute vec2 a_position;
attribute vec2 a_textureCoords;
attribute vec4 a_color;

uniform vec2 u_resolution;
uniform float u_pixelRatio;
uniform vec2 u_dimensions;
uniform float u_angle;

varying vec4 v_color;
varying vec2 v_textureCoords;
varying float v_dist;

const float PI = 3.14159265359;

vec2 calcPoint(float d, float angle) {
return d * vec2(cos(angle), sin(angle)) + (u_dimensions * 0.5);
}

void main() {
vec2 normalized = a_position * u_pixelRatio / u_resolution;
vec2 zero_two = normalized * 2.0;
vec2 clip_space = zero_two - 1.0;

gl_Position = vec4(clip_space * vec2(1.0, -1.0), 0, 1);

v_color = a_color;
v_textureCoords = a_textureCoords;

float a = u_angle;
float lineDist = abs(u_dimensions.x * cos(a)) + abs(u_dimensions.y * sin(a));
vec2 f = calcPoint(lineDist * 0.5, a);
vec2 t = calcPoint(lineDist * 0.5, a + PI);
vec2 gradVec = t - f;
float dist = dot(a_textureCoords * u_dimensions - f, gradVec) / dot(gradVec, gradVec);
v_dist = dist;
}
`,
fragment(renderer: WebGlRenderer, props: LinearGradientProps) {
return `
# ifdef GL_FRAGMENT_PRECISION_HIGH
Expand All @@ -75,16 +30,25 @@ export const LinearGradient: WebGlShaderType<LinearGradientProps> = {
precision mediump float;
# endif

#define PI 3.14159265359
#define MAX_STOPS ${props.colors.length}
#define LAST_STOP ${props.colors.length - 1}

uniform float u_alpha;
uniform vec2 u_dimensions;

uniform sampler2D u_texture;

uniform float u_angle;
uniform float u_stops[MAX_STOPS];
uniform vec4 u_colors[MAX_STOPS];

varying vec4 v_color;
varying vec2 v_textureCoords;
varying float v_dist;

vec2 calcPoint(float d, float angle) {
return d * vec2(cos(angle), sin(angle)) + (u_dimensions * 0.5);
}

vec4 getGradientColor(float dist) {
dist = clamp(dist, 0.0, 1.0);
Expand All @@ -105,14 +69,21 @@ export const LinearGradient: WebGlShaderType<LinearGradientProps> = {
return mix(u_colors[i], u_colors[i + 1], lDist);
}
}
return u_colors[LAST_STOP];
}

void main() {
vec4 color = texture2D(u_texture, v_textureCoords) * v_color;
vec4 colorOut = getGradientColor(v_dist);
vec3 blendedRGB = mix(color.rgb, colorOut.rgb, clamp(colorOut.a, 0.0, 1.0));
gl_FragColor = vec4(blendedRGB, color.a);
float a = u_angle;
float lineDist = abs(u_dimensions.x * cos(a)) + abs(u_dimensions.y * sin(a));
vec2 f = calcPoint(lineDist * 0.5, a);
vec2 t = calcPoint(lineDist * 0.5, a + PI);
// Scale to avoid mediump float overflow on platforms without highp
float s = max(u_dimensions.x, u_dimensions.y);
vec2 gradVec = (t - f) / s;
float dist = dot((v_textureCoords.xy * u_dimensions - f) / s, gradVec) / dot(gradVec, gradVec);
vec4 colorOut = getGradientColor(dist);
color = mix(color, colorOut, clamp(colorOut.a, 0.0, 1.0));
gl_FragColor = color * u_alpha;
}
`;
},
Expand Down
Loading