mirror of
https://github.com/Doodle3D/Doodle3D-Slicer.git
synced 2024-12-25 12:23:49 +01:00
228 lines
6.1 KiB
JavaScript
228 lines
6.1 KiB
JavaScript
|
/**
|
||
|
* @author zz85 https://github.com/zz85 / http://www.lab4games.net/zz85/blog
|
||
|
*
|
||
|
* Bird Simulation Render
|
||
|
*
|
||
|
* A simple scene rendering a quad of the following shaders
|
||
|
* 1. Pass-thru Shader,
|
||
|
* 2. Bird Position Update Shader,
|
||
|
* 3. Bird Velocity Update Shader
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
function SimulationRenderer(WIDTH, renderer) {
|
||
|
|
||
|
WIDTH = WIDTH || 4;
|
||
|
var camera = new THREE.Camera();
|
||
|
camera.position.z = 1;
|
||
|
|
||
|
// Init RTT stuff
|
||
|
gl = renderer.getContext();
|
||
|
|
||
|
if ( !gl.getExtension( "OES_texture_float" )) {
|
||
|
alert( "No OES_texture_float support for float textures!" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS) == 0) {
|
||
|
alert( "No support for vertex shader textures!" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var scene = new THREE.Scene();
|
||
|
|
||
|
var uniforms = {
|
||
|
time: { type: "f", value: 1.0 },
|
||
|
resolution: { type: "v2", value: new THREE.Vector2( WIDTH, WIDTH ) },
|
||
|
texture: { type: "t", value: null }
|
||
|
};
|
||
|
|
||
|
var passThruShader = new THREE.ShaderMaterial( {
|
||
|
uniforms: uniforms,
|
||
|
vertexShader: document.getElementById( 'vertexShader' ).textContent,
|
||
|
fragmentShader: document.getElementById( 'fragmentShader' ).textContent
|
||
|
} );
|
||
|
|
||
|
var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), passThruShader );
|
||
|
|
||
|
var positionShader = new THREE.ShaderMaterial( {
|
||
|
|
||
|
uniforms: {
|
||
|
time: { type: "f", value: 1.0 },
|
||
|
delta: { type: "f", value: 0.0 },
|
||
|
resolution: { type: "v2", value: new THREE.Vector2( WIDTH, WIDTH ) },
|
||
|
texturePosition: { type: "t", value: null },
|
||
|
textureVelocity: { type: "t", value: null },
|
||
|
},
|
||
|
vertexShader: document.getElementById( 'vertexShader' ).textContent,
|
||
|
fragmentShader: document.getElementById( 'fragmentShaderPosition' ).textContent
|
||
|
|
||
|
} );
|
||
|
|
||
|
this.positionShader = positionShader;
|
||
|
|
||
|
var velocityShader = new THREE.ShaderMaterial( {
|
||
|
|
||
|
uniforms: {
|
||
|
time: { type: "f", value: 1.0 },
|
||
|
delta: { type: "f", value: 0.0 },
|
||
|
resolution: { type: "v2", value: new THREE.Vector2( WIDTH, WIDTH ) },
|
||
|
texturePosition: { type: "t", value: null },
|
||
|
textureVelocity: { type: "t", value: null },
|
||
|
testing: { type: "f", value: 1.0 },
|
||
|
seperationDistance: { type: "f", value: 1.0 },
|
||
|
alignmentDistance: { type: "f", value: 1.0 },
|
||
|
cohesionDistance: { type: "f", value: 1.0 },
|
||
|
freedomFactor: { type: "f", value: 1.0 },
|
||
|
predator: { type: "v3", value: new THREE.Vector3() }
|
||
|
},
|
||
|
defines: {
|
||
|
WIDTH: WIDTH.toFixed(2)
|
||
|
},
|
||
|
vertexShader: document.getElementById( 'vertexShader' ).textContent,
|
||
|
fragmentShader: document.getElementById( 'fragmentShaderVelocity' ).textContent
|
||
|
|
||
|
} );
|
||
|
|
||
|
this.velocityUniforms = velocityShader.uniforms;
|
||
|
|
||
|
scene.add( mesh );
|
||
|
|
||
|
var flipflop = true;
|
||
|
var rtPosition1, rtPosition2, rtVelocity1, rtVelocity2;
|
||
|
|
||
|
function init() {
|
||
|
var dtPosition = generatePositionTexture();
|
||
|
var dtVelocity = generateVelocityTexture();
|
||
|
|
||
|
rtPosition1 = getRenderTarget( THREE.RGBAFormat );
|
||
|
rtPosition2 = rtPosition1.clone();
|
||
|
rtVelocity1 = getRenderTarget( THREE.RGBFormat );
|
||
|
rtVelocity2 = rtVelocity1.clone();
|
||
|
|
||
|
simulator.renderTexture(dtPosition, rtPosition1);
|
||
|
simulator.renderTexture(rtPosition1, rtPosition2);
|
||
|
|
||
|
simulator.renderTexture(dtVelocity, rtVelocity1);
|
||
|
simulator.renderTexture(rtVelocity1, rtVelocity2);
|
||
|
|
||
|
simulator.velocityUniforms.testing.value = 10;
|
||
|
}
|
||
|
|
||
|
this.init = init;
|
||
|
|
||
|
function getRenderTarget( type ) {
|
||
|
var renderTarget = new THREE.WebGLRenderTarget(WIDTH, WIDTH, {
|
||
|
wrapS: THREE.RepeatWrapping,
|
||
|
wrapT: THREE.RepeatWrapping,
|
||
|
minFilter: THREE.NearestFilter,
|
||
|
magFilter: THREE.NearestFilter,
|
||
|
format: type,
|
||
|
type: THREE.FloatType,
|
||
|
stencilBuffer: false
|
||
|
});
|
||
|
|
||
|
return renderTarget;
|
||
|
}
|
||
|
|
||
|
// Takes a texture, and render out as another texture
|
||
|
this.renderTexture = function ( input, output ) {
|
||
|
mesh.material = passThruShader;
|
||
|
uniforms.texture.value = input;
|
||
|
renderer.render( scene, camera, output );
|
||
|
}
|
||
|
|
||
|
|
||
|
this.renderPosition = function(position, velocity, output, delta) {
|
||
|
mesh.material = positionShader;
|
||
|
positionShader.uniforms.texturePosition.value = position;
|
||
|
positionShader.uniforms.textureVelocity.value = velocity;
|
||
|
positionShader.uniforms.time.value = performance.now();
|
||
|
positionShader.uniforms.delta.value = delta;
|
||
|
renderer.render( scene, camera, output );
|
||
|
this.currentPosition = output;
|
||
|
}
|
||
|
|
||
|
this.renderVelocity = function(position, velocity, output, delta) {
|
||
|
mesh.material = velocityShader;
|
||
|
velocityShader.uniforms.texturePosition.value = position;
|
||
|
velocityShader.uniforms.textureVelocity.value = velocity;
|
||
|
velocityShader.uniforms.time.value = performance.now();
|
||
|
velocityShader.uniforms.delta.value = delta;
|
||
|
renderer.render( scene, camera, output );
|
||
|
this.currentVelocity = output;
|
||
|
}
|
||
|
|
||
|
this.simulate = function( delta ) {
|
||
|
|
||
|
if (flipflop) {
|
||
|
|
||
|
simulator.renderVelocity( rtPosition1, rtVelocity1, rtVelocity2, delta );
|
||
|
simulator.renderPosition( rtPosition1, rtVelocity2, rtPosition2, delta );
|
||
|
|
||
|
} else {
|
||
|
|
||
|
simulator.renderVelocity( rtPosition2, rtVelocity2, rtVelocity1, delta );
|
||
|
simulator.renderPosition( rtPosition2, rtVelocity1, rtPosition1, delta );
|
||
|
|
||
|
}
|
||
|
|
||
|
flipflop = !flipflop;
|
||
|
|
||
|
}
|
||
|
|
||
|
function generatePositionTexture() {
|
||
|
|
||
|
var a = new Float32Array( PARTICLES * 4 );
|
||
|
|
||
|
for ( var k = 0, kl = a.length; k < kl; k += 4 ) {
|
||
|
|
||
|
var x = Math.random() * BOUNDS - BOUNDS_HALF;
|
||
|
var y = Math.random() * BOUNDS - BOUNDS_HALF;
|
||
|
var z = Math.random() * BOUNDS - BOUNDS_HALF;
|
||
|
|
||
|
a[ k + 0 ] = x;
|
||
|
a[ k + 1 ] = y;
|
||
|
a[ k + 2 ] = z;
|
||
|
a[ k + 3 ] = 1;
|
||
|
|
||
|
}
|
||
|
|
||
|
var texture = new THREE.DataTexture( a, WIDTH, WIDTH, THREE.RGBAFormat, THREE.FloatType );
|
||
|
texture.minFilter = THREE.NearestFilter;
|
||
|
texture.magFilter = THREE.NearestFilter;
|
||
|
texture.needsUpdate = true;
|
||
|
texture.flipY = false;
|
||
|
|
||
|
return texture;
|
||
|
|
||
|
}
|
||
|
|
||
|
function generateVelocityTexture() {
|
||
|
|
||
|
var a = new Float32Array( PARTICLES * 3 );
|
||
|
|
||
|
for ( var k = 0, kl = a.length; k < kl; k += 3 ) {
|
||
|
|
||
|
var x = Math.random() - 0.5;
|
||
|
var y = Math.random() - 0.5;
|
||
|
var z = Math.random() - 0.5;
|
||
|
|
||
|
a[ k + 0 ] = x * 10;
|
||
|
a[ k + 1 ] = y * 10;
|
||
|
a[ k + 2 ] = z * 10;
|
||
|
|
||
|
}
|
||
|
|
||
|
var texture = new THREE.DataTexture( a, WIDTH, WIDTH, THREE.RGBFormat, THREE.FloatType );
|
||
|
texture.minFilter = THREE.NearestFilter;
|
||
|
texture.magFilter = THREE.NearestFilter;
|
||
|
texture.needsUpdate = true;
|
||
|
texture.flipY = false;
|
||
|
|
||
|
return texture;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|