scratch-render/src/shaders/sprite.frag
Christopher Willis-Ford 41d3d6f6ba First pass at implementing all effects
Some of the math is wrong but I believe all the structure is now in place.
2016-05-19 15:46:37 -07:00

181 lines
3.9 KiB
GLSL

precision mediump float;
#ifdef ENABLE_color
uniform float u_color;
#endif
#ifdef ENABLE_fisheye
uniform float u_fisheye;
#endif
#ifdef ENABLE_whirl
uniform float u_whirl;
#endif
#ifdef ENABLE_pixelate
uniform float u_pixelate;
#endif
#ifdef ENABLE_mosaic
uniform float u_mosaic;
#endif
#ifdef ENABLE_brightness
uniform float u_brightness;
#endif
#ifdef ENABLE_ghost
uniform float u_ghost;
#endif
uniform sampler2D u_skin;
#define u_pixelate_half vec2(0.5,0.5) // TODO
varying vec2 v_texCoord;
#if defined(ENABLE_color) || defined(ENABLE_brightness)
vec3 convertRGB2HSV(vec3 rgb)
{
float maxRGB = max(max(rgb.r, rgb.g), rgb.b);
float minRGB = min(min(rgb.r, rgb.g), rgb.b);
float span = maxRGB - minRGB;
float h, s;
if (span == 0.0)
{
h = s = 0.0;
}
else
{
if (maxRGB == rgb.r) h = 60.0 * ((rgb.g - rgb.b) / span);
else if (maxRGB == rgb.g) h = 120.0 + 60.0 * ((rgb.b - rgb.r) / span);
else h = 240.0 + 60.0 * ((rgb.r - rgb.g) / span);
s = span / maxRGB;
}
return vec3(h, s, maxRGB);
}
vec3 convertHSV2RGB(vec3 hsv)
{
float h = hsv.r;
float s = hsv.g;
float v = hsv.b;
float f = h / 60.0;
int i = int(f);
f -= float(i);
float p = v * (1.0 - s);
float q = v * (1.0 - (s * f));
float t = v * (1.0 - (s * (1.0 - f)));
vec3 rgb;
if (i == 1)
{
rgb = vec3(q, v, p);
}
else if (i == 2)
{
rgb = vec3(p, v, t);
}
else if (i == 3)
{
rgb = vec3(p, q, v);
}
else if (i == 4)
{
rgb = vec3(t, p, v);
}
else if (i == 5)
{
rgb = vec3(v, p, q);
}
else // i == 0, i == 6, or h was out of range
{
rgb = vec3(v, t, p);
}
return rgb;
}
#endif // defined(ENABLE_color) || defined(ENABLE_brightness)
const vec2 kCenter = vec2(0.5, 0.5);
void main()
{
vec2 texcoord0 = v_texCoord;
#ifdef ENABLE_mosaic
texcoord0 = fract(u_mosaic * texcoord0);
#endif // ENABLE_mosaic
#ifdef ENABLE_pixelate
texcoord0 = floor(texcoord0 / u_pixelate) * u_pixelate + u_pixelate_half;
#endif // ENABLE_pixelate
#ifdef ENABLE_whirl
{
const float kRadius = 0.5;
vec2 offset = texcoord0 - kCenter;
float offsetMagnitude = length(offset);
float whirlFactor = 1.0 - (offsetMagnitude / kRadius);
float whirlActual = u_whirl * whirlFactor * whirlFactor;
float sinWhirl = sin(whirlActual);
float cosWhirl = cos(whirlActual);
mat2 rotationMatrix = mat2(
cosWhirl, -sinWhirl,
sinWhirl, cosWhirl
);
// TODO: tweak this algorithm such that texture coordinates don't depend on conditionals.
// see: https://www.opengl.org/wiki/Sampler_%28GLSL%29#Non-uniform_flow_control
if (offsetMagnitude <= kRadius)
{
texcoord0 = rotationMatrix * offset + kCenter;
}
}
#endif // ENABLE_whirl
#ifdef ENABLE_fisheye
{
vec2 vec = (texcoord0 - kCenter) / kCenter;
float r = pow(length(vec), u_fisheye);
float angle = atan(vec.y, vec.x);
// TODO: tweak this algorithm such that texture coordinates don't depend on conditionals.
// see: https://www.opengl.org/wiki/Sampler_%28GLSL%29#Non-uniform_flow_control
if (r <= 1.0)
{
texcoord0 = kCenter + r * vec2(cos(angle), sin(angle)) * kCenter;
}
}
#endif // ENABLE_fisheye
gl_FragColor = texture2D(u_skin, texcoord0);
if (gl_FragColor.a == 0.0)
{
discard;
}
#if defined(ENABLE_color) || defined(ENABLE_brightness)
{
vec3 hsv = convertRGB2HSV(gl_FragColor.rgb);
#ifdef ENABLE_color
{
// this code forces grayscale values to be slightly saturated
// so that some slight change of hue will be visible
if (hsv.b < 0.11) hsv = vec3(0.0, 1.0, 0.11); // force black to dark gray, fully-saturated
if (hsv.g < 0.09) hsv = vec3(0.0, 0.09, hsv.b); // make saturation at least 0.09
hsv.r = mod(hsv.r + u_color, 360.0);
if (hsv.r < 0.0) hsv.r += 360.0;
}
#endif // ENABLE_color
#ifdef ENABLE_brightness
hsv.b = clamp(hsv.b + u_brightness, 0.0, 1.0);
#endif // ENABLE_brightness
gl_FragColor.rgb = convertHSV2RGB(hsv);
}
#endif // defined(ENABLE_color) || defined(ENABLE_brightness)
#ifdef ENABLE_ghost
gl_FragColor.a *= u_ghost;
#endif // ENABLE_ghost
}