PixAnvil/Three.js demo
Setup
Loop
P
UI
Save
Stats
sim.nP=120*120; // number of particles (size of texture) sim.P=new gVector1D(sim.nP); // current particle positions sim.Pnext=new gVector1D(sim.nP); // positions in next frame sim.P.debugTo(scene,10.0,0.0,10.0,5.0); // Ground var groundTex=THREE.ImageUtils.loadTexture( "textures/checkerboard_noisy.jpg" ); groundTex.wrapS=groundTex.wrapT=THREE.RepeatWrapping; groundTex.repeat=new vec2(25.0,25.0); sim.ground = new THREE.Mesh( new THREE.CubeGeometry(50,50,0.0001), new THREE.MeshLambertMaterial( {color: 0xffccaa, opacity: 1, map:groundTex}) ); sim.ground.position.z=-1; /* hack for radius 1 */ sim.ground.receiveShadow=true; scene.add(sim.ground); // Sun-like spotlight var l=new THREE.SpotLight(); sim.light = l; l.position.set( -50, -100, 100 ); l.castShadow=true; l.shadowCameraNear = 50; l.shadowCameraFar = 500; l.shadowCameraFov = 10; // degrees field of view scene.add(l);
// This GLSL code updates the P array if (!sim.fnP) { sim.fnP=new gFunction1D(PixAnvil.loadTab('P')); } sim.fnP.set("dt",lib.dt); sim.fnP.set("time",lib.time); sim.fnP.set("P",sim.P); // read from P sim.fnP.run(sim.Pnext); // write to Pnext sim.Pnext.swap(sim.P); // ping-pong buffers
/* This code calculates the new P positions */ /* uniforms are set automatically (see Loop) */ vec4 run(float index) { float threshold=13000.0-1200.0*cos(time*0.2); if (index>threshold) { // top: red stripes return vec4(sin(index*0.1),0.0,0.0,1.0); } else if (index==1598.0) { // lone green pixel return vec4(0,1,0,1); } else { // bottom: crazy color shifting! float above=index+128.0; // pixels/row vec4 L=P(above-1.0); vec4 C=P(above); vec4 R=P(above+1.0); vec4 average=(L+C+R)/3.0; return fract(average-0.01); } }
// Camera control: // Update camera coordinate system var s=camera; if (!s.X) { // startup: create initial coordinates s.X=new vec3(1,0,0); s.Y=new vec3(0,0,1); s.Z=new vec3(0,-1,-0.2); // camera Z is world Y s.P=new vec3(0,-5,1.3); // initial location } // Move camera via keyboard var move=new vec3(0,0,0); // sums current frame motion // X control via A and D if (lib.key['a']) move.pe(new vec3(-1,0,0)); if (lib.key['d']) move.pe(new vec3(+1,0,0)); // Y control via W and S if (lib.key['w']) move.pe(new vec3(0,0,-1)); if (lib.key['s']) move.pe(new vec3(0,0,+1)); // Z control via Q and Z if (lib.key['q']) move.pe(new vec3(0,+1,0)); if (lib.key['z']) move.pe(new vec3(0,-1,0)); move.te(5.0*lib.dt); // meters/second motion rate s.P.pe(s.X.t(move.x).p(s.Y.t(move.y)).p(s.Z.t(move.z))); // Rotate camera via mouse var speed=0.01; // radians per mouse pixel if (lib.mouseleft) { // move Z with mouse s.Z.pe(s.X.t(-lib.mousedx*speed).p( s.Y.t( lib.mousedy*speed))); } // Keep level: make sure X is horizontal. s.X.z=0.0; s.Y.crossVectors(s.Z,s.X.normalize()); // Orthonormalize s.X.crossVectors(s.Y,s.Z).normalize(); s.Y.crossVectors(s.Z,s.X).normalize(); s.Z.normalize(); // Write coordinate system into matrix s.matrixAutoUpdate=false; // don't trash s.matrixWorldNeedsUpdate=true; // show var m=s.matrix; // the camera's matrix // Utility function: set a matrix column function setCol(m,col,vec) { m.elements[4*col+0]=vec.x; m.elements[4*col+1]=vec.y; m.elements[4*col+2]=vec.z; } setCol(m,0,s.X); setCol(m,1,s.Y); setCol(m,2,s.Z); setCol(m,3,s.P); // position from sim
To save, copy this text into a
plain text
editor like Notepad, and save as HTML.
Startup: 15 ms
Time:
10x
1x
0.1x
0.01x
0.001x
0.0001x