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

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more