23
25
uniform sampler2D shapeTexture;
24
26
uniform sampler2D sourceTexture;
27
uniform lowp vec2 dfdtFactors;
28
uniform lowp vec2 opacityFactors;
25
29
uniform lowp float sourceOpacity;
26
uniform lowp float opacity;
30
uniform lowp float distanceAA;
27
31
uniform bool textured;
32
uniform mediump int aspect;
29
34
varying mediump vec2 shapeCoord;
30
35
varying mediump vec4 sourceCoord;
31
36
varying lowp vec4 backgroundColor;
38
const mediump int FLAT = 0x08; // 1 << 3
39
const mediump int INSET = 0x10; // 1 << 4
35
// Early texture fetch to cover latency as best as possible.
36
43
lowp vec4 shapeData = texture2D(shapeTexture, shapeCoord);
38
44
lowp vec4 color = backgroundColor;
40
46
// FIXME(loicm) Would be better to use a bitfield but bitwise ops have only been integrated in
41
47
// GLSL 1.3 (OpenGL 3) and GLSL ES 3 (OpenGL ES 3).
43
// Blend the source over the current color (static flow control prevents the texture fetch).
49
// Blend the source over the current color.
50
// FIXME(loicm) sign() is far from optimal. Call texture2D() at beginning of scope.
44
51
lowp vec2 axisMask = -sign((sourceCoord.zw * sourceCoord.zw) - vec2(1.0));
45
52
lowp float mask = clamp(axisMask.x + axisMask.y, 0.0, 1.0);
46
53
lowp vec4 source = texture2D(sourceTexture, sourceCoord.st) * vec4(sourceOpacity * mask);
47
54
color = vec4(1.0 - source.a) * color + source;
50
// Shape the current color with the mask.
51
color *= vec4(shapeData.b);
53
// Blend the border over the current color.
54
color = vec4(1.0 - shapeData.r) * color + shapeData.gggr;
56
gl_FragColor = color * vec4(opacity);
57
// Get screen-space derivative of texture coordinate t representing the normalized distance
58
// between 2 pixels. dFd*() unfortunately have to be called outside of the following branches
59
// (evaluated using a uniform variable) in order to work correctly with Mesa.
60
lowp float dfdt = dfdtFactors.x != 0.0 ? dFdy(shapeCoord.t) : dFdx(shapeCoord.t);
63
// Mask the current color with an anti-aliased and resolution independent shape mask built
64
// from distance fields.
65
lowp float distanceMin = abs(dfdt) * -distanceAA + 0.5;
66
lowp float distanceMax = abs(dfdt) * distanceAA + 0.5;
67
color *= smoothstep(distanceMin, distanceMax, shapeData.b);
69
} else if (aspect == INSET) {
70
// The vertex layout of the shape is made so that the derivative is negative from top to
71
// middle and positive from middle to bottom.
72
lowp float shapeSide = dfdt * dfdtFactors.y <= 0.0 ? 0.0 : 1.0;
73
// Blend the shape inner shadow over the current color. The shadow color is black, its
74
// translucency is stored in the texture.
75
lowp float shadow = shapeData[int(shapeSide)];
76
color = vec4(1.0 - shadow) * color + vec4(0.0, 0.0, 0.0, shadow);
77
// Get the anti-aliased and resolution independent shape mask using distance fields.
78
lowp float distanceMin = abs(dfdt) * -distanceAA + 0.5;
79
lowp float distanceMax = abs(dfdt) * distanceAA + 0.5;
80
lowp vec2 mask = smoothstep(distanceMin, distanceMax, shapeData.ba);
81
// Get the bevel color. The bevel is made of the top mask masked with the bottom mask. A
82
// gradient from the bottom (1) to the middle (0) of the shape is used to factor out values
83
// resulting from the mask anti-aliasing. The bevel color is white with 60% opacity.
84
lowp float bevel = (mask.x * -mask.y) + mask.x; // -ab + a = a(1 - b)
85
lowp float gradient = clamp((shapeSide * -shapeCoord.t) + shapeSide, 0.0, 1.0);
86
bevel *= gradient * 0.6;
87
// Mask the current color then blend the bevel over the resulting color. We simply use
88
// additive blending since the bevel has already been masked.
89
color = (color * vec4(mask[int(shapeSide)])) + vec4(bevel);
92
gl_FragColor = color * opacityFactors.xxxy;