<main>
<video id="video" playsinline></video>
<button id="access">Access Camera</button>
<canvas id="canvas"></canvas>
<div id="buttons">
<button data-shader="gl_FragColor = vec4(color, 1.0);">Default</button>
<button data-shader="gl_FragColor = vec4(color * vec3(0.9, 0.0, 1.0), 1.0);">Purple</button>
<button data-shader="gl_FragColor = vec4(color * vec3(1.5, 1.5, 0.0), 1.0);">Yellow</button>
<button data-shader="color = smoothstep(vec3(0.2), vec3(0.8), color); gl_FragColor = vec4(color, 1.0);">High Contrast</button>
<button data-shader="gl_FragColor = vec4(vec3(1.0) - color, 1.0);">Invert</button>
<button data-shader="color += vec3(sin(4.5 * u_time), sin(3.1 * u_time + 1.0), sin(2.7 * u_time)); gl_FragColor = vec4(color, 1.0);">Rave</button>
</div>
</main>
main {
align-items: center;
display: flex;
height: 100vh;
justify-content: center;
width: 100vw;
}
#canvas,
#video,
#buttons {
display: none;
}
button {
color: #558;
cursor: pointer;
border: 0.3em solid #558;
font-weight: bold;
letter-spacing: 0.1em;
text-transform: uppercase;
padding: 0.35em 1em;
transition: 0.2s;
}
button:hover,
button:active {
background: #558;
box-shadow: 0 0 3px #000;
color: #fff;
}
#canvas,
#buttons {
float: left;
}
#buttons {
max-width: 400px;
}
#buttons button {
display: block;
margin: 10px 0 0 10px;
text-align: center;
width: 200px;
}
#access {
display: block;
font-size: 1.5em;
}
canvas {
height: auto;
max-width: 400px;
}
View Compiled
const video = document.getElementById('video');
const buffer = document.createElement('canvas');
const canvas = document.getElementById('canvas');
let glslCanvas;
let fragColor = `gl_FragColor = vec4(color, 1.0);`;
function init() {
window.navigator.mediaDevices.getUserMedia({
audio: false,
video: {
facing: 'user'
}
})
.then(setup)
.catch((err) => console.log('There was an error 😱', err));
}
function setup(stream) {
canvas.style.display = 'block';
document.getElementById('access').style.display = 'none';
document.getElementById('buttons').style.display = 'block';
video.srcObject = stream;
video.play();
window.devicePixelRatio = 1;
update();
}
function render() {
buffer.width = video.videoWidth;
buffer.height = video.videoHeight;
buffer.getContext('2d').drawImage(video, 0, 0);
canvas.width = buffer.width;
canvas.height = buffer.height;
if (!glslCanvas) {
glslCanvas = new GlslCanvas(canvas);
update();
}
var dataURL = buffer.toDataURL();
glslCanvas.setUniform('u_texture', dataURL);
window.requestAnimationFrame(render);
}
function update() {
const vertexShader = `
#ifdef GL_ES
precision mediump float;
#endif
uniform sampler2D u_texture;
uniform vec2 u_resolution;
uniform float u_time;
void main() {
vec2 st = gl_FragCoord.xy / u_resolution.xy;
float x = gl_FragCoord.x;
float y = gl_FragCoord.y;
vec3 color = texture2D(u_texture, st).rgb;
${fragColor}
}
`;
if (glslCanvas) glslCanvas.load(vertexShader);
}
function toggle() {
fragColor = this.getAttribute('data-shader');
update();
}
document.getElementById('access').addEventListener('click', init);
video.addEventListener('canplay', render);
[...document.getElementById('buttons').children].forEach(button => {
button.addEventListener('click', toggle);
});
This Pen doesn't use any external CSS resources.