Skip to content

Instantly share code, notes, and snippets.

@filippovitale
Created February 2, 2017 22:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save filippovitale/97e5007bb76bf4bb50802ef25b1c0cc2 to your computer and use it in GitHub Desktop.
Save filippovitale/97e5007bb76bf4bb50802ef25b1c0cc2 to your computer and use it in GitHub Desktop.
Unpacked version (with comments) of the beautiful TEA STORM
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Tea Storm unpacked</title>
</head>
<body onload=setInterval(paint,32)>
<canvas id=c />
<script>
/*
http://www.p01.org/tea_storm/
TEA STORM won at the 256 bytes intro competition at Function 2013 in Budapest,
Hungary on September 14th, 2013.
Casts 75x75 rays with up to 40 checks along the rays which amounts to a maximum
of 75x75x40 = 225,000 tests.
No fixed step raymarching but a distance function that gives an estimate of how
far is the surface of the object at each point in 3D space and the rays march on
until they get close enough.
That part is trivial: A canvas, a body element with onload event setting a timer
that clears the canvas, adjust the time variable, go through each pixel and
render them. Just make sure to reuse variables where possible, set the right
properties and create alias variables where necessary.
*/
m=4
t=64
h=64
Q=Math.cos
function draw(xx, yy, nn) {
// with nn in the range [0; m]
c.getContext('2d').fillRect(xx*m,yy*m,nn,nn)
}
function compute_intensity() {
N=4; // the number of iterations
D=4; // the distance, how far we marched along the current camera ray
d=1; // distance to the object is estimated in `d`
// This is a safe distance considering the origin of the camera. At each step,
// the new position along the camera ray is computed in 3D space in X, Y and Z,
// the distance to the object is estimated in d and added to D, and N decreased
// by 0.1.
// the condition `.1<d*N`:
// - Ensure that we stop when N reaches 0 or we have reached the object.
// - The multiplication d*N introduces an approximation of the focal distance.
for(;.1<d*N;) {
// The origin of the camera lies in {0, 0, -9} and looks toward {0, 0, 0}
X=D*(x/h)-D/2;
Y=D*y/h-D/2;
Z=D/2-9;
// Sphere
//d=(X*X+Y*Y+Z*Z)/9-1
// Sphere morphing into a cylinder
//d=(X*X+Y*Y*Q(t/6)+Z*Z)/9-1
// Bumpy sphere
//d=(X*X+Y*Y+Z*Z)/9-1+Q(X+t)*Q(Y-t)
// Bumpy sphere-cylinder
//d=(X*X+Y*Y*Q(t/6)+Z*Z)/9-1+Q(X+t)*Q(Y-t)
// Bumpy twirling morphing sphere-cylinder \(';;')/
d=(X*X+Y*Y*Q(t/6+Q(D-X-Y))+Z*Z)/9-1+Q(X+t)*Q(Y-t);
D+=d;
//
N-=.1;
// the further we are from the origin of the camera, the bigger the margin of
// error we can allow without any visual artefact. Of course this is not
// entirelly correct since N does not represent the distance travelled but the
// number of iterations, but this is good enough.
}
}
function paint() {
// adjust the time variable
t-=.1
// clear the canvas
c.height=h*m
c.width=h*m
// c.getContext('2d').clearRect(0, 0, h*m, h*m);
// X loop from 75 to 0 (if h=75)
for(x=h;x--;)
// Y loop from 75 to 0 (if h=75)
for(y=h;y--;draw(x,y,N))
compute_intensity();
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment