Skip to content

Instantly share code, notes, and snippets.

@mikecann
Created August 21, 2011 14:33
Show Gist options
  • Save mikecann/1160680 to your computer and use it in GitHub Desktop.
Save mikecann/1160680 to your computer and use it in GitHub Desktop.
Trying to get double buffered rendering working in Three.JS HaXe
package threeUtils;
import js.Lib;
import three.Camera;
import three.Matrix4;
import three.Mesh;
import three.MeshShaderMaterial;
import three.PlaneGeometry;
import three.Scene;
import three.ShaderUtils;
import three.Texture;
import three.UniformsUtils;
import three.WebGLRenderer;
import three.WebGLRenderTarget;
import three.THREE;
/**
* ...
* @author MikeCann
*/
class DoubleBufferedRT
{
public var width : Int;
public var height : Int;
public var target1 : WebGLRenderTarget;
public var target2 : WebGLRenderTarget;
private var areTargetsFlipped : Bool;
public function new(width:Int, height:Int, ?options:Dynamic)
{
this.width = width;
this.height = height;
target1 = new WebGLRenderTarget(width, height, options);
target2 = new WebGLRenderTarget(width, height, options);
areTargetsFlipped = false;
}
public function initBuffers(renderer:WebGLRenderer,tex:Texture) : Void
{
var scene = new Scene();
var cam = new Camera();
cam.projectionMatrix = Matrix4.makeOrtho( Lib.window.innerWidth / - 2, Lib.window.innerWidth / 2, Lib.window.innerHeight / 2, Lib.window.innerHeight / - 2, -10000, 10000 );
cam.position.z = 100;
var screen_shader = ShaderUtils.lib.screen;
var screen_uniforms = UniformsUtils.clone( screen_shader.uniforms );
screen_uniforms.tDiffuse.texture = tex;
var mat = new MeshShaderMaterial( {
uniforms: screen_uniforms,
vertexShader: screen_shader.vertexShader,
fragmentShader: screen_shader.fragmentShader,
blending: AdditiveBlending,
transparent: true
} );
var quad = new Mesh(new PlaneGeometry(Lib.window.innerWidth, Lib.window.innerHeight), mat);
quad.position.z = -100;
scene.addObject( quad );
renderer.render( scene, cam, target1, false );
renderer.render( scene, cam, target2, false );
}
public function flip() : DoubleBufferedRT
{
areTargetsFlipped = !areTargetsFlipped;
return this;
}
public function getFront() : WebGLRenderTarget
{
return areTargetsFlipped?target1:target2;
}
public function getBack() : WebGLRenderTarget
{
return areTargetsFlipped?target2:target1;
}
}
package ;
import Html5Dom;
import three.DataTexture;
import threeUtils.DoubleBufferedRT;
import three.Matrix4;
import three.Mesh;
import three.MeshShaderMaterial;
import three.Sprite;
import three.Texture;
import three.WebGLRenderTarget;
import utils.js.JSFramerate;
import js.Lib;
import utils.js.ThreeUtils;
import utils.Rand;
import utils.RequestAnimationFrame;
import three.Camera;
import three.Scene;
import three.MeshDepthMaterial;
import three.WebGLRenderer;
import three.MeshBasicMaterial;
import three.ImageUtils;
import three.THREE;
import three.PlaneGeometry;
import three.ShaderUtils;
import three.UniformsUtils;
/**
* ...
* @author MikeCann
*/
class ThreeParticles
{
public var numParticles : Int;
public var particleSize : Int;
public var dontUseTexture : Bool;
private var framerate : JSFramerate;
private var container : Dynamic;
private var width : Int;
private var height : Int;
private var cameraOrtho : Camera;
private var renderer : WebGLRenderer;
private var updatesScene : Scene;
private var finalScene : Scene;
private var positions : DoubleBufferedRT;
private var velocities : DoubleBufferedRT;
private var materialUpdates : MeshShaderMaterial;
private var materialFinal : MeshShaderMaterial;
private var rtFlip : Bool;
public function new()
{
numParticles = 1000;
particleSize = 32;
dontUseTexture = false;
init();
}
private function onResize():Void
{
width = Lib.window.innerWidth;
height = Lib.window.innerHeight;
renderer.setSize( width, height );
trace(width + ", " + height);
}
public function init() : Void
{
initRenderer();
initCamera();
initBuffers();
initUpdatesScene();
initFinalScene();
// Begin updates
framerate = new JSFramerate();
render();
}
private function initRenderer() : Void
{
// Create the container and listen for resizes
container = cast Lib.document.createElement( 'div' );
Lib.document.body.appendChild( container );
new JQuery(Lib.window).resize(onResize);
width = Lib.window.innerWidth;
height = Lib.window.innerHeight;
// Create renderer
renderer = new WebGLRenderer(); // { antialias: true }
renderer.setSize( width, height );
renderer.sortObjects = false;
renderer.setClearColorHex(0x123456, 0.5);
container.appendChild(renderer.domElement);
}
private function initCamera() : Void
{
// Just stick with 2D for now
cameraOrtho = new Camera();
cameraOrtho.projectionMatrix = Matrix4.makeOrtho( Lib.window.innerWidth / - 2, Lib.window.innerWidth / 2, Lib.window.innerHeight / 2, Lib.window.innerHeight / - 2, -10000, 10000 );
cameraOrtho.position.z = 100;
}
private function initBuffers() : Void
{
// Just populate the buffers with some random values for now
var imgW = 100, imgH = 100, imgB = 3;
var positionsData = new Uint8Array( imgW * imgH * imgB );
var velocitiesData = new Uint8Array( imgW * imgH * imgB );
for (i in 0...(imgW*imgH*imgB))
{
positionsData[i] = Rand.integer(0, 256);
velocitiesData[i] = Rand.integer(0, 100);
}
// Positions
var t : DataTexture = new DataTexture( positionsData, imgW, imgH, RGBFormat );
t.needsUpdate = true;
positions = new DoubleBufferedRT( 100, 100, { minFilter: LinearFilter, magFilter: NearestFilter, format: RGBFormat } );
positions.initBuffers(renderer,t);
// Velocities
var t : DataTexture = new DataTexture( velocitiesData, imgW, imgH, RGBFormat );
t.needsUpdate = true;
velocities = new DoubleBufferedRT( 100, 100, { minFilter: LinearFilter, magFilter: NearestFilter, format: RGBFormat } );
velocities.initBuffers(renderer,t);
}
private function initUpdatesScene() : Void
{
updatesScene = new Scene();
// Make the updates material for the screen quad
materialUpdates = new MeshShaderMaterial({
uniforms: {
tPositions: { type: "t", value: 0, texture: null },
tVelocities: { type: "t", value: 0, texture: null }
},
vertexShader: getPositionsVS(),
fragmentShader: getPositionsFS(),
depthTest: false
} );
// Positions quad
var plane = new PlaneGeometry(Lib.window.innerWidth, Lib.window.innerHeight);
var quadScreen = new Mesh(plane, materialUpdates );
quadScreen.position.z = -100;
updatesScene.addObject( quadScreen );
}
private function initFinalScene() : Void
{
finalScene = new Scene();
// Final scene will just use the default screen shader
var screen_shader = ShaderUtils.lib.screen;
var screen_uniforms = UniformsUtils.clone( screen_shader.uniforms );
materialFinal = new MeshShaderMaterial( {
uniforms: screen_uniforms,
vertexShader: screen_shader.vertexShader,
fragmentShader: screen_shader.fragmentShader,
blending: AdditiveBlending,
transparent: true
} );
// Final quad
var plane = new PlaneGeometry(Lib.window.innerWidth, Lib.window.innerHeight);
var quadScreen = new Mesh( plane, materialFinal );
quadScreen.position.z = -100;
finalScene.addObject( quadScreen );
}
private function render() : Void
{
// First we perform the updates.
materialUpdates.uniforms.tPositions.texture = positions.getFront();
materialUpdates.uniforms.tVelocities.texture = velocities.getFront();
renderer.render(updatesScene, cameraOrtho, positions.getBack(), false );
// Next we render the buffer to the screen
materialFinal.uniforms.tDiffuse.texture = positions.getBack();
renderer.render( finalScene, cameraOrtho );
// Dont forget to flip our buffers
positions.flip();
velocities.flip();
// Next
RequestAnimationFrame.request(render);
framerate.incFrames();
}
private function getPositionsVS() : String
{
return
"
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
";
}
private function getPositionsFS() : String
{
return
"
varying vec2 vUv;
uniform sampler2D tPositions;
uniform sampler2D tVelocities;
void main(void)
{
vec4 position = texture2D( tPositions, vUv );
vec4 velocity = texture2D( tVelocities, vUv );
gl_FragColor = position;
gl_FragColor.r += 0.005;
gl_FragColor.a = 1.0;
/*gl_FragColor = texture2D( tPositions, vUv );
gl_FragColor.r += 0.01;*/
}
";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment