Created
February 2, 2017 22:06
-
-
Save filippovitale/97e5007bb76bf4bb50802ef25b1c0cc2 to your computer and use it in GitHub Desktop.
Unpacked version (with comments) of the beautiful TEA STORM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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