소스 검색

Refactored postprocessing to use double buffering.

Cause everywhere there are warnings about not writing to the same texture which is also being read. Curiously enough this didn't make problems so far (save for mysterious lines when doing "heat" effect in ro.me).
alteredq 14 년 전
부모
커밋
20fae814e7

+ 3 - 2
build/Three.js

@@ -329,8 +329,9 @@ THREE.Line){h=g.geometry;if(h.__dirtyVertices||h.__dirtyColors){g=h;j=n.DYNAMIC_
 n.bufferData(n.ARRAY_BUFFER,H,j)}}h.__dirtyVertices=!1;h.__dirtyColors=!1}else if(g instanceof THREE.ParticleSystem)h=g.geometry,m=y(h),(h.__dirtyVertices||h.__dirtyColors||g.sortParticles||m)&&c(h,n.DYNAMIC_DRAW,g),h.__dirtyVertices=!1,h.__dirtyColors=!1,G(h)};this.setFaceCulling=function(b,c){b?(!c||c=="ccw"?n.frontFace(n.CCW):n.frontFace(n.CW),b=="back"?n.cullFace(n.BACK):b=="front"?n.cullFace(n.FRONT):n.cullFace(n.FRONT_AND_BACK),n.enable(n.CULL_FACE)):n.disable(n.CULL_FACE)};this.supportsVertexTextures=
 function(){return sa}};
 THREE.WebGLRenderTarget=function(b,c,e){this.width=b;this.height=c;e=e||{};this.wrapS=e.wrapS!==void 0?e.wrapS:THREE.ClampToEdgeWrapping;this.wrapT=e.wrapT!==void 0?e.wrapT:THREE.ClampToEdgeWrapping;this.magFilter=e.magFilter!==void 0?e.magFilter:THREE.LinearFilter;this.minFilter=e.minFilter!==void 0?e.minFilter:THREE.LinearMipMapLinearFilter;this.offset=new THREE.Vector2(0,0);this.repeat=new THREE.Vector2(1,1);this.format=e.format!==void 0?e.format:THREE.RGBAFormat;this.type=e.type!==void 0?e.type:
-THREE.UnsignedByteType;this.depthBuffer=e.depthBuffer!==void 0?e.depthBuffer:!0;this.stencilBuffer=e.stencilBuffer!==void 0?e.stencilBuffer:!0};THREE.WebGLRenderTargetCube=function(b,c,e){THREE.WebGLRenderTarget.call(this,b,c,e);this.activeCubeFace=0};THREE.WebGLRenderTargetCube.prototype=new THREE.WebGLRenderTarget;THREE.WebGLRenderTargetCube.prototype.constructor=THREE.WebGLRenderTargetCube;
-THREE.RenderableVertex=function(){this.positionWorld=new THREE.Vector3;this.positionScreen=new THREE.Vector4;this.visible=!0};THREE.RenderableVertex.prototype.copy=function(b){this.positionWorld.copy(b.positionWorld);this.positionScreen.copy(b.positionScreen)};
+THREE.UnsignedByteType;this.depthBuffer=e.depthBuffer!==void 0?e.depthBuffer:!0;this.stencilBuffer=e.stencilBuffer!==void 0?e.stencilBuffer:!0};
+THREE.WebGLRenderTarget.prototype.clone=function(){var b=new THREE.WebGLRenderTarget(this.width,this.height);b.wrapS=this.wrapS;b.wrapT=this.wrapT;b.magFilter=this.magFilter;b.minFilter=this.minFilter;b.offset.copy(this.offset);b.repeat.copy(this.repeat);b.format=this.format;b.type=this.type;b.depthBuffer=this.depthBuffer;b.stencilBuffer=this.stencilBuffer;return b};THREE.WebGLRenderTargetCube=function(b,c,e){THREE.WebGLRenderTarget.call(this,b,c,e);this.activeCubeFace=0};
+THREE.WebGLRenderTargetCube.prototype=new THREE.WebGLRenderTarget;THREE.WebGLRenderTargetCube.prototype.constructor=THREE.WebGLRenderTargetCube;THREE.RenderableVertex=function(){this.positionWorld=new THREE.Vector3;this.positionScreen=new THREE.Vector4;this.visible=!0};THREE.RenderableVertex.prototype.copy=function(b){this.positionWorld.copy(b.positionWorld);this.positionScreen.copy(b.positionScreen)};
 THREE.RenderableFace3=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.faceMaterials=this.meshMaterials=null;this.overdraw=!1;this.uvs=[[]];this.z=null};
 THREE.RenderableFace4=function(){this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.v3=new THREE.RenderableVertex;this.v4=new THREE.RenderableVertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this.faceMaterials=this.meshMaterials=null;this.overdraw=!1;this.uvs=[[]];this.z=null};
 THREE.RenderableObject=function(){this.z=this.object=null};THREE.RenderableParticle=function(){this.rotation=this.z=this.y=this.x=null;this.scale=new THREE.Vector2;this.materials=null};THREE.RenderableLine=function(){this.z=null;this.v1=new THREE.RenderableVertex;this.v2=new THREE.RenderableVertex;this.materials=null};

+ 3 - 1
build/custom/ThreeWebGL.js

@@ -284,4 +284,6 @@ g.colors;q=t.length;o=m.length;r=g.__vertexArray;E=g.__colorArray;u=g.__dirtyCol
 if(h.__dirtyVertices||h.__dirtyColors){g=h;j=f.DYNAMIC_DRAW;k=C=v=v=void 0;t=g.vertices;m=g.colors;q=t.length;o=m.length;r=g.__vertexArray;E=g.__colorArray;u=g.__dirtyColors;if(g.__dirtyVertices){for(v=0;v<q;v++)C=t[v].position,k=v*3,r[k]=C.x,r[k+1]=C.y,r[k+2]=C.z;f.bindBuffer(f.ARRAY_BUFFER,g.__webglVertexBuffer);f.bufferData(f.ARRAY_BUFFER,r,j)}if(u){for(v=0;v<o;v++)color=m[v],k=v*3,E[k]=color.r,E[k+1]=color.g,E[k+2]=color.b;f.bindBuffer(f.ARRAY_BUFFER,g.__webglColorBuffer);f.bufferData(f.ARRAY_BUFFER,
 E,j)}}h.__dirtyVertices=!1;h.__dirtyColors=!1}else if(g instanceof THREE.ParticleSystem)h=g.geometry,m=K(h),(h.__dirtyVertices||h.__dirtyColors||g.sortParticles||m)&&c(h,f.DYNAMIC_DRAW,g),h.__dirtyVertices=!1,h.__dirtyColors=!1,ya(h)};this.setFaceCulling=function(b,c){b?(!c||c=="ccw"?f.frontFace(f.CCW):f.frontFace(f.CW),b=="back"?f.cullFace(f.BACK):b=="front"?f.cullFace(f.FRONT):f.cullFace(f.FRONT_AND_BACK),f.enable(f.CULL_FACE)):f.disable(f.CULL_FACE)};this.supportsVertexTextures=function(){return Ya}};
 THREE.WebGLRenderTarget=function(b,c,d){this.width=b;this.height=c;d=d||{};this.wrapS=d.wrapS!==void 0?d.wrapS:THREE.ClampToEdgeWrapping;this.wrapT=d.wrapT!==void 0?d.wrapT:THREE.ClampToEdgeWrapping;this.magFilter=d.magFilter!==void 0?d.magFilter:THREE.LinearFilter;this.minFilter=d.minFilter!==void 0?d.minFilter:THREE.LinearMipMapLinearFilter;this.offset=new THREE.Vector2(0,0);this.repeat=new THREE.Vector2(1,1);this.format=d.format!==void 0?d.format:THREE.RGBAFormat;this.type=d.type!==void 0?d.type:
-THREE.UnsignedByteType;this.depthBuffer=d.depthBuffer!==void 0?d.depthBuffer:!0;this.stencilBuffer=d.stencilBuffer!==void 0?d.stencilBuffer:!0};THREE.WebGLRenderTargetCube=function(b,c,d){THREE.WebGLRenderTarget.call(this,b,c,d);this.activeCubeFace=0};THREE.WebGLRenderTargetCube.prototype=new THREE.WebGLRenderTarget;THREE.WebGLRenderTargetCube.prototype.constructor=THREE.WebGLRenderTargetCube;
+THREE.UnsignedByteType;this.depthBuffer=d.depthBuffer!==void 0?d.depthBuffer:!0;this.stencilBuffer=d.stencilBuffer!==void 0?d.stencilBuffer:!0};
+THREE.WebGLRenderTarget.prototype.clone=function(){var b=new THREE.WebGLRenderTarget(this.width,this.height);b.wrapS=this.wrapS;b.wrapT=this.wrapT;b.magFilter=this.magFilter;b.minFilter=this.minFilter;b.offset.copy(this.offset);b.repeat.copy(this.repeat);b.format=this.format;b.type=this.type;b.depthBuffer=this.depthBuffer;b.stencilBuffer=this.stencilBuffer;return b};THREE.WebGLRenderTargetCube=function(b,c,d){THREE.WebGLRenderTarget.call(this,b,c,d);this.activeCubeFace=0};
+THREE.WebGLRenderTargetCube.prototype=new THREE.WebGLRenderTarget;THREE.WebGLRenderTargetCube.prototype.constructor=THREE.WebGLRenderTargetCube;

+ 5 - 3
examples/js/postprocessing/BloomPass.js

@@ -51,17 +51,19 @@ THREE.BloomPass = function( strength, kernelSize, sigma, resolution ) {
 
 	} );
 
+	this.needsSwap = false;
+
 };
 
 THREE.BloomPass.prototype = {
 
-	render: function ( renderer, renderTarget, delta ) {
+	render: function ( renderer, writeBuffer, readBuffer, delta ) {
 
 		// Render quad with blured scene into texture (convolution pass 1)
 
 		THREE.EffectComposer.quad.materials[ 0 ] = this.materialConvolution;
 
-		this.convolutionUniforms[ "tDiffuse" ].texture = renderTarget;
+		this.convolutionUniforms[ "tDiffuse" ].texture = readBuffer;
 		this.convolutionUniforms[ "uImageIncrement" ].value = THREE.BloomPass.blurX;
 
 		renderer.render( THREE.EffectComposer.scene, THREE.EffectComposer.camera, this.renderTargetX, true );
@@ -79,7 +81,7 @@ THREE.BloomPass.prototype = {
 
 		this.screenUniforms[ "tDiffuse" ].texture = this.renderTargetY;
 
-		renderer.render( THREE.EffectComposer.scene, THREE.EffectComposer.camera, renderTarget, false );
+		renderer.render( THREE.EffectComposer.scene, THREE.EffectComposer.camera, readBuffer, false );
 
 	}
 

+ 5 - 4
examples/js/postprocessing/DotScreenPass.js

@@ -23,15 +23,16 @@ THREE.DotScreenPass = function( center, angle, scale ) {
 	} );
 
 	this.renderToScreen = false;
+	this.needsSwap = true;
 
 };
 
 THREE.DotScreenPass.prototype = {
 
-	render: function ( renderer, renderTarget, delta ) {
+	render: function ( renderer, writeBuffer, readBuffer, delta ) {
 
-		this.uniforms[ "tDiffuse" ].texture = renderTarget;
-		this.uniforms[ "tSize" ].value.set( renderTarget.width, renderTarget.height );
+		this.uniforms[ "tDiffuse" ].texture = readBuffer;
+		this.uniforms[ "tSize" ].value.set( readBuffer.width, readBuffer.height );
 
 		THREE.EffectComposer.quad.materials[ 0 ] = this.material;
 
@@ -41,7 +42,7 @@ THREE.DotScreenPass.prototype = {
 
 		} else {
 
-			renderer.render( THREE.EffectComposer.scene, THREE.EffectComposer.camera, renderTarget, false );
+			renderer.render( THREE.EffectComposer.scene, THREE.EffectComposer.camera, writeBuffer, false );
 
 		}
 

+ 34 - 8
examples/js/postprocessing/EffectComposer.js

@@ -5,21 +5,35 @@
 THREE.EffectComposer = function( renderer, renderTarget ) {
 
 	this.renderer = renderer;
-	this.renderTarget = renderTarget;
 
-	if ( this.renderTarget === undefined ) {
+	this.renderTarget1 = renderTarget;
+
+	if ( this.renderTarget1 === undefined ) {
 
 		this.renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBufer: false };
-		this.renderTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, this.renderTargetParameters );
+		this.renderTarget1 = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, this.renderTargetParameters );
 
 	}
 
+	this.renderTarget2 = this.renderTarget1.clone();
+
+	this.writeBuffer = this.renderTarget1;
+	this.readBuffer = this.renderTarget2;
+
 	this.passes = [];
 
 };
 
 THREE.EffectComposer.prototype = {
 
+	swapBuffers: function() {
+
+		var tmp = this.readBuffer;
+		this.readBuffer = this.writeBuffer;
+		this.writeBuffer = tmp;
+
+	},
+
 	addPass: function ( pass ) {
 
 		this.passes.push( pass );
@@ -32,20 +46,33 @@ THREE.EffectComposer.prototype = {
 
 		for ( i = 0; i < il; i ++ ) {
 
-			this.passes[ i ].render( this.renderer, this.renderTarget, delta );
+			this.passes[ i ].render( this.renderer, this.writeBuffer, this.readBuffer, delta );
+
+			if ( this.passes[ i ].needsSwap ) {
+
+				this.swapBuffers();
+
+			}
 
 		}
 
 	},
 
-	reset: function () {
+	reset: function ( renderTarget ) {
+
+		this.renderTarget1 = renderTarget;
 
-		if ( this.renderTargetParameters ) {
+		if ( this.renderTarget1 === undefined ) {
 
-			this.renderTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, this.renderTargetParameters );
+			this.renderTarget1 = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, this.renderTargetParameters );
 
 		}
 
+		this.renderTarget2 = this.renderTarget1.clone();
+
+		this.writeBuffer = this.renderTarget1;
+		this.readBuffer = this.renderTarget2;
+
 		THREE.EffectComposer.quad.scale.set( window.innerWidth, window.innerHeight, 1 );
 
 		THREE.EffectComposer.camera.left = window.innerWidth / - 2;
@@ -55,7 +82,6 @@ THREE.EffectComposer.prototype = {
 
 		THREE.EffectComposer.camera.updateProjectionMatrix();
 
-
 	}
 
 };

+ 4 - 3
examples/js/postprocessing/FilmPass.js

@@ -22,14 +22,15 @@ THREE.FilmPass = function( noiseIntensity, scanlinesIntensity, scanlinesCount, g
 	if ( scanlinesCount !== undefined ) this.uniforms.sCount.value = scanlinesCount;
 
 	this.renderToScreen = false;
+	this.needsSwap = true;
 
 };
 
 THREE.FilmPass.prototype = {
 
-	render: function ( renderer, renderTarget, delta ) {
+	render: function ( renderer, writeBuffer, readBuffer, delta ) {
 
-		this.uniforms[ "tDiffuse" ].texture = renderTarget;
+		this.uniforms[ "tDiffuse" ].texture = readBuffer;
 		this.uniforms[ "time" ].value += delta;
 
 		THREE.EffectComposer.quad.materials[ 0 ] = this.material;
@@ -40,7 +41,7 @@ THREE.FilmPass.prototype = {
 
 		} else {
 
-			renderer.render( THREE.EffectComposer.scene, THREE.EffectComposer.camera, renderTarget, false );
+			renderer.render( THREE.EffectComposer.scene, THREE.EffectComposer.camera, writeBuffer, false );
 
 		}
 

+ 3 - 2
examples/js/postprocessing/RenderPass.js

@@ -8,14 +8,15 @@ THREE.RenderPass = function ( scene, camera ) {
 	this.camera = camera;
 
 	this.clear = true;
+	this.needsSwap = false;
 
 };
 
 THREE.RenderPass.prototype = {
 
-	render: function ( renderer, renderTarget, delta ) {
+	render: function ( renderer, writeBuffer, readBuffer, delta ) {
 
-		renderer.render( this.scene, this.camera, renderTarget, this.clear );
+		renderer.render( this.scene, this.camera, readBuffer, this.clear );
 
 	}
 

+ 4 - 3
examples/js/postprocessing/ShaderPass.js

@@ -17,14 +17,15 @@ THREE.ShaderPass = function( shader, textureID ) {
 	} );
 
 	this.renderToScreen = false;
+	this.needsSwap = true;
 
 };
 
 THREE.ShaderPass.prototype = {
 
-	render: function ( renderer, renderTarget, delta ) {
+	render: function ( renderer, writeBuffer, readBuffer, delta ) {
 
-		this.uniforms[ this.textureID ].texture = renderTarget;
+		this.uniforms[ this.textureID ].texture = readBuffer;
 
 		THREE.EffectComposer.quad.materials[ 0 ] = this.material;
 
@@ -34,7 +35,7 @@ THREE.ShaderPass.prototype = {
 
 		} else {
 
-			renderer.render( THREE.EffectComposer.scene, THREE.EffectComposer.camera, renderTarget, false );
+			renderer.render( THREE.EffectComposer.scene, THREE.EffectComposer.camera, writeBuffer, false );
 
 		}
 

+ 4 - 2
examples/js/postprocessing/TexturePass.js

@@ -19,15 +19,17 @@ THREE.TexturePass = function( texture, opacity ) {
 
 	} );
 
+	this.needsSwap = false;
+
 };
 
 THREE.TexturePass.prototype = {
 
-	render: function ( renderer, renderTarget, delta ) {
+	render: function ( renderer, writeBuffer, readBuffer, delta ) {
 
 		THREE.EffectComposer.quad.materials[ 0 ] = this.material;
 
-		renderer.render( THREE.EffectComposer.scene, THREE.EffectComposer.camera, renderTarget );
+		renderer.render( THREE.EffectComposer.scene, THREE.EffectComposer.camera, readBuffer );
 
 	}
 

+ 5 - 10
examples/webgl_postprocessing.html

@@ -281,17 +281,12 @@
 
 				composerScene.reset();
 
-				composer1.reset();
-				composer2.reset();
-				composer3.reset();
-				composer4.reset();
+				composer1.reset( new THREE.WebGLRenderTarget( halfWidth, halfHeight, rtParameters ) );
+				composer2.reset( new THREE.WebGLRenderTarget( halfWidth, halfHeight, rtParameters ) );
+				composer3.reset( new THREE.WebGLRenderTarget( halfWidth, halfHeight, rtParameters ) );
+				composer4.reset( new THREE.WebGLRenderTarget( halfWidth, halfHeight, rtParameters ) );
 
-				composer1.renderTarget = new THREE.WebGLRenderTarget( halfWidth, halfHeight, rtParameters );
-				composer2.renderTarget = new THREE.WebGLRenderTarget( halfWidth, halfHeight, rtParameters );
-				composer3.renderTarget = new THREE.WebGLRenderTarget( halfWidth, halfHeight, rtParameters );
-				composer4.renderTarget = new THREE.WebGLRenderTarget( halfWidth, halfHeight, rtParameters );
-
-				renderScene.uniforms[ "tDiffuse" ].texture = composerScene.renderTarget;
+				renderScene.uniforms[ "tDiffuse" ].texture = composerScene.renderTarget2;
 
 				quadBG.scale.set( window.innerWidth, window.innerHeight, 1 );
 

+ 23 - 0
src/renderers/WebGLRenderTarget.js

@@ -25,3 +25,26 @@ THREE.WebGLRenderTarget = function ( width, height, options ) {
 	this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;
 
 };
+
+THREE.WebGLRenderTarget.prototype.clone = function() {
+
+	var tmp = new THREE.WebGLRenderTarget( this.width, this.height );
+
+	tmp.wrapS = this.wrapS;
+	tmp.wrapT = this.wrapT;
+
+	tmp.magFilter = this.magFilter;
+	tmp.minFilter = this.minFilter;
+
+	tmp.offset.copy( this.offset );
+	tmp.repeat.copy( this.repeat );
+
+	tmp.format = this.format;
+	tmp.type = this.type;
+
+	tmp.depthBuffer = this.depthBuffer;
+	tmp.stencilBuffer = this.stencilBuffer;
+
+	return tmp;
+
+};