Published
Edited
Jun 7, 2021
Importers
16 stars
Insert cell
Insert cell
bnbShader(`
#define TAU 6.28318

uniform vec2 u_resolution;
uniform float u_time;

void main() {
vec2 st = gl_FragCoord.xy / u_resolution;
gl_FragColor = vec4(floor(st * 10.) / 9., sin(u_time * TAU) * .5 + .5, 1.0);
}`)

Insert cell
Insert cell
await visibility(), bnbShader(`
// we can use JS in our shader
#define PI ${Math.PI}
#define TAU ${Math.PI * 2}

uniform float u_time;
uniform vec2 u_resolution;

// we have access to glslify modules using include from @mbostock/pseudo-glslify
${await include("glsl-noise/simplex/4d.glsl")}

// and snippets
${modularDist()}
${map()}
${palette([0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [0.0, 0.1, 0.2])}

void main() {
vec2 pos = (gl_FragCoord.xy * 2. - u_resolution)/u_resolution.y;
float N = 5.;
float angle = modularDist(map(atan(pos.y, pos.x) + PI/10., -PI, PI, 0., 1.), 1./N) * N;
float r = length(pos);
float n = snoise(vec4(vec2(r * 2., angle), cos(u_time * TAU) * .6, sin(u_time * TAU) * .6));
gl_FragColor = vec4(palette(modularDist(n * (6. + sin(u_time * TAU) * 2.), 2.)), 1.);
}`, {
w: 540, h: 540,
record: true,
numFrames: 120,
fps: 20
})
Insert cell
Insert cell
Insert cell
Insert cell
await visibility(), bnbShader(`
#define PI ${Math.PI}
#define TAU ${Math.PI * 2}

uniform vec2 u_resolution;
uniform float u_time;
uniform sampler2D u_texture;

mat2 rotate(float angle) {
return mat2(cos(angle), -sin(angle), sin(angle), cos(angle));
}

void main() {
vec2 uv = gl_FragCoord.xy / u_resolution;
uv.y = 1. - uv.y;
uv -= .5;
uv *= rotate(smoothstep(0.55, 0.05, length(uv)) * sin(u_time * TAU) * TAU * 1.5);
uv += .5;
gl_FragColor = texture2D(u_texture, uv);
}
`, {
w: 450, h: 450,
u_texture: `https://source.unsplash.com/featured?gradient,${Date.now()}`,
numFrames: 120,
record: true,
antiAlisaing: 3
})
Insert cell
Insert cell
await visibility(), bnbShader(`
uniform vec2 u_resolution;
uniform float u_time;
uniform sampler2D u_texture;

${palette([.5, .5, .5], [.5, .5, .5], [1, 1, 0], [.9, .8, .3])}

void main() {
vec2 uv = gl_FragCoord.xy / u_resolution;
uv.y = 1. - uv.y;
gl_FragColor = vec4(palette(fract(texture2D(u_texture, uv).r * 20. - u_time*2.)), 1.);
}
`, {
w: 540, h: 540,
init: (s, g) => {
const pg = s.createGraphics(g.w, g.h)
pg.background(0)
const seed = Date.now()
const scaleX = 150
const scaleY = scaleX
for(let x = 0; x < g.w; x ++) {
for(let y = 0; y < g.w; y ++) {
pg.stroke(s.noise(x/scaleX + seed, y/scaleY) * 255)
pg.point(x, y)
}
}
g.u_texture = pg
},
record: true,
video: true
})
Insert cell
Insert cell
await visibility(), bnbShader(`
uniform vec2 u_resolution;
uniform float u_frame;
uniform sampler2D u_framebuffer;

void main() {
vec2 uv = gl_FragCoord.xy / u_resolution;
vec2 pos = (gl_FragCoord.xy * 2. - u_resolution) / u_resolution.y;

vec3 color = vec3(0);

// initialize first frame
if(u_frame == 0.) {
color = vec3(step(.05, uv.x) * step(uv.x, .95) * step(.45, uv.y) * step(uv.y, .55));
color += vec3(step(.45, uv.x) * step(uv.x, .55) * step(.05, uv.y) * step(uv.y, .95));
}
else {
uv.y = 1. - uv.y;
float alive = texture2D(u_framebuffer, uv).r;
vec2 delta = vec2(1.) / u_resolution;
float sum = 0.;
for(float i = -1.; i <= 1.; i++) {
for(float j = -1.; j <= 1.; j++) {
if(i == 0. && j == 0.) continue;
sum += texture2D(u_framebuffer, uv + vec2(i, j) * delta).r;
}
}
if(alive == 1.) {
// Any live cell with fewer than two live neighbours dies, as if by underpopulation.
if(sum < 2.) color = vec3(0.);
// Any live cell with two or three live neighbours lives on to the next generation.
else if(sum <= 3.) color = vec3(1.);
// Any live cell with more than three live neighbours dies, as if by overpopulation.
else color = vec3(0.);
}
else {
// Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
if(sum == 3.) color = vec3(1.);
}
// can be resumed to:
// if(sum == 3. || (alive == 1. && sum == 2.)) color = vec3(1.);
}
gl_FragColor = vec4(color, 1);
}
`, {
w: 540, h: 540,
numFrames: 200,
record: true,
video: true,
chromaticAberration: .2,
})
Insert cell
Insert cell
Insert cell
bnbShader = (fragmentShader, options = {}) => bnb({
...options,
preload: (s, g) => {
g.pg = s.createGraphics(g.w, g.h, s.WEBGL)
g.pg.pixelDensity(1)
g.pg.sh = g.pg.createShader(`
#ifdef GL_ES
precision mediump float;
#endif
attribute vec3 aPosition;
void main() {
gl_Position = vec4(aPosition, 1.0);
}`, `
#ifdef GL_ES
precision mediump float;
#endif
${fragmentShader}
`)
g.pg.shader(g.pg.sh)
g.pg.noStroke()
if(options.u_texture) g.u_texture = s.loadImage(options.u_texture)
if(options.init) options.init(s, g)
},
draw: (s, t, g) => {
g.pg.sh.setUniform('u_resolution', [s.width, s.height])
g.pg.sh.setUniform('u_time', t)
g.pg.sh.setUniform('u_mouse', [s.mouseX, s.mouseY])
g.pg.sh.setUniform('u_frame', g.frame)
g.pg.sh.setUniform('u_framebuffer', g.pg)
if(g.u_texture) g.pg.sh.setUniform('u_texture', g.u_texture)
if (options.update) options.update(s, t, g)

//g.pg.clear()
g.pg.noStroke()
g.pg.beginShape()
g.pg.vertex(-1, -1)
g.pg.vertex(1, -1)
g.pg.vertex(1, 1)
g.pg.vertex(-1, 1)
g.pg.endShape(s.CLOSE)
s.clear()
s.image(g.pg, 0, 0)
}
})
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more