gtk2/gsk/resources/glsl/radial_gradient.glsl
Timm Bäder 982ebf1b69 gradient shaders: Reduce out values as well
We only do 6 color stops here now. Also works around a driver bug.

Fixes #3196
2020-10-05 20:35:34 -04:00

85 lines
2.2 KiB
GLSL

// VERTEX_SHADER
uniform float u_start;
uniform float u_end;
uniform float u_color_stops[6 * 5];
uniform int u_num_color_stops;
uniform vec2 u_radius;
uniform vec2 u_center;
_OUT_ vec2 center;
_OUT_ vec4 color_stops[6];
_OUT_ float color_offsets[6];
_OUT_ float start;
_OUT_ float end;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
center = (u_modelview * vec4(u_center, 0, 1)).xy;
start = u_start;
end = u_end;
for (int i = 0; i < u_num_color_stops; i ++) {
color_offsets[i] = u_color_stops[(i * 5) + 0];
color_stops[i] = gsk_premultiply(vec4(u_color_stops[(i * 5) + 1],
u_color_stops[(i * 5) + 2],
u_color_stops[(i * 5) + 3],
u_color_stops[(i * 5) + 4]));
}
}
// FRAGMENT_SHADER:
#ifdef GSK_LEGACY
uniform int u_num_color_stops;
#else
uniform highp int u_num_color_stops;
#endif
uniform vec2 u_radius;
uniform float u_end;
_IN_ vec2 center;
_IN_ vec4 color_stops[6];
_IN_ float color_offsets[6];
_IN_ float start;
_IN_ float end;
// The offsets in the color stops are relative to the
// start and end values of the gradient.
float abs_offset(float offset) {
return start + ((end - start) * offset);
}
void main() {
vec2 pixel = gsk_get_frag_coord();
vec2 rel = (center - pixel) / (u_radius);
float d = sqrt(dot(rel, rel));
if (d < abs_offset (color_offsets[0])) {
gskSetOutputColor(color_stops[0] * u_alpha);
return;
}
if (d > end) {
gskSetOutputColor(color_stops[u_num_color_stops - 1] * u_alpha);
return;
}
vec4 color = vec4(0, 0, 0, 0);
for (int i = 1; i < u_num_color_stops; i++) {
float last_offset = abs_offset(color_offsets[i - 1]);
float this_offset = abs_offset(color_offsets[i]);
// We have color_stops[i - 1] at last_offset and color_stops[i] at this_offset.
// We now need to map `d` between those two offsets and simply mix linearly between them
if (d >= last_offset && d <= this_offset) {
float f = (d - last_offset) / (this_offset - last_offset);
color = mix(color_stops[i - 1], color_stops[i], f);
break;
}
}
gskSetOutputColor(color * u_alpha);
}