Преглед изворни кода

Support backgrounds (cube, texture, color) via passes (#9158)

* start of background pass test.

* get clear pass and texture pass working well with each other.

* cube texture pass works.  render pass now obeys Pass.clear.  CubeTexturePass supports opacity.  TexturePass doesn't write to the depth buffer.

* get rid of temp matrix.

* add to files.js.  better title.

* remove unused scene parameter from CubeTexturePass.
Ben Houston (Clara.io) пре 9 година
родитељ
комит
309723cd09

+ 1 - 0
examples/files.js

@@ -190,6 +190,7 @@ var files = {
 		"webgl_points_sprites",
 		"webgl_postprocessing",
 		"webgl_postprocessing_advanced",
+		"webgl_postprocessing_backgrounds",
 		"webgl_postprocessing_crossfade",
 		"webgl_postprocessing_dof",
 		"webgl_postprocessing_dof2",

+ 57 - 0
examples/js/postprocessing/CubeTexturePass.js

@@ -0,0 +1,57 @@
+/**
+ * @author bhouston / http://clara.io/
+ */
+
+THREE.CubeTexturePass = function ( camera, envMap, opacity ) {
+
+	THREE.Pass.call( this );
+
+	this.camera = camera;
+
+	this.needsSwap = false;
+
+	this.cubeShader = THREE.ShaderLib[ 'cube' ];
+	this.cubeMesh = new THREE.Mesh(
+		new THREE.BoxBufferGeometry( 10, 10, 10 ),
+		new THREE.ShaderMaterial( {
+			uniforms: this.cubeShader.uniforms,
+			vertexShader: this.cubeShader.vertexShader,
+			fragmentShader: this.cubeShader.fragmentShader,
+			depthTest: false,
+			depthWrite: false,
+			side: THREE.BackSide
+		} )
+	);
+
+	this.envMap = envMap;
+	this.opacity = ( opacity !== undefined ) ? opacity : 1.0;
+
+	this.cubeScene = new THREE.Scene();
+	this.cubeCamera = new THREE.PerspectiveCamera();
+	this.cubeScene.add( this.cubeMesh );
+
+};
+
+THREE.CubeTexturePass.prototype = Object.assign( Object.create( THREE.Pass.prototype ), {
+
+	constructor: THREE.CubeTexturePass,
+
+	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+
+		var oldAutoClear = renderer.autoClear;
+		renderer.autoClear = false;
+
+		this.cubeCamera.projectionMatrix.copy( this.camera.projectionMatrix );
+		this.cubeCamera.quaternion.setFromRotationMatrix( this.camera.matrixWorld );
+
+		this.cubeMesh.material.uniforms[ "tCube" ].value = this.envMap;
+		this.cubeMesh.material.uniforms[ "opacity" ].value = this.opacity;
+		this.cubeMesh.material.transparent = ( this.opacity < 1.0 );
+
+		renderer.render( this.cubeScene, this.cubeCamera, this.renderToScreen ? null : readBuffer, this.clear );
+
+		renderer.autoClear = oldAutoClear;
+
+	}
+
+} );

+ 4 - 1
examples/js/postprocessing/RenderPass.js

@@ -25,6 +25,9 @@ THREE.RenderPass.prototype = Object.assign( Object.create( THREE.Pass.prototype
 
 	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
 
+		var oldAutoClear = renderer.autoClear;
+		renderer.autoClear = false;
+
 		this.scene.overrideMaterial = this.overrideMaterial;
 
 		var oldClearColor, oldClearAlpha;
@@ -47,7 +50,7 @@ THREE.RenderPass.prototype = Object.assign( Object.create( THREE.Pass.prototype
 		}
 
 		this.scene.overrideMaterial = null;
-
+		renderer.autoClear = oldAutoClear;
 	}
 
 } );

+ 16 - 6
examples/js/postprocessing/TexturePass.js

@@ -2,7 +2,7 @@
  * @author alteredq / http://alteredqualia.com/
  */
 
-THREE.TexturePass = function ( texture, opacity ) {
+THREE.TexturePass = function ( map, opacity ) {
 
 	THREE.Pass.call( this );
 
@@ -11,16 +11,18 @@ THREE.TexturePass = function ( texture, opacity ) {
 
 	var shader = THREE.CopyShader;
 
-	this.uniforms = THREE.UniformsUtils.clone( shader.uniforms );
+	this.map = map;
+	this.opacity = ( opacity !== undefined ) ? opacity : 1.0;
 
-	this.uniforms[ "opacity" ].value = ( opacity !== undefined ) ? opacity : 1.0;
-	this.uniforms[ "tDiffuse" ].value = texture;
+	this.uniforms = THREE.UniformsUtils.clone( shader.uniforms );
 
 	this.material = new THREE.ShaderMaterial( {
 
 		uniforms: this.uniforms,
 		vertexShader: shader.vertexShader,
-		fragmentShader: shader.fragmentShader
+		fragmentShader: shader.fragmentShader,
+		depthTest: false,
+		depthWrite: false
 
 	} );
 
@@ -40,10 +42,18 @@ THREE.TexturePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
 
 	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
 
+		var oldAutoClear = renderer.autoClear;
+		renderer.autoClear = false;
+
 		this.quad.material = this.material;
 
-		renderer.render( this.scene, this.camera, readBuffer, this.clear );
+		this.uniforms[ "opacity" ].value = this.opacity;
+		this.uniforms[ "tDiffuse" ].value = this.map;
+		this.material.transparent = ( this.opacity < 1.0 );
+
+		renderer.render( this.scene, this.camera, this.renderToScreen ? null : readBuffer, this.clear );
 
+		renderer.autoClear = oldAutoClear;
 	}
 
 } );

+ 284 - 0
examples/webgl_postprocessing_backgrounds.html

@@ -0,0 +1,284 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - postprocessing backgrounds</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				margin: 0px;
+				background-color: #000;
+				overflow: hidden;
+				font-family:Monospace;
+				font-size:13px;
+				margin: 0px;
+				text-align:center;
+				overflow: hidden;
+			}
+
+			a { color: #88f; }
+
+			#info {
+				color: #fff;
+				position: absolute;
+				top: 10px;
+				width: 100%;
+				text-align: center;
+				display:block;
+			}
+		</style>
+	</head>
+	<body>
+		<div id="info">
+			<a href="http://threejs.org" target="_blank">three.js</a> - Backgrounds: ClearPass, TexturePass and CubeTexturePass by <a href="https://clara.io" target="_blank">Ben Houston</a></div>
+
+		<div id="container"></div>
+
+		<script src="../build/three.js"></script>
+		<script src="js/libs/stats.min.js"></script>
+		<script src="js/libs/dat.gui.min.js"></script>
+
+		<script src="js/shaders/CopyShader.js"></script>
+
+		<script src="js/postprocessing/EffectComposer.js"></script>
+		<script src="js/postprocessing/ClearPass.js"></script>
+		<script src="js/postprocessing/RenderPass.js"></script>
+		<script src="js/postprocessing/TexturePass.js"></script>
+		<script src="js/postprocessing/CubeTexturePass.js"></script>
+		<script src="js/postprocessing/ShaderPass.js"></script>
+
+		<script src="js/controls/OrbitControls.js"></script>
+
+		<script>
+
+			var scene, renderer, composer;
+			var clearPass, texturePass, renderPass;
+			var cameraP, cubeTexturePassP;
+			//var cameraO, cubeTexturePassO;
+			var gui, stats, texture;
+
+			var params = {
+
+				clearPass: true,
+				clearColor: 'white',
+				clearAlpha: 1.0,
+
+				texturePass: true,
+				texturePassOpacity: 1.0,
+
+				cubeTexturePass: true,
+				cubeTexturePassOpacity: 1.0,
+
+				renderPass: true,
+
+				//autoRotate: true,
+
+				//camera: 'perspective'
+		
+			};
+
+			init();
+			animate();
+
+			clearGui();
+
+			function clearGui() {
+
+				if ( gui ) gui.destroy();
+
+				gui = new dat.GUI();
+
+				gui.add( params, "clearPass" );
+				gui.add( params, "clearColor", [ 'black', 'white', 'blue', 'green', 'red' ] );		
+				gui.add( params, "clearAlpha", 0, 1 );		
+
+				gui.add( params, "texturePass" );
+				gui.add( params, "texturePassOpacity", 0, 1 );		
+
+				gui.add( params, "cubeTexturePass" );
+				gui.add( params, "cubeTexturePassOpacity", 0, 1 );		
+	
+				gui.add( params, "renderPass" );
+			
+				//gui.add( params, "autoRotate" );
+
+				//gui.add( params, 'camera', [ 'perspective', 'orthographic' ] );
+			
+				gui.open();
+
+			}
+
+			function init() {
+
+				container = document.getElementById( "container" );
+
+				var width = window.innerWidth || 1;
+				var height = window.innerHeight || 1;
+				var aspect = width / height;
+				var devicePixelRatio = window.devicePixelRatio || 1;
+
+				renderer = new THREE.WebGLRenderer( { antialias: false } );
+				renderer.setPixelRatio( devicePixelRatio );
+				renderer.setSize( width, height );
+				document.body.appendChild( renderer.domElement );
+
+				stats = new Stats();
+				container.appendChild( stats.dom );
+
+				//
+
+				cameraP = new THREE.PerspectiveCamera( 65, aspect, 3, 10 );
+				cameraP.position.z = 7;
+
+			//	cameraO = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 3, 10 );
+			//	cameraO.position.z = 7;
+
+			//	var fov = THREE.Math.degToRad( cameraP.fov );
+			//	var hyperfocus = ( cameraP.near + cameraP.far ) / 2;
+			//	var _height = 2 * Math.tan( fov / 2 ) * hyperfocus;
+			//	cameraO.zoom = height / _height;
+
+				scene = new THREE.Scene();
+
+				group = new THREE.Object3D();
+				scene.add( group );
+
+				var light = new THREE.PointLight( 0xddffdd, 1.0 );
+				light.position.z = 70;
+				light.position.y = -70;
+				light.position.x = -70;
+				scene.add( light );
+
+				var light2 = new THREE.PointLight( 0xffdddd, 1.0 );
+				light2.position.z = 70;
+				light2.position.x = -70;
+				light2.position.y = 70;
+				scene.add( light2 );
+
+				var light3 = new THREE.PointLight( 0xddddff, 1.0 );
+				light3.position.z = 70;
+				light3.position.x = 70;
+				light3.position.y = -70;
+				scene.add( light3 );
+
+				var geometry = new THREE.SphereBufferGeometry( 1, 48, 24 );
+
+				var material = new THREE.MeshStandardMaterial();
+				material.roughness = 0.5 * Math.random() + 0.25;
+				material.metalness = 0;
+				material.color.setHSL( Math.random(), 1.0, 0.3 );
+
+				var mesh = new THREE.Mesh( geometry, material );
+				group.add( mesh );
+
+				// postprocessing
+
+				var genCubeUrls = function( prefix, postfix ) {
+					return [
+						prefix + 'px' + postfix, prefix + 'nx' + postfix,
+						prefix + 'py' + postfix, prefix + 'ny' + postfix,
+						prefix + 'pz' + postfix, prefix + 'nz' + postfix
+					];
+				};
+
+				composer = new THREE.EffectComposer( renderer );
+
+				clearPass = new THREE.ClearPass( params.clearColor, params.clearAlpha );
+				composer.addPass( clearPass );
+
+				texturePass = new THREE.TexturePass();
+				composer.addPass( texturePass );
+
+				var textureLoader = new THREE.TextureLoader();
+				textureLoader.load( "../examples/textures/hardwood2_diffuse.jpg", function( map ) {
+					texturePass.map = map;
+				});
+
+				cubeTexturePassP = new THREE.CubeTexturePass( cameraP );
+				composer.addPass( cubeTexturePassP );
+
+				var ldrUrls = genCubeUrls( "./textures/cube/pisa/", ".png" );
+				new THREE.CubeTextureLoader().load( ldrUrls, function ( ldrCubeMap ) {
+					cubeTexturePassP.envMap = ldrCubeMap;
+					console.log( "loaded envmap");
+				});
+
+				renderPass = new THREE.RenderPass( scene, cameraP );
+				renderPass.clear = false;
+				composer.addPass( renderPass );
+		
+				copyPass = new THREE.ShaderPass( THREE.CopyShader );
+				copyPass.renderToScreen = true;
+				composer.addPass( copyPass );
+		
+				var controls = new THREE.OrbitControls( cameraP, renderer.domElement );
+				controls.target.set( 0, 0, 0 );
+				controls.update();
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+			function onWindowResize() {
+
+				var width = window.innerWidth;
+				var height = window.innerHeight;
+				var aspect = width / height;
+
+				cameraP.aspect = aspect;
+				cameraP.updateProjectionMatrix();
+
+				/*cameraO.left = - height * aspect;
+				cameraO.right = height * aspect;
+				cameraO.top = height;
+				cameraO.bottom = - height;
+				cameraO.updateProjectionMatrix();*/
+
+				renderer.setSize( width, height );
+
+				var pixelRatio = renderer.getPixelRatio();
+				var newWidth  = Math.floor( width / pixelRatio ) || 1;
+				var newHeight = Math.floor( height / pixelRatio ) || 1;
+				composer.setSize( newWidth, newHeight );
+
+			}
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				stats.begin();
+
+				cameraP.updateMatrixWorld( true );
+			
+				var newColor = clearPass.clearColor;
+				switch( params.clearColor ) {
+					case 'blue': newColor = 0x0000ff; break;
+					case 'red': newColor = 0xff0000; break;
+					case 'green': newColor = 0x00ff00; break;
+					case 'white': newColor = 0xffffff; break;
+					case 'black': newColor = 0x000000; break;
+				}
+	
+				clearPass.enabled = params.clearPass;
+				clearPass.clearColor = newColor;
+				clearPass.clearAlpha = params.clearAlpha;
+
+				texturePass.enabled = params.texturePass;
+				texturePass.opacity = params.texturePassOpacity;
+
+				cubeTexturePassP.enabled = params.cubeTexturePass;
+				cubeTexturePassP.opacity = params.cubeTexturePassOpacity;
+
+				renderPass.enabled = params.renderPass;
+
+				composer.render();
+
+				stats.end();
+
+			}
+
+		</script>
+		<div>
+	</body>
+</html>

+ 2 - 1
src/renderers/shaders/ShaderLib.js

@@ -172,7 +172,8 @@ THREE.ShaderLib = {
 
 		uniforms: {
 			"tCube": { value: null },
-			"tFlip": { value: - 1 }
+			"tFlip": { value: - 1 },
+			"opacity": { value: 1.0 }
 		},
 
 		vertexShader: THREE.ShaderChunk[ 'cube_vert' ],

+ 2 - 0
src/renderers/shaders/ShaderLib/cube_frag.glsl

@@ -1,5 +1,6 @@
 uniform samplerCube tCube;
 uniform float tFlip;
+uniform float opacity;
 
 varying vec3 vWorldPosition;
 
@@ -12,6 +13,7 @@ void main() {
 	#include <clipping_planes_fragment>
 
 	gl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );
+	gl_FragColor.a *= opacity;
 
 	#include <logdepthbuf_fragment>