Tiny and beautiful programs living on the Web
Alexander Mordvintsev, Google, 2024
<!DOCTYPE html>
<title>Tiny SwissGL example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<script src="swissgl.js"></script>
<style>
body, html {margin: 0; padding: 0; overflow: hidden;}
#c {width:100vw; height: 100vh}
</style>
<canvas id="c"></canvas>
<script>
"use strict";
const canvas = document.getElementById('c');
const glsl = SwissGL(canvas);
glsl.loop(({time})=>{
glsl.adjustCanvas();
glsl({time, Aspect:'cover',FP:`
sin(length(XY)*vec3(30,30.5,31)
-time+atan(XY.x,XY.y)*3.),1`});
});
</script>
vec2 UV
– quad coordinates [0..1]x[0..1]vec4 FOut
– output color (RGBA)We also have vec2 XY
(same as UV, but [-1..1]x[-1..1]), and full
GLSL ES to use
ivec2 I
- integer pixel coordinates
Options: "fit", "cover", "x", "y", "mean"
(I'm not 100% happy about this design, might change in th future)
Options: "fit", "cover", "x", "y", "mean"
(I'm not 100% happy about this design, might change in th future)
But why are image top and bottom clipped?
Aspect
it covers the full viewAspect:'fit'
makes this quad to fit the view
Full syntax
Is quad boring? 🥱
Grid
and Mesh
work together
Problem?
In simple cases we may also useFace:'front'
or
Face:'back'
No perspective?
We can also pass per-vertex colors
Fragment program draws a radially decaying sprite, but it's still a opaque quad
Blend
Clear
Note the use of integer pixel coordinates
(ping-pong buffers)