Public
Edited
Sep 25, 2023
Importers
Insert cell
Insert cell
makeRegl(`
float dist = length(gl_FragCoord.xy);
vec2 textureCoords = uv + cos(t) * vec2(0.5 - uv.y, uv.x - 0.5) - sin(2.0 * t) * (uv - 0.5);
vec3 textureData = texture2D(texture, textureCoords).rgb;
vec4 addVec = vec4(
1.0 + cos(2.0 * t),
1.0 + cos(2.0 * t + 1.5),
1.0 + cos(2.0 * t + 3.0),
0.0
);
float addVecCoeff = exp(-0.01 * dist);
gl_FragColor = vec4(0.98 * textureData, 1) + addVecCoeff * addVec;
`, ``, 100, 400)
Insert cell
function makeRegl(glsl, funcs='', height=400, w=null) {
let isFullWidth = false;
if (w === null) {
w = width;
isFullWidth = true;
}
const threshold = 0.5;
const dpi = window.devicePixelRatio;
const pxWidth = isFullWidth ? Math.round(w * dpi) : w;
const pxHeight = isFullWidth ? Math.round(height * dpi) : height;
const canvas = DOM.canvas(pxWidth, pxHeight);
const displayWidth = Math.round(width * dpi);
const displayHeight = Math.round(width * dpi / pxWidth * pxHeight);
const useSecondCanvas = false; // displayWidth != pxWidth;
canvas.style.width = width + 'px';
const secondCanvas = useSecondCanvas ? DOM.canvas(displayWidth, displayHeight) : null;
const ctx = canvas.getContext('webgl', {
preserveDrawingBuffer: useSecondCanvas,
});
const regl = reglConstructor(ctx);
const pixels = regl.texture();
const drawFeedback = regl({
frag: `
precision mediump float;
uniform sampler2D texture;
uniform float t;
uniform vec2 iResolution;
varying vec2 uv;

${funcs}

void main () {
${glsl}
}`,
vert: `
precision mediump float;
attribute vec2 position;
varying vec2 uv;
void main () {
uv = position;
gl_Position = vec4(2.0 * position - 1.0, 0, 1);
}`,
attributes: {
position: [
-2, 0,
0, -2,
2, 2]
},
uniforms: {
texture: pixels,
t: ({tick}) => 0.01 * (tick - 1),
iResolution: [pxWidth, pxHeight],
},
count: 3
})

let cancel = null;
let running = false;

const start = () => {
if (running) {
console.log('already running');
return;
}
running = true;
const doCancel = regl.frame(function () {
regl.clear({
color: [0, 0, 0, 1]
})
drawFeedback()

pixels({
copy: true
});

if (useSecondCanvas) {
const secondCtx = secondCanvas.getContext('2d');
secondCtx.drawImage(canvas, 0, 0, displayWidth, displayHeight);
}
}).cancel;
cancel = () => {
if (!running) {
console.log('not cancelling because not running');
} else {
running = false;
doCancel();
}
}
}

const observer = new IntersectionObserver(onIntersection, {threshold});
function onIntersection(entries, opts){
if (entries[0].intersectionRatio > threshold || threshold === 0 && entries[0].isIntersecting) {
console.log('start');
start();
} else {
if (cancel) {
console.log('cancel');
cancel();
} else {
console.log('no cancel');
}
}
}
setTimeout(() => {
observer.observe(useSecondCanvas ? secondCanvas : canvas);
}, 100);

return useSecondCanvas ? secondCanvas : canvas;
}
Insert cell
// makeRegl3(`
// vec2 uv = gl_FragCoord.xy / iResolution;
// float dist = length(gl_FragCoord.xy);
// vec2 textureCoords = uv + cos(t) * vec2(0.5 - uv.y, uv.x - 0.5) - sin(2.0 * t) * (uv - 0.5);
// vec3 textureData = texture(prevFrame, textureCoords).rgb;
// vec4 addVec = vec4(
// 1.0 + cos(2.0 * t),
// 1.0 + cos(2.0 * t + 1.5),
// 1.0 + cos(2.0 * t + 3.0),
// 0.0
// );
// float addVecCoeff = exp(-0.01 * dist);
// fragColor = vec4(0.98 * textureData, 1) + addVecCoeff * addVec;
// `)
Insert cell
// function makeRegl3(glsl, funcs='', height=400) {
// const threshold = 0.5;
// const dpi = window.devicePixelRatio;
// const pxWidth = Math.round(width * dpi);
// const pxHeight = Math.round(height * dpi);
// const canvas = DOM.canvas(pxWidth, pxHeight);
// canvas.style.width = width + 'px';
// const regl = reglConstructor({
// canvas: canvas,
// extensions: ['OES_standard_derivatives', 'EXT_shader_texture_lod'],
// });
// const pixels = regl.texture();
// const drawFeedback = regl({
// frag: `#version 300 es
// precision mediump float;
// uniform sampler2D prevFrame;
// uniform float t;
// uniform vec2 iResolution;
// // in vec2 uv;
// out vec4 fragColor;

// ${funcs}

// void main () {
// ${glsl}
// }`,
// vert: `#version 300 es
// precision mediump float;
// attribute vec2 position;
// // varying vec2 uv;
// void main () {
// // uv = position;
// gl_Position = vec4(2.0 * position - 1.0, 0, 1);
// }`,
// attributes: {
// position: [
// -2, 0,
// 0, -2,
// 2, 2]
// },
// uniforms: {
// prevFrame: pixels,
// t: ({tick}) => 0.01 * tick,
// iResolution: [pxWidth, pxHeight],
// },
// count: 3
// })

// let cancel = null;
// let running = false;

// const start = () => {
// if (running) {
// console.log('already running');
// return;
// }
// running = true;
// const doCancel = regl.frame(function () {
// regl.clear({
// color: [0, 0, 0, 1]
// })
// drawFeedback()
// pixels({
// copy: true
// })
// }).cancel;
// cancel = () => {
// if (!running) {
// console.log('not cancelling because not running');
// } else {
// running = false;
// doCancel();
// }
// }
// }

// const observer = new IntersectionObserver(onIntersection, {threshold});
// function onIntersection(entries, opts){
// if (entries[0].intersectionRatio > threshold || threshold === 0 && entries[0].isIntersecting) {
// console.log('start');
// start();
// } else {
// if (cancel) {
// console.log('cancel');
// cancel();
// } else {
// console.log('no cancel');
// }
// }
// }
// setTimeout(() => {
// observer.observe(canvas);
// }, 100);
// // start();


// return canvas;
// }
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