55precision mediump float ;
66
77#include < impeller/ color.glsl>
8+ #include < impeller/ constants.glsl>
89#include < impeller/ gradient.glsl>
910#include < impeller/ texture.glsl>
1011#include < impeller/ types.glsl>
@@ -29,6 +30,14 @@ uniform FragInfo {
2930 // / bottom-right), or the circular cap radii for rounded superellipses in
3031 // / radii.xy (top octant in x, right octant in y).
3132 vec4 radii;
33+ // / Gradient parameters:
34+ // / - Linear gradient:
35+ // / xy: Start point in local coordinates.
36+ // / zw: Delta vector (end - start) in local coordinates.
37+ // / - Radial gradient:
38+ // / xy: Center point in local coordinates.
39+ // / zw: Unused (0.0).
40+ vec4 gradient_coords;
3241
3342 // ===========================================================================
3443 // vec2 fields
@@ -39,6 +48,8 @@ uniform FragInfo {
3948 vec2 center;
4049 // / The half-dimensions of the shape (half-width, half-height).
4150 vec2 size;
51+ // / The size of a device pixel in local coordinates.
52+ vec2 pixel_size;
4253
4354 // --- Superellipse Parameters ---
4455 // / The exponent degree (n_x, n_y) of the superellipse curvature.
@@ -53,17 +64,6 @@ uniform FragInfo {
5364 // / rounded superellipse.
5465 vec2 circle_center_right;
5566
56- // --- Gradient Parameters ---
57- // / The starting point of a linear gradient, or the center point of a radial
58- // / gradient.
59- vec2 gradient_start;
60- // / The ending point of a linear gradient, or (radius, 0.0) for a radial
61- // / gradient.
62- vec2 gradient_end;
63- // / Half the size of a single gradient texel in normalized texture
64- // / coordinates.
65- vec2 half_texel;
66-
6767 // ===========================================================================
6868 // float fields
6969 // ===========================================================================
@@ -102,6 +102,13 @@ uniform FragInfo {
102102 // / 2: Mirror
103103 // / 3: Decal
104104 float tile_mode;
105+ // / Half the size of a single gradient texel in normalized texture
106+ // / coordinates along the gradient ramp (x axis).
107+ float half_texel;
108+ // / Inverse gradient length:
109+ // / - Linear gradient: 1.0 / dot(delta, delta)
110+ // / - Radial gradient: 1.0 / radius
111+ float inv_gradient_length;
105112}
106113frag_info;
107114
@@ -115,17 +122,20 @@ vec4 getColor() {
115122 if (frag_info.color_source_type < 0.5 ) {
116123 // Solid color
117124 color = frag_info.color;
118- } else if (frag_info.color_source_type < 1.5 ) {
119- // Linear gradient
120- vec4 gradient_color = IPSampleLinearGradient(
121- color_source_sampler, frag_info.gradient_start, frag_info.gradient_end,
122- v_position, frag_info.half_texel, frag_info.tile_mode, vec4 (0.0 ));
123- color = vec4 (gradient_color.rgb, gradient_color.a * frag_info.color.a);
124125 } else {
125- // Radial gradient
126- vec4 gradient_color = IPSampleRadialGradient(
127- color_source_sampler, frag_info.gradient_start,
128- frag_info.gradient_end.x, v_position, frag_info.half_texel,
126+ float t;
127+ if (frag_info.color_source_type < 1.5 ) {
128+ // Linear gradient
129+ t = IPComputeLinearGradientT(v_position, frag_info.gradient_coords.xy,
130+ frag_info.gradient_coords.zw,
131+ frag_info.inv_gradient_length);
132+ } else {
133+ // Radial gradient
134+ t = IPComputeRadialGradientT(v_position, frag_info.gradient_coords.xy,
135+ frag_info.inv_gradient_length);
136+ }
137+ vec4 gradient_color = IPSampleLinearWithTileMode(
138+ color_source_sampler, vec2 (t, 0.5 ), vec2 (frag_info.half_texel, 0.5 ),
129139 frag_info.tile_mode, vec4 (0.0 ));
130140 color = vec4 (gradient_color.rgb, gradient_color.a * frag_info.color.a);
131141 }
@@ -166,7 +176,7 @@ float distanceFromChamferRect(vec2 p, vec2 half_size, float chamfer_size) {
166176 p = abs (p);
167177 float d1 = max (p.x - half_size.x, p.y - half_size.y);
168178 float d2 =
169- (p.x + p.y - half_size.x - half_size.y + chamfer_size) * 0.70710678 ;
179+ (p.x + p.y - half_size.x - half_size.y + chamfer_size) * kHalfSqrtTwo ;
170180 return max (d1, d2);
171181}
172182
@@ -215,25 +225,14 @@ float distanceFromRoundedSuperellipse(vec2 p,
215225 se_degree);
216226}
217227
218- // Special case pixel size calculation for rectangles. The standard `pixelSize`
219- // function uses SDF derivatives, which gives invalid results for very small
220- // shapes, where adjacent device pixels span across opposing edges of the shape.
221- // This function calculates pixel size for rectangles without using SDF
222- // derivatives.
228+ // Calculates pixel size for rectangles using frag_info.pixel_size.
223229float rectPixelSize(vec2 p) {
224- // The change in local coordinates per horizontal device pixel (device_dx)
225- // and vertical device pixel (device_dy).
226- vec2 device_dx = dFdx (v_position);
227- vec2 device_dy = dFdy (v_position);
228- // The size of a device pixel in terms of local coordinates.
229- vec2 device_pixel_size = vec2 (length (vec2 (device_dx.x, device_dy.x)),
230- length (vec2 (device_dx.y, device_dy.y)));
231-
232230 // Get pixel size in the direction perpendicular to the closest edge of the
233- // rectangle: device_pixel_size .x when closer to a vertical edge, and
234- // pixel_size.y when closer to a horizontal edge.
231+ // rectangle: frag_info.pixel_size .x when closer to a vertical edge, and
232+ // frag_info. pixel_size.y when closer to a horizontal edge.
235233 vec2 distance = abs (abs (p) - frag_info.size);
236- return (distance .x < distance .y) ? device_pixel_size.x : device_pixel_size.y;
234+ return (distance .x < distance .y) ? frag_info.pixel_size.x
235+ : frag_info.pixel_size.y;
237236}
238237
239238// Special case pixel size calculation for rounded rectangles, similar to
0 commit comments