Created
August 21, 2011 14:33
-
-
Save mikecann/1160680 to your computer and use it in GitHub Desktop.
Trying to get double buffered rendering working in Three.JS HaXe
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
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; | |
} | |
} |
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
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