gsk: Give ngl its own shader sources

We may want to change the interface between the
shaders and the renderer for ngl, and therefore,
sharing the shaders between gl and ngl will not
be practical, going forward.
This commit is contained in:
Matthias Clasen 2021-03-11 21:31:31 -05:00
parent 7f292d34bd
commit 3252f1e301
23 changed files with 1241 additions and 21 deletions

View File

@ -20,13 +20,17 @@ def replace_if_changed(new, old):
else:
os.remove(new)
source_shaders = []
gl_source_shaders = []
ngl_source_shaders = []
vulkan_compiled_shaders = []
vulkan_shaders = []
for f in sys.argv[2:]:
if f.endswith('.glsl'):
source_shaders.append(f)
if f.startswith('ngl'):
ngl_source_shaders.append(f);
else:
gl_source_shaders.append(f)
elif f.endswith('.spv'):
vulkan_compiled_shaders.append(f)
elif f.endswith('.frag') or f.endswith('.vert'):
@ -40,11 +44,16 @@ xml = '''<?xml version='1.0' encoding='UTF-8'?>
'''
for f in source_shaders:
for f in gl_source_shaders:
xml += ' <file alias=\'glsl/{0}\'>resources/glsl/{0}</file>\n'.format(os.path.basename(f))
xml += '\n'
for f in ngl_source_shaders:
xml += ' <file alias=\'ngl/{0}\'>ngl/resources/{0}</file>\n'.format(os.path.basename(f))
xml += '\n'
for f in vulkan_compiled_shaders:
xml += ' <file alias=\'vulkan/{0}\'>resources/vulkan/{0}</file>\n'.format(os.path.basename(f))

View File

@ -20,6 +20,28 @@ gsk_private_gl_shaders = [
'resources/glsl/custom.glsl',
]
gsk_private_ngl_shaders = [
'ngl/resources/preamble.glsl',
'ngl/resources/preamble.fs.glsl',
'ngl/resources/preamble.vs.glsl',
'ngl/resources/border.glsl',
'ngl/resources/blit.glsl',
'ngl/resources/coloring.glsl',
'ngl/resources/color.glsl',
'ngl/resources/linear_gradient.glsl',
'ngl/resources/radial_gradient.glsl',
'ngl/resources/conic_gradient.glsl',
'ngl/resources/color_matrix.glsl',
'ngl/resources/blur.glsl',
'ngl/resources/inset_shadow.glsl',
'ngl/resources/outset_shadow.glsl',
'ngl/resources/unblurred_outset_shadow.glsl',
'ngl/resources/cross_fade.glsl',
'ngl/resources/blend.glsl',
'ngl/resources/repeat.glsl',
'ngl/resources/custom.glsl',
]
gsk_public_sources = files([
'gskdiff.c',
'gskcairorenderer.c',
@ -150,6 +172,7 @@ gsk_resources_xml = configure_file(output: 'gsk.resources.xml',
find_program('gen-gsk-gresources-xml.py'),
'@OUTPUT@',
gsk_private_gl_shaders,
gsk_private_ngl_shaders,
gsk_private_vulkan_compiled_shaders,
gsk_private_vulkan_shaders
],

View File

@ -336,13 +336,13 @@ gsk_ngl_driver_load_programs (GskNglDriver *self,
/* Setup preambles that are shared by all shaders */
gsk_ngl_compiler_set_preamble_from_resource (compiler,
GSK_NGL_COMPILER_ALL,
"/org/gtk/libgsk/glsl/preamble.glsl");
"/org/gtk/libgsk/ngl/preamble.glsl");
gsk_ngl_compiler_set_preamble_from_resource (compiler,
GSK_NGL_COMPILER_VERTEX,
"/org/gtk/libgsk/glsl/preamble.vs.glsl");
"/org/gtk/libgsk/ngl/preamble.vs.glsl");
gsk_ngl_compiler_set_preamble_from_resource (compiler,
GSK_NGL_COMPILER_FRAGMENT,
"/org/gtk/libgsk/glsl/preamble.fs.glsl");
"/org/gtk/libgsk/ngl/preamble.fs.glsl");
/* Setup attributes that are provided via VBO */
gsk_ngl_compiler_bind_attribute (compiler, "aPosition", 0);

View File

@ -1,69 +1,69 @@
GSK_NGL_DEFINE_PROGRAM (blend,
"/org/gtk/libgsk/glsl/blend.glsl",
"/org/gtk/libgsk/ngl/blend.glsl",
GSK_NGL_ADD_UNIFORM (1, BLEND_SOURCE2, u_source2)
GSK_NGL_ADD_UNIFORM (2, BLEND_MODE, u_mode))
GSK_NGL_DEFINE_PROGRAM (blit,
"/org/gtk/libgsk/glsl/blit.glsl",
"/org/gtk/libgsk/ngl/blit.glsl",
GSK_NGL_NO_UNIFORMS)
GSK_NGL_DEFINE_PROGRAM (blur,
"/org/gtk/libgsk/glsl/blur.glsl",
"/org/gtk/libgsk/ngl/blur.glsl",
GSK_NGL_ADD_UNIFORM (1, BLUR_RADIUS, u_blur_radius)
GSK_NGL_ADD_UNIFORM (2, BLUR_SIZE, u_blur_size)
GSK_NGL_ADD_UNIFORM (3, BLUR_DIR, u_blur_dir))
GSK_NGL_DEFINE_PROGRAM (border,
"/org/gtk/libgsk/glsl/border.glsl",
"/org/gtk/libgsk/ngl/border.glsl",
GSK_NGL_ADD_UNIFORM (1, BORDER_COLOR, u_color)
GSK_NGL_ADD_UNIFORM (2, BORDER_WIDTHS, u_widths)
GSK_NGL_ADD_UNIFORM (3, BORDER_OUTLINE_RECT, u_outline_rect))
GSK_NGL_DEFINE_PROGRAM (color,
"/org/gtk/libgsk/glsl/color.glsl",
"/org/gtk/libgsk/ngl/color.glsl",
GSK_NGL_ADD_UNIFORM (1, COLOR_COLOR, u_color))
GSK_NGL_DEFINE_PROGRAM (coloring,
"/org/gtk/libgsk/glsl/coloring.glsl",
"/org/gtk/libgsk/ngl/coloring.glsl",
GSK_NGL_ADD_UNIFORM (1, COLORING_COLOR, u_color))
GSK_NGL_DEFINE_PROGRAM (color_matrix,
"/org/gtk/libgsk/glsl/color_matrix.glsl",
"/org/gtk/libgsk/ngl/color_matrix.glsl",
GSK_NGL_ADD_UNIFORM (1, COLOR_MATRIX_COLOR_MATRIX, u_color_matrix)
GSK_NGL_ADD_UNIFORM (2, COLOR_MATRIX_COLOR_OFFSET, u_color_offset))
GSK_NGL_DEFINE_PROGRAM (conic_gradient,
"/org/gtk/libgsk/glsl/conic_gradient.glsl",
"/org/gtk/libgsk/ngl/conic_gradient.glsl",
GSK_NGL_ADD_UNIFORM (1, CONIC_GRADIENT_COLOR_STOPS, u_color_stops)
GSK_NGL_ADD_UNIFORM (2, CONIC_GRADIENT_NUM_COLOR_STOPS, u_num_color_stops)
GSK_NGL_ADD_UNIFORM (3, CONIC_GRADIENT_GEOMETRY, u_geometry))
GSK_NGL_DEFINE_PROGRAM (cross_fade,
"/org/gtk/libgsk/glsl/cross_fade.glsl",
"/org/gtk/libgsk/ngl/cross_fade.glsl",
GSK_NGL_ADD_UNIFORM (1, CROSS_FADE_PROGRESS, u_progress)
GSK_NGL_ADD_UNIFORM (2, CROSS_FADE_SOURCE2, u_source2))
GSK_NGL_DEFINE_PROGRAM (inset_shadow,
"/org/gtk/libgsk/glsl/inset_shadow.glsl",
"/org/gtk/libgsk/ngl/inset_shadow.glsl",
GSK_NGL_ADD_UNIFORM (1, INSET_SHADOW_COLOR, u_color)
GSK_NGL_ADD_UNIFORM (2, INSET_SHADOW_SPREAD, u_spread)
GSK_NGL_ADD_UNIFORM (3, INSET_SHADOW_OFFSET, u_offset)
GSK_NGL_ADD_UNIFORM (4, INSET_SHADOW_OUTLINE_RECT, u_outline_rect))
GSK_NGL_DEFINE_PROGRAM (linear_gradient,
"/org/gtk/libgsk/glsl/linear_gradient.glsl",
"/org/gtk/libgsk/ngl/linear_gradient.glsl",
GSK_NGL_ADD_UNIFORM (1, LINEAR_GRADIENT_COLOR_STOPS, u_color_stops)
GSK_NGL_ADD_UNIFORM (2, LINEAR_GRADIENT_NUM_COLOR_STOPS, u_num_color_stops)
GSK_NGL_ADD_UNIFORM (3, LINEAR_GRADIENT_POINTS, u_points)
GSK_NGL_ADD_UNIFORM (4, LINEAR_GRADIENT_REPEAT, u_repeat))
GSK_NGL_DEFINE_PROGRAM (outset_shadow,
"/org/gtk/libgsk/glsl/outset_shadow.glsl",
"/org/gtk/libgsk/ngl/outset_shadow.glsl",
GSK_NGL_ADD_UNIFORM (1, OUTSET_SHADOW_COLOR, u_color)
GSK_NGL_ADD_UNIFORM (2, OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))
GSK_NGL_DEFINE_PROGRAM (radial_gradient,
"/org/gtk/libgsk/glsl/radial_gradient.glsl",
"/org/gtk/libgsk/ngl/radial_gradient.glsl",
GSK_NGL_ADD_UNIFORM (1, RADIAL_GRADIENT_COLOR_STOPS, u_color_stops)
GSK_NGL_ADD_UNIFORM (2, RADIAL_GRADIENT_NUM_COLOR_STOPS, u_num_color_stops)
GSK_NGL_ADD_UNIFORM (3, RADIAL_GRADIENT_REPEAT, u_repeat)
@ -71,12 +71,12 @@ GSK_NGL_DEFINE_PROGRAM (radial_gradient,
GSK_NGL_ADD_UNIFORM (5, RADIAL_GRADIENT_GEOMETRY, u_geometry))
GSK_NGL_DEFINE_PROGRAM (repeat,
"/org/gtk/libgsk/glsl/repeat.glsl",
"/org/gtk/libgsk/ngl/repeat.glsl",
GSK_NGL_ADD_UNIFORM (1, REPEAT_CHILD_BOUNDS, u_child_bounds)
GSK_NGL_ADD_UNIFORM (2, REPEAT_TEXTURE_RECT, u_texture_rect))
GSK_NGL_DEFINE_PROGRAM (unblurred_outset_shadow,
"/org/gtk/libgsk/glsl/unblurred_outset_shadow.glsl",
"/org/gtk/libgsk/ngl/unblurred_outset_shadow.glsl",
GSK_NGL_ADD_UNIFORM (1, UNBLURRED_OUTSET_SHADOW_COLOR, u_color)
GSK_NGL_ADD_UNIFORM (2, UNBLURRED_OUTSET_SHADOW_SPREAD, u_spread)
GSK_NGL_ADD_UNIFORM (3, UNBLURRED_OUTSET_SHADOW_OFFSET, u_offset)

View File

@ -0,0 +1,310 @@
// VERTEX_SHADER:
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
}
// FRAGMENT_SHADER:
uniform int u_mode;
uniform sampler2D u_source2;
float
combine (float source, float backdrop)
{
return source + backdrop * (1.0 - source);
}
vec4
composite (vec4 Cs, vec4 Cb, vec3 B)
{
float ao = Cs.a + Cb.a * (1.0 - Cs.a);
vec3 Co = (Cs.a*(1.0 - Cb.a)*Cs.rgb + Cs.a*Cb.a*B + (1.0 - Cs.a)*Cb.a*Cb.rgb) / ao;
return vec4(Co, ao);
}
vec4
normal (vec4 Cs, vec4 Cb)
{
return composite (Cs, Cb, Cs.rgb);
}
vec4
multiply (vec4 Cs, vec4 Cb)
{
return composite (Cs, Cb, Cs.rgb * Cb.rgb);
}
vec4
difference (vec4 Cs, vec4 Cb)
{
return composite (Cs, Cb, abs(Cs.rgb - Cb.rgb));
}
vec4
screen (vec4 Cs, vec4 Cb)
{
return composite (Cs, Cb, Cs.rgb + Cb.rgb - Cs.rgb * Cb.rgb);
}
float
hard_light (float source, float backdrop)
{
if (source <= 0.5)
return 2.0 * backdrop * source;
else
return 2.0 * (backdrop + source - backdrop * source) - 1.0;
}
vec4
hard_light (vec4 Cs, vec4 Cb)
{
vec3 B = vec3 (hard_light (Cs.r, Cb.r),
hard_light (Cs.g, Cb.g),
hard_light (Cs.b, Cb.b));
return composite (Cs, Cb, B);
}
float
soft_light (float source, float backdrop)
{
float db;
if (backdrop <= 0.25)
db = ((16.0 * backdrop - 12.0) * backdrop + 4.0) * backdrop;
else
db = sqrt (backdrop);
if (source <= 0.5)
return backdrop - (1.0 - 2.0 * source) * backdrop * (1.0 - backdrop);
else
return backdrop + (2.0 * source - 1.0) * (db - backdrop);
}
vec4
soft_light (vec4 Cs, vec4 Cb)
{
vec3 B = vec3 (soft_light (Cs.r, Cb.r),
soft_light (Cs.g, Cb.g),
soft_light (Cs.b, Cb.b));
return composite (Cs, Cb, B);
}
vec4
overlay (vec4 Cs, vec4 Cb)
{
vec3 B = vec3 (hard_light (Cb.r, Cs.r),
hard_light (Cb.g, Cs.g),
hard_light (Cb.b, Cs.b));
return composite (Cs, Cb, B);
}
vec4
darken (vec4 Cs, vec4 Cb)
{
vec3 B = min (Cs.rgb, Cb.rgb);
return composite (Cs, Cb, B);
}
vec4
lighten (vec4 Cs, vec4 Cb)
{
vec3 B = max (Cs.rgb, Cb.rgb);
return composite (Cs, Cb, B);
}
float
color_dodge (float source, float backdrop)
{
return (source == 1.0) ? source : min (backdrop / (1.0 - source), 1.0);
}
vec4
color_dodge (vec4 Cs, vec4 Cb)
{
vec3 B = vec3 (color_dodge (Cs.r, Cb.r),
color_dodge (Cs.g, Cb.g),
color_dodge (Cs.b, Cb.b));
return composite (Cs, Cb, B);
}
float
color_burn (float source, float backdrop)
{
return (source == 0.0) ? source : max ((1.0 - ((1.0 - backdrop) / source)), 0.0);
}
vec4
color_burn (vec4 Cs, vec4 Cb)
{
vec3 B = vec3 (color_burn (Cs.r, Cb.r),
color_burn (Cs.g, Cb.g),
color_burn (Cs.b, Cb.b));
return composite (Cs, Cb, B);
}
vec4
exclusion (vec4 Cs, vec4 Cb)
{
vec3 B = Cb.rgb + Cs.rgb - 2.0 * Cb.rgb * Cs.rgb;
return composite (Cs, Cb, B);
}
float
lum (vec3 c)
{
return 0.3 * c.r + 0.59 * c.g + 0.11 * c.b;
}
vec3
clip_color (vec3 c)
{
float l = lum (c);
float n = min (c.r, min (c.g, c.b));
float x = max (c.r, max (c.g, c.b));
if (n < 0.0) c = l + (((c - l) * l) / (l - n));
if (x > 1.0) c = l + (((c - l) * (1.0 - l)) / (x - l));
return c;
}
vec3
set_lum (vec3 c, float l)
{
float d = l - lum (c);
return clip_color (vec3 (c.r + d, c.g + d, c.b + d));
}
float
sat (vec3 c)
{
return max (c.r, max (c.g, c.b)) - min (c.r, min (c.g, c.b));
}
vec3
set_sat (vec3 c, float s)
{
float cmin = min (c.r, min (c.g, c.b));
float cmax = max (c.r, max (c.g, c.b));
vec3 res;
if (cmax == cmin)
res = vec3 (0, 0, 0);
else
{
if (c.r == cmax)
{
if (c.g == cmin)
{
res.b = ((c.b - cmin) * s) / (cmax - cmin);
res.g = 0.0;
}
else
{
res.g = ((c.g - cmin) * s) / (cmax - cmin);
res.b = 0.0;
}
res.r = s;
}
else if (c.g == cmax)
{
if (c.r == cmin)
{
res.b = ((c.b - cmin) * s) / (cmax - cmin);
res.r = 0.0;
}
else
{
res.r = ((c.r - cmin) * s) / (cmax - cmin);
res.b = 0.0;
}
res.g = s;
}
else
{
if (c.r == cmin)
{
res.g = ((c.g - cmin) * s) / (cmax - cmin);
res.r = 0.0;
}
else
{
res.r = ((c.r - cmin) * s) / (cmax - cmin);
res.g = 0.0;
}
res.b = s;
}
}
return res;
}
vec4
color (vec4 Cs, vec4 Cb)
{
vec3 B = set_lum (Cs.rgb, lum (Cb.rgb));
return composite (Cs, Cb, B);
}
vec4
hue (vec4 Cs, vec4 Cb)
{
vec3 B = set_lum (set_sat (Cs.rgb, sat (Cb.rgb)), lum (Cb.rgb));
return composite (Cs, Cb, B);
}
vec4
saturation (vec4 Cs, vec4 Cb)
{
vec3 B = set_lum (set_sat (Cb.rgb, sat (Cs.rgb)), lum (Cb.rgb));
return composite (Cs, Cb, B);
}
vec4
luminosity (vec4 Cs, vec4 Cb)
{
vec3 B = set_lum (Cb.rgb, lum (Cs.rgb));
return composite (Cs, Cb, B);
}
void main() {
vec4 bottom_color = GskTexture(u_source, vUv);
vec4 top_color = GskTexture(u_source2, vUv);
vec4 result;
if (u_mode == 0)
result = normal(top_color, bottom_color);
else if (u_mode == 1)
result = multiply(top_color, bottom_color);
else if (u_mode == 2)
result = screen(top_color, bottom_color);
else if (u_mode == 3)
result = overlay(top_color, bottom_color);
else if (u_mode == 4)
result = darken(top_color, bottom_color);
else if (u_mode == 5)
result = lighten(top_color, bottom_color);
else if (u_mode == 6)
result = color_dodge(top_color, bottom_color);
else if (u_mode == 7)
result = color_burn(top_color, bottom_color);
else if (u_mode == 8)
result = hard_light(top_color, bottom_color);
else if (u_mode == 9)
result = soft_light(top_color, bottom_color);
else if (u_mode == 10)
result = difference(top_color, bottom_color);
else if (u_mode == 11)
result = exclusion(top_color, bottom_color);
else if (u_mode == 12)
result = color(top_color, bottom_color);
else if (u_mode == 13)
result = hue(top_color, bottom_color);
else if (u_mode == 14)
result = saturation(top_color, bottom_color);
else if (u_mode == 15)
result = luminosity(top_color, bottom_color);
else
discard;
gskSetOutputColor(result * u_alpha);
}

View File

@ -0,0 +1,13 @@
// VERTEX_SHADER:
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
}
// FRAGMENT_SHADER:
void main() {
vec4 diffuse = GskTexture(u_source, vUv);
gskSetOutputColor(diffuse * u_alpha);
}

View File

@ -0,0 +1,55 @@
// VERTEX_SHADER:
uniform float u_blur_radius;
uniform vec2 u_blur_size;
uniform vec2 u_blur_dir;
_OUT_ vec2 pixel_step;
_OUT_ float pixels_per_side;
_OUT_ vec3 initial_gaussian;
const float PI = 3.14159265;
const float RADIUS_MULTIPLIER = 2.0;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
pixel_step = (vec2(1.0) / u_blur_size) * u_blur_dir;
pixels_per_side = floor(u_blur_radius * RADIUS_MULTIPLIER / 2.0);
float sigma = u_blur_radius / 2.0; // *shrug*
initial_gaussian.x = 1.0 / (sqrt(2.0 * PI) * sigma);
initial_gaussian.y = exp(-0.5 / (sigma * sigma));
initial_gaussian.z = initial_gaussian.y * initial_gaussian.y;
}
// FRAGMENT_SHADER:
_IN_ vec2 pixel_step;
_IN_ float pixels_per_side;
_IN_ vec3 initial_gaussian;
// blur_radius 0 is NOT supported and MUST be caught before.
// Partially from http://callumhay.blogspot.com/2010/09/gaussian-blur-shader-glsl.html
void main() {
vec3 incrementalGaussian = initial_gaussian;
float coefficientSum = 0.0;
vec4 sum = GskTexture(u_source, vUv) * incrementalGaussian.x;
coefficientSum += incrementalGaussian.x;
incrementalGaussian.xy *= incrementalGaussian.yz;
vec2 p = pixel_step;
for (int i = 1; i <= int(pixels_per_side); i++) {
sum += GskTexture(u_source, vUv - p) * incrementalGaussian.x;
sum += GskTexture(u_source, vUv + p) * incrementalGaussian.x;
coefficientSum += 2.0 * incrementalGaussian.x;
incrementalGaussian.xy *= incrementalGaussian.yz;
p += pixel_step;
}
gskSetOutputColor(sum / coefficientSum);
}

View File

@ -0,0 +1,40 @@
// VERTEX_SHADER:
uniform vec4 u_color;
uniform vec4 u_widths;
uniform vec4[3] u_outline_rect;
_OUT_ vec4 final_color;
_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
final_color = gsk_premultiply(u_color) * u_alpha;
GskRoundedRect outside = gsk_create_rect(u_outline_rect);
GskRoundedRect inside = gsk_rounded_rect_shrink (outside, u_widths);
gsk_rounded_rect_transform(outside, u_modelview);
gsk_rounded_rect_transform(inside, u_modelview);
gsk_rounded_rect_encode(outside, transformed_outside_outline);
gsk_rounded_rect_encode(inside, transformed_inside_outline);
}
// FRAGMENT_SHADER:
uniform vec4[3] u_outline_rect;
_IN_ vec4 final_color;
_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
vec2 frag = gsk_get_frag_coord();
float alpha = clamp(gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outside_outline), frag) -
gsk_rounded_rect_coverage(gsk_decode_rect(transformed_inside_outline), frag),
0.0, 1.0);
gskSetOutputColor(final_color * alpha);
}

View File

@ -0,0 +1,18 @@
// VERTEX_SHADER:
uniform vec4 u_color;
_OUT_ vec4 final_color;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
final_color = gsk_premultiply(u_color) * u_alpha;
}
// FRAGMENT_SHADER:
_IN_ vec4 final_color;
void main() {
gskSetOutputColor(final_color);
}

View File

@ -0,0 +1,25 @@
// VERTEX_SHADER:
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
}
// FRAGMENT_SHADER:
uniform mat4 u_color_matrix;
uniform vec4 u_color_offset;
void main() {
vec4 color = GskTexture(u_source, vUv);
// Un-premultilpy
if (color.a != 0.0)
color.rgb /= color.a;
color = u_color_matrix * color + u_color_offset;
color = clamp(color, 0.0, 1.0);
color.rgb *= color.a;
gskSetOutputColor(color * u_alpha);
}

View File

@ -0,0 +1,22 @@
// VERTEX_SHADER:
uniform vec4 u_color;
_OUT_ vec4 final_color;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
final_color = gsk_premultiply(u_color) * u_alpha;
}
// FRAGMENT_SHADER:
_IN_ vec4 final_color;
void main() {
vec4 diffuse = GskTexture(u_source, vUv);
gskSetOutputColor(final_color * diffuse.a);
}

View File

@ -0,0 +1,73 @@
// VERTEX_SHADER
uniform vec4 u_geometry;
_NOPERSPECTIVE_ _OUT_ vec2 coord;
void main() {
gl_Position = u_projection * (u_modelview * vec4(aPosition, 0.0, 1.0));
vec2 mv0 = u_modelview[0].xy;
vec2 mv1 = u_modelview[1].xy;
vec2 offset = aPosition - u_geometry.xy;
coord = vec2(dot(mv0, offset),
dot(mv1, offset));
}
// FRAGMENT_SHADER:
#ifdef GSK_LEGACY
uniform int u_num_color_stops;
#else
uniform highp int u_num_color_stops; // Why? Because it works like this.
#endif
uniform vec4 u_geometry;
uniform float u_color_stops[6 * 5];
_NOPERSPECTIVE_ _IN_ vec2 coord;
float get_offset(int index) {
return u_color_stops[5 * index];
}
vec4 get_color(int index) {
int base = 5 * index + 1;
return vec4(u_color_stops[base],
u_color_stops[base + 1],
u_color_stops[base + 2],
u_color_stops[base + 3]);
}
void main() {
// direction of point in range [-PI, PI]
vec2 pos = floor(coord);
float angle = atan(pos.y, pos.x);
// fract() does the modulo here, so now we have progress
// into the current conic
float offset = fract(angle * u_geometry.z + u_geometry.w);
if (offset < get_offset(0)) {
gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha));
return;
}
int n = u_num_color_stops - 1;
for (int i = 0; i < n; i++) {
float curr_offset = get_offset(i);
float next_offset = get_offset(i + 1);
if (offset >= curr_offset && offset < next_offset) {
float f = (offset - curr_offset) / (next_offset - curr_offset);
vec4 curr_color = gsk_premultiply(get_color(i));
vec4 next_color = gsk_premultiply(get_color(i + 1));
vec4 color = mix(curr_color, next_color, f);
gskSetOutputColor(color * u_alpha);
return;
}
}
gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha));
}

View File

@ -0,0 +1,20 @@
// VERTEX_SHADER:
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
}
// FRAGMENT_SHADER:
uniform float u_progress;
uniform sampler2D u_source2;
void main() {
vec4 source1 = GskTexture(u_source, vUv); // start child
vec4 source2 = GskTexture(u_source2, vUv); // end child
float p_start = (1.0 - u_progress) * u_alpha;
float p_end = u_progress * u_alpha;
vec4 color = (p_start * source1) + (p_end * source2);
gskSetOutputColor(color);
}

View File

@ -0,0 +1,21 @@
// VERTEX_SHADER:
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
}
// FRAGMENT_SHADER:
// The shader supplies:
void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv);
uniform vec2 u_size;
uniform sampler2D u_source2;
uniform sampler2D u_source3;
uniform sampler2D u_source4;
void main() {
vec4 fragColor;
vec2 fragCoord = vec2(vUv.x * u_size.x, (1.0-vUv.y) * u_size.y);
mainImage(fragColor, fragCoord, u_size, vUv);
gskSetOutputColor(fragColor);
}

View File

@ -0,0 +1,41 @@
// VERTEX_SHADER:
uniform vec4 u_color;
uniform float u_spread;
uniform vec2 u_offset;
uniform vec4[3] u_outline_rect;
_OUT_ vec4 final_color;
_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
final_color = gsk_premultiply(u_color) * u_alpha;
GskRoundedRect outside = gsk_create_rect(u_outline_rect);
GskRoundedRect inside = gsk_rounded_rect_shrink(outside, vec4(u_spread));
gsk_rounded_rect_offset(inside, u_offset);
gsk_rounded_rect_transform(outside, u_modelview);
gsk_rounded_rect_transform(inside, u_modelview);
gsk_rounded_rect_encode(outside, transformed_outside_outline);
gsk_rounded_rect_encode(inside, transformed_inside_outline);
}
// FRAGMENT_SHADER:
_IN_ vec4 final_color;
_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
vec2 frag = gsk_get_frag_coord();
float alpha = clamp(gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outside_outline), frag) -
gsk_rounded_rect_coverage(gsk_decode_rect(transformed_inside_outline), frag),
0.0, 1.0);
gskSetOutputColor(final_color * alpha);
}

View File

@ -0,0 +1,95 @@
// VERTEX_SHADER
uniform vec4 u_points;
_NOPERSPECTIVE_ _OUT_ vec4 info;
void main() {
gl_Position = u_projection * (u_modelview * vec4(aPosition, 0.0, 1.0));
vec2 mv0 = u_modelview[0].xy;
vec2 mv1 = u_modelview[1].xy;
vec2 offset = aPosition - u_points.xy;
vec2 coord = vec2(dot(mv0, offset),
dot(mv1, offset));
// Original equation:
// VS | maxDist = length(end - start);
// VS | gradient = end - start;
// VS | gradientLength = length(gradient);
// FS | pos = frag_coord - start
// FS | proj = (dot(gradient, pos) / (gradientLength * gradientLength)) * gradient
// FS | offset = length(proj) / maxDist
// Simplified formula derivation:
// 1. Notice that maxDist = gradientLength:
// offset = length(proj) / gradientLength
// 2. Let gnorm = gradient / gradientLength, then:
// proj = (dot(gnorm * gradientLength, pos) / (gradientLength * gradientLength)) * (gnorm * gradientLength) =
// = dot(gnorm, pos) * gnorm
// 3. Since gnorm is unit length then:
// length(proj) = length(dot(gnorm, pos) * gnorm) = dot(gnorm, pos)
// 4. We can avoid the FS division by passing a scaled pos from the VS:
// offset = dot(gnorm, pos) / gradientLength = dot(gnorm, pos / gradientLength)
// 5. 1.0 / length(gradient) is inversesqrt(dot(gradient, gradient)) in GLSL
vec2 gradient = vec2(dot(mv0, u_points.zw),
dot(mv1, u_points.zw));
float rcp_gradient_length = inversesqrt(dot(gradient, gradient));
info = rcp_gradient_length * vec4(coord, gradient);
}
// FRAGMENT_SHADER:
#ifdef GSK_LEGACY
uniform int u_num_color_stops;
#else
uniform highp int u_num_color_stops; // Why? Because it works like this.
#endif
uniform float u_color_stops[6 * 5];
uniform bool u_repeat;
_NOPERSPECTIVE_ _IN_ vec4 info;
float get_offset(int index) {
return u_color_stops[5 * index];
}
vec4 get_color(int index) {
int base = 5 * index + 1;
return vec4(u_color_stops[base],
u_color_stops[base + 1],
u_color_stops[base + 2],
u_color_stops[base + 3]);
}
void main() {
float offset = dot(info.xy, info.zw);
if (u_repeat) {
offset = fract(offset);
}
if (offset < get_offset(0)) {
gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha));
return;
}
int n = u_num_color_stops - 1;
for (int i = 0; i < n; i++) {
float curr_offset = get_offset(i);
float next_offset = get_offset(i + 1);
if (offset >= curr_offset && offset < next_offset) {
float f = (offset - curr_offset) / (next_offset - curr_offset);
vec4 curr_color = gsk_premultiply(get_color(i));
vec4 next_color = gsk_premultiply(get_color(i + 1));
vec4 color = mix(curr_color, next_color, f);
gskSetOutputColor(color * u_alpha);
return;
}
}
gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha));
}

View File

@ -0,0 +1,33 @@
// VERTEX_SHADER:
uniform vec4 u_color;
uniform vec4[3] u_outline_rect;
_OUT_ vec4 final_color;
_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outline;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
final_color = gsk_premultiply(u_color) * u_alpha;
GskRoundedRect outline = gsk_create_rect(u_outline_rect);
gsk_rounded_rect_transform(outline, u_modelview);
gsk_rounded_rect_encode(outline, transformed_outline);
}
// FRAGMENT_SHADER:
_IN_ vec4 final_color;
_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outline;
void main() {
vec2 frag = gsk_get_frag_coord();
float alpha = GskTexture(u_source, vUv).a;
alpha *= (1.0 - clamp(gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outline), frag), 0.0, 1.0));
vec4 color = final_color * alpha;
gskSetOutputColor(color);
}

View File

@ -0,0 +1,139 @@
uniform sampler2D u_source;
uniform mat4 u_projection;
uniform mat4 u_modelview;
uniform float u_alpha;// = 1.0;
uniform vec4 u_viewport;
uniform vec4[3] u_clip_rect;
#if defined(GSK_LEGACY)
_OUT_ vec4 outputColor;
#elif !defined(GSK_GLES)
_OUT_ vec4 outputColor;
#endif
_IN_ vec2 vUv;
GskRoundedRect gsk_decode_rect(_GSK_ROUNDED_RECT_UNIFORM_ r)
{
#if defined(GSK_GLES) || defined(GSK_LEGACY)
return GskRoundedRect(r[0], r[1], r[2]);
#else
return r;
#endif
}
float
gsk_ellipsis_dist (vec2 p, vec2 radius)
{
if (radius == vec2(0, 0))
return 0.0;
vec2 p0 = p / radius;
vec2 p1 = 2.0 * p0 / radius;
return (dot(p0, p0) - 1.0) / length (p1);
}
float
gsk_ellipsis_coverage (vec2 point, vec2 center, vec2 radius)
{
float d = gsk_ellipsis_dist (point - center, radius);
return clamp (0.5 - d, 0.0, 1.0);
}
float
gsk_rounded_rect_coverage (GskRoundedRect r, vec2 p)
{
if (p.x < r.bounds.x || p.y < r.bounds.y ||
p.x >= r.bounds.z || p.y >= r.bounds.w)
return 0.0;
vec2 ref_tl = r.corner_points1.xy;
vec2 ref_tr = r.corner_points1.zw;
vec2 ref_br = r.corner_points2.xy;
vec2 ref_bl = r.corner_points2.zw;
if (p.x >= ref_tl.x && p.x >= ref_bl.x &&
p.x <= ref_tr.x && p.x <= ref_br.x)
return 1.0;
if (p.y >= ref_tl.y && p.y >= ref_tr.y &&
p.y <= ref_bl.y && p.y <= ref_br.y)
return 1.0;
vec2 rad_tl = r.corner_points1.xy - r.bounds.xy;
vec2 rad_tr = r.corner_points1.zw - r.bounds.zy;
vec2 rad_br = r.corner_points2.xy - r.bounds.zw;
vec2 rad_bl = r.corner_points2.zw - r.bounds.xw;
float d_tl = gsk_ellipsis_coverage(p, ref_tl, rad_tl);
float d_tr = gsk_ellipsis_coverage(p, ref_tr, rad_tr);
float d_br = gsk_ellipsis_coverage(p, ref_br, rad_br);
float d_bl = gsk_ellipsis_coverage(p, ref_bl, rad_bl);
vec4 corner_coverages = 1.0 - vec4(d_tl, d_tr, d_br, d_bl);
bvec4 is_out = bvec4(p.x < ref_tl.x && p.y < ref_tl.y,
p.x > ref_tr.x && p.y < ref_tr.y,
p.x > ref_br.x && p.y > ref_br.y,
p.x < ref_bl.x && p.y > ref_bl.y);
return 1.0 - dot(vec4(is_out), corner_coverages);
}
float
gsk_rect_coverage (vec4 r, vec2 p)
{
if (p.x < r.x || p.y < r.y ||
p.x >= r.z || p.y >= r.w)
return 0.0;
return 1.0;
}
vec4 GskTexture(sampler2D sampler, vec2 texCoords) {
#if defined(GSK_GLES) || defined(GSK_LEGACY)
return texture2D(sampler, texCoords);
#else
return texture(sampler, texCoords);
#endif
}
#ifdef GSK_GL3
layout(origin_upper_left) in vec4 gl_FragCoord;
#endif
vec2 gsk_get_frag_coord() {
vec2 fc = gl_FragCoord.xy;
#ifdef GSK_GL3
fc += u_viewport.xy;
#else
fc.x += u_viewport.x;
fc.y = (u_viewport.y + u_viewport.w) - fc.y;
#endif
return fc;
}
void gskSetOutputColor(vec4 color) {
vec4 result;
#if defined(NO_CLIP)
result = color;
#elif defined(RECT_CLIP)
result = color * gsk_rect_coverage(gsk_get_bounds(u_clip_rect),
gsk_get_frag_coord());
#else
result = color * gsk_rounded_rect_coverage(gsk_create_rect(u_clip_rect),
gsk_get_frag_coord());
#endif
#if defined(GSK_GLES) || defined(GSK_LEGACY)
gl_FragColor = result;
#else
outputColor = result;
#endif
}

View File

@ -0,0 +1,57 @@
#ifndef GSK_LEGACY
precision highp float;
#endif
#if defined(GSK_GLES) || defined(GSK_LEGACY)
#define _OUT_ varying
#define _IN_ varying
#define _NOPERSPECTIVE_
#define _GSK_ROUNDED_RECT_UNIFORM_ vec4[3]
#else
#define _OUT_ out
#define _IN_ in
#define _NOPERSPECTIVE_ noperspective
#define _GSK_ROUNDED_RECT_UNIFORM_ GskRoundedRect
#endif
struct GskRoundedRect
{
vec4 bounds; // Top left and bottom right
// Look, arrays can't be in structs if you want to return the struct
// from a function in gles or whatever. Just kill me.
vec4 corner_points1; // xy = top left, zw = top right
vec4 corner_points2; // xy = bottom right, zw = bottom left
};
// Transform from a C GskRoundedRect to what we need.
GskRoundedRect
gsk_create_rect(vec4[3] data)
{
vec4 bounds = vec4(data[0].xy, data[0].xy + data[0].zw);
vec4 corner_points1 = vec4(bounds.xy + data[1].xy,
bounds.zy + vec2(data[1].zw * vec2(-1, 1)));
vec4 corner_points2 = vec4(bounds.zw + (data[2].xy * vec2(-1, -1)),
bounds.xw + vec2(data[2].zw * vec2(1, -1)));
return GskRoundedRect(bounds, corner_points1, corner_points2);
}
vec4
gsk_get_bounds(vec4[3] data)
{
return vec4(data[0].xy, data[0].xy + data[0].zw);
}
vec4 gsk_premultiply(vec4 c) {
return vec4(c.rgb * c.a, c.a);
}
vec4 gsk_scaled_premultiply(vec4 c, float s) {
// Fast version of gsk_premultiply(c) * s
// 4 muls instead of 7
float a = s * c.a;
return vec4(c.rgb * a, a);
}

View File

@ -0,0 +1,69 @@
uniform mat4 u_projection;
uniform mat4 u_modelview;
uniform float u_alpha;
#if defined(GSK_GLES) || defined(GSK_LEGACY)
attribute vec2 aPosition;
attribute vec2 aUv;
_OUT_ vec2 vUv;
#else
_IN_ vec2 aPosition;
_IN_ vec2 aUv;
_OUT_ vec2 vUv;
#endif
// amount is: top, right, bottom, left
GskRoundedRect
gsk_rounded_rect_shrink (GskRoundedRect r, vec4 amount)
{
vec4 new_bounds = r.bounds + vec4(1.0,1.0,-1.0,-1.0) * amount.wxyz;
vec4 new_corner_points1 = r.corner_points1;
vec4 new_corner_points2 = r.corner_points2;
if (r.corner_points1.xy == r.bounds.xy) new_corner_points1.xy = new_bounds.xy;
if (r.corner_points1.zw == r.bounds.zy) new_corner_points1.zw = new_bounds.zy;
if (r.corner_points2.xy == r.bounds.zw) new_corner_points2.xy = new_bounds.zw;
if (r.corner_points2.zw == r.bounds.xw) new_corner_points2.zw = new_bounds.xw;
return GskRoundedRect (new_bounds, new_corner_points1, new_corner_points2);
}
void
gsk_rounded_rect_offset(inout GskRoundedRect r, vec2 offset)
{
r.bounds.xy += offset;
r.bounds.zw += offset;
r.corner_points1.xy += offset;
r.corner_points1.zw += offset;
r.corner_points2.xy += offset;
r.corner_points2.zw += offset;
}
void gsk_rounded_rect_transform(inout GskRoundedRect r, mat4 mat)
{
r.bounds.xy = (mat * vec4(r.bounds.xy, 0.0, 1.0)).xy;
r.bounds.zw = (mat * vec4(r.bounds.zw, 0.0, 1.0)).xy;
r.corner_points1.xy = (mat * vec4(r.corner_points1.xy, 0.0, 1.0)).xy;
r.corner_points1.zw = (mat * vec4(r.corner_points1.zw, 0.0, 1.0)).xy;
r.corner_points2.xy = (mat * vec4(r.corner_points2.xy, 0.0, 1.0)).xy;
r.corner_points2.zw = (mat * vec4(r.corner_points2.zw, 0.0, 1.0)).xy;
}
#if defined(GSK_LEGACY)
// Can't have out or inout array parameters...
#define gsk_rounded_rect_encode(r, uni) uni[0] = r.bounds; uni[1] = r.corner_points1; uni[2] = r.corner_points2;
#else
void gsk_rounded_rect_encode(GskRoundedRect r, out _GSK_ROUNDED_RECT_UNIFORM_ out_r)
{
#if defined(GSK_GLES)
out_r[0] = r.bounds;
out_r[1] = r.corner_points1;
out_r[2] = r.corner_points2;
#else
out_r = r;
#endif
}
#endif

View File

@ -0,0 +1,74 @@
// VERTEX_SHADER
uniform vec4 u_geometry;
_NOPERSPECTIVE_ _OUT_ vec2 coord;
void main() {
gl_Position = u_projection * (u_modelview * vec4(aPosition, 0.0, 1.0));
vec2 mv0 = u_modelview[0].xy;
vec2 mv1 = u_modelview[1].xy;
vec2 offset = aPosition - u_geometry.xy;
vec2 dir = vec2(dot(mv0, offset),
dot(mv1, offset));
coord = dir * u_geometry.zw;
}
// FRAGMENT_SHADER:
#ifdef GSK_LEGACY
uniform int u_num_color_stops;
#else
uniform highp int u_num_color_stops;
#endif
uniform bool u_repeat;
uniform vec2 u_range;
uniform float u_color_stops[6 * 5];
_NOPERSPECTIVE_ _IN_ vec2 coord;
float get_offset(int index) {
return u_color_stops[5 * index];
}
vec4 get_color(int index) {
int base = 5 * index + 1;
return vec4(u_color_stops[base],
u_color_stops[base + 1],
u_color_stops[base + 2],
u_color_stops[base + 3]);
}
void main() {
// Reverse scale
float offset = length(coord) * u_range.x + u_range.y;
if (u_repeat) {
offset = fract(offset);
}
if (offset < get_offset(0)) {
gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha));
return;
}
int n = u_num_color_stops - 1;
for (int i = 0; i < n; i++) {
float curr_offset = get_offset(i);
float next_offset = get_offset(i + 1);
if (offset >= curr_offset && offset < next_offset) {
float f = (offset - curr_offset) / (next_offset - curr_offset);
vec4 curr_color = gsk_premultiply(get_color(i));
vec4 next_color = gsk_premultiply(get_color(i + 1));
vec4 color = mix(curr_color, next_color, f);
gskSetOutputColor(color * u_alpha);
return;
}
}
gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha));
}

View File

@ -0,0 +1,41 @@
// VERTEX_SHADER:
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
vUv = vec2(aUv.x, aUv.y);
}
// FRAGMENT_SHADER:
uniform vec4 u_child_bounds;
uniform vec4 u_texture_rect;
float wrap(float f, float wrap_for) {
return mod(f, wrap_for);
}
/* We get the texture coordinates via vUv,
* but that might be on a texture atlas, so we need to do the
* wrapping ourselves.
*/
void main() {
/* We map the texture coordinate to [1;0], then wrap it and scale the result again */
float tw = u_texture_rect.z - u_texture_rect.x;
float th = u_texture_rect.w - u_texture_rect.y;
float mapped_x = (vUv.x - u_texture_rect.x) / tw;
float mapped_y = (vUv.y - u_texture_rect.y) / th;
float wrapped_x = wrap(u_child_bounds.x + mapped_x * u_child_bounds.z, 1.0);
float wrapped_y = wrap(u_child_bounds.y + mapped_y * u_child_bounds.w, 1.0);
vec2 tp;
tp.x = u_texture_rect.x + (wrapped_x * tw);
tp.y = u_texture_rect.y + (wrapped_y * th);
vec4 diffuse = GskTexture(u_source, tp);
gskSetOutputColor(diffuse * u_alpha);
}

View File

@ -0,0 +1,42 @@
// VERTEX_SHADER:
uniform vec4 u_color;
uniform float u_spread;
uniform vec2 u_offset;
uniform vec4[3] u_outline_rect;
_OUT_ vec4 final_color;
_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
_OUT_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
final_color = gsk_premultiply(u_color) * u_alpha;
GskRoundedRect inside = gsk_create_rect(u_outline_rect);
GskRoundedRect outside = gsk_rounded_rect_shrink(inside, vec4(- u_spread));
gsk_rounded_rect_offset(outside, u_offset);
gsk_rounded_rect_transform(outside, u_modelview);
gsk_rounded_rect_transform(inside, u_modelview);
gsk_rounded_rect_encode(outside, transformed_outside_outline);
gsk_rounded_rect_encode(inside, transformed_inside_outline);
}
// FRAGMENT_SHADER:
_IN_ vec4 final_color;
_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
_IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
vec2 frag = gsk_get_frag_coord();
float alpha = clamp(gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outside_outline), frag) -
gsk_rounded_rect_coverage(gsk_decode_rect(transformed_inside_outline), frag),
0.0, 1.0);
gskSetOutputColor(final_color * alpha);
}