Skip to content

Instantly share code, notes, and snippets.

@curtmack
Last active August 29, 2015 14:23
Show Gist options
  • Save curtmack/caf610c7d2533e4afde2 to your computer and use it in GitHub Desktop.
Save curtmack/caf610c7d2533e4afde2 to your computer and use it in GitHub Desktop.
Pride shader

I was inspired by Facebook's celebratepride converter, and decided to make my own version in GLSL.

##Usage

Compile the vertex and fragment shaders into a program, then apply that program to a quad that takes up the whole screen. The screen should be square.

##Uniforms

Vertex shader

The vertex shader does not take any uniforms.

Fragment shader

  • screenWidth — The width of the GL screen, in pixels.
  • screenHeight — The height of the GL screen, in pixels.
  • noise — A texture of pure white noise, used for randomness. GIMP can create such an image for you: Go to Filters > Noise > Hurl..., then set the Randomness % to 100%.
  • target — A texture you want to mask over the tiles. The value channel of the tiles is masked onto the value channel of the target texture, while the hue and saturation channels are always taken from the tiles.

Remember that both textures should have a power of 2 width and height. I recommend the same dimensions as your screen.

##WebGL

Shaders marked #version 100 are WebGL compatible, so you can use these with in a website using WebGL if you so desire. (Heck, that's how I put my avatar into it.)

#version 100
#define tiles 7
precision highp float;
uniform float screenWidth;
uniform float screenHeight;
uniform sampler2D noise;
uniform sampler2D target;
vec2 hash2(vec2 p) {
return texture2D(noise, p).xy;
}
// these implementations of rgb2hsv and hsv2rgb originally written by sam of Lol Engine
// http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
vec3 rgb2hsv(vec3 c)
{
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
vec3 hsv2rgb(vec3 c) {
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
vec3 tile(vec2 pt) {
// apply base color
// take floor of vertical coordinate divided into 14 pieces
// then use that as hue
vec2 tileStart = floor(pt * float(tiles)) / float(tiles);
vec2 tileLoc = (pt - tileStart) * float(tiles);
// scaling hue by 85% makes the colors more closely match the gay pride flag,
// with deep purple (not magenta) on the bottom
vec3 hsv = vec3(tileStart.y * 0.85, 0.8, 0.0);
// tile-based randomness
float rnd = hash2(tileStart).x;
// point-based randomness
rnd = rnd + hash2(pt).y;
// border wear
float wear = 2.0 * (clamp(tileLoc.y, 0.9, 1.0) - 0.9);
wear = wear - 2.0 * (clamp(tileLoc.y, 0.0, 0.1) - 0.1);
wear = wear + 2.0 * (clamp(tileLoc.x, 0.9, 1.0) - 0.9);
wear = wear - 2.0 * (clamp(tileLoc.x, 0.0, 0.1) - 0.1);
// apply randomness
hsv.g = hsv.g + (0.2 * (rnd - 1.0));
// apply value mask
vec3 targetColor = rgb2hsv(texture2D(target, pt).rgb);
hsv.b = 0.6 * targetColor.b + 0.4;
// apply randomness
hsv.b = hsv.b + (0.3 * (rnd - 1.0));
// apply wear
hsv.b = hsv.b - wear;
return hsv2rgb(hsv);
}
void main() {
vec2 coord = vec2(gl_FragCoord.x/screenWidth, gl_FragCoord.y/screenHeight);
// account for image coordinates vs. GL coordinates
coord.y = 1.0 - coord.y;
gl_FragColor = vec4(tile(coord), 1.0);
}
#version 100
attribute vec2 vPosition;
void main()
{
gl_Position = vec4(vPosition, 0.0, 1.0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment