Shader thingy
A WebGL fragment shader renderer web component. A minimal setup for experimenting with WebGL Fragment Shaders, but still using two framebuffers so we can use the previous frame as a texture for the current frame.
I was/am working on another web component, El Shader, for toying with fragment shaders and you can find some of those experiments at shader.maphca.se.
The clean setup, uses default simple fragment shader code
With custom shader code to generate wavey waves (view source)
precision highp float;
precision highp sampler2D;
uniform float time;
uniform vec2 resolution;
uniform sampler2D previousFrame;
vec2 uv() {
return (gl_FragCoord.xy / resolution * 2.0 - 1.0) * vec2(resolution.x / resolution.y, 1.0);
}
void main() {
vec2 uv = uv();
vec3 wave_color = vec3(0.0);
float wave_width = 0.01;
uv.y += 0.1;
for(float i = 0.0; i < 3.0; i++) {
uv.y += 0.17 * sin(uv.x + time + i / 17.0);
wave_width = abs(1.0 / (150.0 * uv.y));
wave_color += vec3(wave_width * 1.9, wave_width * 2.3, wave_width * 1.5);
}
gl_FragColor = vec4(wave_color, 1.0);
}
Trippy shizzle
precision highp float;
precision highp sampler2D;
uniform float time;
uniform vec2 resolution;
uniform sampler2D previousFrame;
vec2 uv() {
return (gl_FragCoord.xy / resolution * 2.0 - 1.0) * vec2(resolution.x / resolution.y, 1.0);
}
void main() {
float t = time * .3;
vec2 uv = uv();
vec3 c = vec3(0.);
float f = 0.;
float a = atan(uv.y, uv.x);
float d = length(uv);
float s1 = -.1;
float s2 = s1 + (sin(t - d * 3.) * .1 + .15);
for (float i = 0.; i < (2. * 6.28); i += (2. * 6.28 / 128.)) {
f += smoothstep(s1, s2, sin(a * (5.) - t + sin(i - t) * 11.5) * .1 * d + (d - i * .4));
}
f += t;
float spread = sin(t) * .001;
c.rgb = sin((vec3(f - spread, f, f + spread)) * 6.) * .5 + .5;
gl_FragColor = vec4(c.r * .8439, c.g * .1477, c.b * .1877, 1.0);
}
Waves
precision highp float;
precision highp sampler2D;
uniform float time;
uniform vec2 resolution;
uniform sampler2D previousFrame;
vec2 uv() {
return (gl_FragCoord.xy / resolution * 2.0 - 1.0) * vec2(resolution.x / resolution.y, 1.0);
}
float gradient(float p)
{
vec2 pt0 = vec2(0.00,0.0);
vec2 pt1 = vec2(0.86,0.1);
vec2 pt2 = vec2(0.955,0.40);
vec2 pt3 = vec2(0.99,1.0);
vec2 pt4 = vec2(1.00,0.0);
if (p < pt0.x) return pt0.y;
if (p < pt1.x) return mix(pt0.y, pt1.y, (p-pt0.x) / (pt1.x-pt0.x));
if (p < pt2.x) return mix(pt1.y, pt2.y, (p-pt1.x) / (pt2.x-pt1.x));
if (p < pt3.x) return mix(pt2.y, pt3.y, (p-pt2.x) / (pt3.x-pt2.x));
if (p < pt4.x) return mix(pt3.y, pt4.y, (p-pt3.x) / (pt4.x-pt3.x));
return pt4.y;
}
float waveN(vec2 uv, vec2 s12, vec2 t12, vec2 f12, vec2 h12)
{
vec2 x12 = sin((time * 0.37 * s12 + t12 + uv.x) * f12) * h12;
float g = gradient(uv.y / (0.5 + x12.x + x12.y));
return g * 0.27;
}
float wave1(vec2 uv)
{
return waveN(vec2(uv.x,uv.y-0.25), vec2(0.03,0.06), vec2(0.00,0.02), vec2(8.0,3.7), vec2(0.06,0.05));
}
float wave2(vec2 uv)
{
return waveN(vec2(uv.x,uv.y-0.25), vec2(0.04,0.07), vec2(0.16,-0.37), vec2(6.7,2.89), vec2(0.06,0.05));
}
float wave3(vec2 uv)
{
return waveN(vec2(uv.x,0.75-uv.y), vec2(0.035,0.055), vec2(-0.09,0.27), vec2(7.4,2.51), vec2(0.06,0.05));
}
float wave4(vec2 uv)
{
return waveN(vec2(uv.x,0.75-uv.y), vec2(0.032,0.09), vec2(0.08,-0.22), vec2(6.5,3.89), vec2(0.06,0.05));
}
void main() {
vec2 uv = uv();
uv.y += .5;
float waves = wave1(uv) + wave2(uv) + wave3(uv) + wave4(uv);
float x = uv.x;
float y = 1.0 - uv.y;
//vec3 bg = mix(vec3(0.05,0.05,0.3),vec3(0.1,0.65,0.85), (x+y)*0.55);
vec3 ac = vec3(1.0) - (vec3(1.0, 1.0, 1.0) * waves * .5);
gl_FragColor = vec4(ac, 1.0);
}
Glitch image
precision highp float;
precision highp sampler2D;
uniform float time;
uniform vec2 resolution;
uniform sampler2D previousFrame;
uniform sampler2D image_texture_0;
uniform vec2 image_texture_resolution_0;
vec3 mod289(vec3 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec2 mod289(vec2 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec3 permute(vec3 x) {
return mod289(((x*34.0)+1.0)*x);
}
float snoise(vec2 v)
{
const vec4 C = vec4(0.211324865405187, // (3.0-sqrt(3.0))/6.0
0.366025403784439, // 0.5*(sqrt(3.0)-1.0)
-0.577350269189626, // -1.0 + 2.0 * C.x
0.024390243902439); // 1.0 / 41.0
// First corner
vec2 i = floor(v + dot(v, C.yy) );
vec2 x0 = v - i + dot(i, C.xx);
// Other corners
vec2 i1;
//i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0
//i1.y = 1.0 - i1.x;
i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
// x0 = x0 - 0.0 + 0.0 * C.xx ;
// x1 = x0 - i1 + 1.0 * C.xx ;
// x2 = x0 - 1.0 + 2.0 * C.xx ;
vec4 x12 = x0.xyxy + C.xxzz;
x12.xy -= i1;
// Permutations
i = mod289(i); // Avoid truncation effects in permutation
vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 ))
+ i.x + vec3(0.0, i1.x, 1.0 ));
vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);
m = m*m ;
m = m*m ;
// Gradients: 41 points uniformly over a line, mapped onto a diamond.
// The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287)
vec3 x = 2.0 * fract(p * C.www) - 1.0;
vec3 h = abs(x) - 0.5;
vec3 ox = floor(x + 0.5);
vec3 a0 = x - ox;
// Normalise gradients implicitly by scaling m
// Approximation of: m *= inversesqrt( a0*a0 + h*h );
m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );
// Compute final noise value at P
vec3 g;
g.x = a0.x * x0.x + h.x * x0.y;
g.yz = a0.yz * x12.xz + h.yz * x12.yw;
return 130.0 * dot(m, g);
}
float rand(vec2 co)
{
return fract(sin(dot(co.xy,vec2(12.9898,78.233))) * 43758.5453);
}
vec2 uv() {
return (gl_FragCoord.xy / resolution * 2.0 - 1.0) * vec2(resolution.x / resolution.y, 1.0);
}
void main() {
float t = time * .3;
float imageAspect = image_texture_resolution_0.x / image_texture_resolution_0.y;
float screenAspect = resolution.x / resolution.y;
vec2 uv = gl_FragCoord.xy / resolution;
// cover:
float aspect_ratio_correction = 1.;
if (imageAspect > screenAspect) {
aspect_ratio_correction = screenAspect / imageAspect;
uv.x *= aspect_ratio_correction;
uv.x += (1.0 - aspect_ratio_correction) / 2.0;
} else {
aspect_ratio_correction = imageAspect / screenAspect;
uv.y *= aspect_ratio_correction;
uv.y += (1.0 - aspect_ratio_correction) / 2.0;
}
// Create large, incidental noise waves
float noise = max(0.0, snoise(vec2(time, uv.y * 0.3)) - 0.3) * (1.0 / 0.7);
// Offset by smaller, constant noise waves
noise = noise + (snoise(vec2(time*10.0, uv.y * 2.4)) - 0.5) * 0.15;
// Apply the noise as x displacement for every line
float xpos = uv.x - noise * noise * 0.25;
vec4 fragColor = texture2D(image_texture_0, vec2(xpos, uv.y));
// Mix in some random interference for lines
fragColor.rgb = mix(fragColor.rgb, vec3(rand(vec2(uv.y * time))), noise * 0.3).rgb;
// Apply a line pattern every 4 pixels
if (floor(mod(gl_FragCoord.y * 0.25, 2.0)) == 0.0)
{
fragColor.rgb *= 1.0 - (0.15 * noise);
}
// Shift green/blue channels (using the red channel)
fragColor.g = mix(fragColor.r, texture2D(image_texture_0, vec2(xpos + noise * 0.05, uv.y)).g, 0.25);
fragColor.b = mix(fragColor.r, texture2D(image_texture_0, vec2(xpos - noise * 0.05, uv.y)).b, 0.25);
gl_FragColor = fragColor;
}
Glitch on hover
precision highp float;
precision highp sampler2D;
uniform float time;
uniform vec2 resolution;
uniform sampler2D previousFrame;
uniform int play_state; // 1: PLAYING, 0: PAUSED, -1: STOPPED
uniform sampler2D image_texture_0;
uniform vec2 image_texture_resolution_0;
vec3 mod289(vec3 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec2 mod289(vec2 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec3 permute(vec3 x) {
return mod289(((x*34.0)+1.0)*x);
}
float snoise(vec2 v)
{
const vec4 C = vec4(0.211324865405187, // (3.0-sqrt(3.0))/6.0
0.366025403784439, // 0.5*(sqrt(3.0)-1.0)
-0.577350269189626, // -1.0 + 2.0 * C.x
0.024390243902439); // 1.0 / 41.0
// First corner
vec2 i = floor(v + dot(v, C.yy) );
vec2 x0 = v - i + dot(i, C.xx);
// Other corners
vec2 i1;
//i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0
//i1.y = 1.0 - i1.x;
i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
// x0 = x0 - 0.0 + 0.0 * C.xx ;
// x1 = x0 - i1 + 1.0 * C.xx ;
// x2 = x0 - 1.0 + 2.0 * C.xx ;
vec4 x12 = x0.xyxy + C.xxzz;
x12.xy -= i1;
// Permutations
i = mod289(i); // Avoid truncation effects in permutation
vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 ))
+ i.x + vec3(0.0, i1.x, 1.0 ));
vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);
m = m*m ;
m = m*m ;
// Gradients: 41 points uniformly over a line, mapped onto a diamond.
// The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287)
vec3 x = 2.0 * fract(p * C.www) - 1.0;
vec3 h = abs(x) - 0.5;
vec3 ox = floor(x + 0.5);
vec3 a0 = x - ox;
// Normalise gradients implicitly by scaling m
// Approximation of: m *= inversesqrt( a0*a0 + h*h );
m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );
// Compute final noise value at P
vec3 g;
g.x = a0.x * x0.x + h.x * x0.y;
g.yz = a0.yz * x12.xz + h.yz * x12.yw;
return 130.0 * dot(m, g);
}
float rand(vec2 co)
{
return fract(sin(dot(co.xy,vec2(12.9898,78.233))) * 43758.5453);
}
vec2 uv() {
return (gl_FragCoord.xy / resolution * 2.0 - 1.0) * vec2(resolution.x / resolution.y, 1.0);
}
void main() {
float t = time * .3;
float imageAspect = image_texture_resolution_0.x / image_texture_resolution_0.y;
float screenAspect = resolution.x / resolution.y;
vec2 uv = gl_FragCoord.xy / resolution;
// cover:
float aspect_ratio_correction = 1.;
if (imageAspect > screenAspect) {
aspect_ratio_correction = screenAspect / imageAspect;
uv.x *= aspect_ratio_correction;
uv.x += (1.0 - aspect_ratio_correction) / 2.0;
} else {
aspect_ratio_correction = imageAspect / screenAspect;
uv.y *= aspect_ratio_correction;
uv.y += (1.0 - aspect_ratio_correction) / 2.0;
}
vec4 fragColor = texture2D(image_texture_0, uv);
if(play_state > -1) {
// Create large, incidental noise waves
float noise = max(0.0, snoise(vec2(time, uv.y * 0.3)) - 0.3) * (1.0 / 0.7);
// Offset by smaller, constant noise waves
noise = noise + (snoise(vec2(time*10.0, uv.y * 2.4)) - 0.5) * 0.15;
// Apply the noise as x displacement for every line
float xpos = uv.x - noise * noise * 0.25;
fragColor = texture2D(image_texture_0, vec2(xpos, uv.y));
// Mix in some random interference for lines
fragColor.rgb = mix(fragColor.rgb, vec3(rand(vec2(uv.y * time))), noise * 0.3).rgb;
// Apply a line pattern every 4 pixels
if (floor(mod(gl_FragCoord.y * 0.25, 2.0)) == 0.0)
{
fragColor.rgb *= 1.0 - (0.15 * noise);
}
// Shift green/blue channels (using the red channel)
fragColor.g = mix(fragColor.r, texture2D(image_texture_0, vec2(xpos + noise * 0.05, uv.y)).g, 0.25);
fragColor.b = mix(fragColor.r, texture2D(image_texture_0, vec2(xpos - noise * 0.05, uv.y)).b, 0.25);
}
gl_FragColor = fragColor;
}