Bläddra i källkod

Merged with alteredq branch

Mr.doob 12 år sedan
förälder
incheckning
ec8dc3e3f3

+ 86 - 8
examples/js/ShaderDeferred.js

@@ -292,7 +292,15 @@ THREE.ShaderDeferred = {
 
 				// emissive color
 
-				"gl_FragColor.w = vec3_to_float( compressionScale * emissive * diffuseMapColor );",
+				"#ifdef USE_COLOR",
+
+					"gl_FragColor.w = vec3_to_float( compressionScale * emissive * diffuseMapColor * vColor );",
+
+				"#else",
+
+					"gl_FragColor.w = vec3_to_float( compressionScale * emissive * diffuseMapColor );",
+
+				"#endif",
 
 			"}"
 
@@ -443,10 +451,78 @@ THREE.ShaderDeferred = {
 			"uniform sampler2D samplerLight;",
 			"uniform float brightness;",
 
+			// tonemapping operators
+			// based on John Hable's HLSL snippets
+			// from http://filmicgames.com/archives/75
+
+			"#ifdef TONEMAP_UNCHARTED",
+
+				"const float A = 0.15;",
+				"const float B = 0.50;",
+				"const float C = 0.10;",
+				"const float D = 0.20;",
+				"const float E = 0.02;",
+				"const float F = 0.30;",
+				"const float W = 11.2;",
+
+				"vec3 Uncharted2Tonemap( vec3 x ) {",
+
+				   "return ( ( x * ( A * x + C * B ) + D * E ) / ( x * ( A * x + B ) + D * F ) ) - E / F;",
+
+				"}",
+
+			"#endif",
+
 			"void main() {",
 
-				"vec3 color = texture2D( samplerLight, texCoord ).xyz;",
-				"gl_FragColor = vec4( brightness * sqrt( color ), 1.0 );",
+				"vec3 inColor = texture2D( samplerLight, texCoord ).xyz;",
+				"inColor *= brightness;",
+
+				"vec3 outColor;",
+
+				"#if defined( TONEMAP_SIMPLE )",
+
+					"outColor = sqrt( inColor );",
+
+				"#elif defined( TONEMAP_LINEAR )",
+
+					// simple linear to gamma conversion
+
+					"outColor = pow( inColor, vec3( 1.0 / 2.2 ) );",
+
+				"#elif defined( TONEMAP_REINHARD )",
+
+					// Reinhard operator
+
+					"inColor = inColor / ( 1.0 + inColor );",
+					"outColor = pow( inColor, vec3( 1.0 / 2.2 ) );",
+
+				"#elif defined( TONEMAP_FILMIC )",
+
+					// filmic operator by Jim Hejl and Richard Burgess-Dawson
+
+					"vec3 x = max( vec3( 0.0 ), inColor - 0.004 );",
+					"outColor = ( x * ( 6.2 * x + 0.5 ) ) / ( x * ( 6.2 * x + 1.7 ) + 0.06 );",
+
+				"#elif defined( TONEMAP_UNCHARTED )",
+
+					// tonemapping operator from Uncharted 2 by John Hable
+
+					"float ExposureBias = 2.0;",
+					"vec3 curr = Uncharted2Tonemap( ExposureBias * inColor );",
+
+					"vec3 whiteScale = vec3( 1.0 ) / Uncharted2Tonemap( vec3( W ) );",
+					"vec3 color = curr * whiteScale;",
+
+					"outColor = pow( color, vec3( 1.0 / 2.2 ) );",
+
+				"#else",
+
+					"outColor = inColor;",
+
+				"#endif",
+
+				"gl_FragColor = vec4( outColor, 1.0 );",
 
 			"}"
 
@@ -919,13 +995,15 @@ THREE.ShaderDeferred = {
 				"vec3 nearestPointInside = vec3( lightPositionVS ) + ( lightRightVS * nearest2D.x + lightUpVS * nearest2D.y );",
 
 				"vec3 lightDir = normalize( nearestPointInside - vertexPositionVS.xyz );",
-				"float NdotL = dot( lightNormalVS, -lightDir );",
+				"float NdotL = max( dot( lightNormalVS, -lightDir ), 0.0 );",
+				"float NdotL2 = max( dot( normal, lightDir ), 0.0 );",
 
-				"if ( NdotL != 0.0 && sideOfPlane( vertexPositionVS.xyz, lightPositionVS, lightNormalVS ) ) {",
+				//"if ( NdotL2 * NdotL > 0.0 && sideOfPlane( vertexPositionVS.xyz, lightPositionVS, lightNormalVS ) ) {",
+				"if ( NdotL2 * NdotL > 0.0 ) {",
 
 					// diffuse
 
-					"vec3 diffuse = vec3( NdotL );",
+					"vec3 diffuse = vec3( sqrt( NdotL * NdotL2 ) );",
 
 					// specular
 
@@ -941,8 +1019,8 @@ THREE.ShaderDeferred = {
 						"vec3 dirSpec = E - vec3( lightPositionVS );",
 						"vec2 dirSpec2D = vec2( dot( dirSpec, lightRightVS ), dot( dirSpec, lightUpVS ) );",
 						"vec2 nearestSpec2D = vec2( clamp( dirSpec2D.x, -w, w ), clamp( dirSpec2D.y, -h, h ) );",
-						"float specFactor = 1.0 - clamp( length( nearestSpec2D - dirSpec2D ) * shininess, 0.0, 1.0 );",
-						"specular = specularColor * specFactor * specAngle;",
+						"float specFactor = 1.0 - clamp( length( nearestSpec2D - dirSpec2D ) * 0.05 * shininess, 0.0, 1.0 );",
+						"specular = specularColor * specFactor * specAngle * diffuse;",
 
 					"}",
 

+ 6 - 0
examples/js/postprocessing/EffectComposer.js

@@ -47,6 +47,12 @@ THREE.EffectComposer.prototype = {
 
 	},
 
+	insertPass: function ( pass, index ) {
+
+		this.passes.splice( index, 0, pass );
+
+	},
+
 	render: function ( delta ) {
 
 		this.writeBuffer = this.renderTarget1;

+ 62 - 12
examples/js/renderers/WebGLDeferredRenderer.js

@@ -15,6 +15,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 	var scaledHeight = Math.floor( currentScale * fullHeight );
 
 	var brightness = parameters.brightness !== undefined ? parameters.brightness : 1;
+	var tonemapping = parameters.tonemapping !== undefined ? parameters.tonemapping : THREE.SimpleOperator;
 	var antialias = parameters.antialias !== undefined ? parameters.antialias : false;
 
 	this.renderer = parameters.renderer;
@@ -205,7 +206,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 			uniforms.viewWidth.value = scaledWidth;
 			uniforms.viewHeight.value = scaledHeight;
 
-			resizableMaterials.push( material );
+			resizableMaterials.push( { "material": material } );
 
 		}
 
@@ -403,7 +404,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 		// keep reference for size reset
 
-		resizableMaterials.push( materialLight );
+		resizableMaterials.push( { "material": materialLight } );
 
 		// sync proxy uniforms to the original light
 
@@ -479,7 +480,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 		// keep reference for size reset
 
-		resizableMaterials.push( materialLight );
+		resizableMaterials.push( { "material": materialLight } );
 
 		// sync proxy uniforms to the original light
 
@@ -545,7 +546,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 		// keep reference for size reset
 
-		resizableMaterials.push( materialLight );
+		resizableMaterials.push( { "material": materialLight } );
 
 		// sync proxy uniforms to the original light
 
@@ -611,7 +612,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 		// keep reference for size reset
 
-		resizableMaterials.push( materialLight );
+		resizableMaterials.push( { "material": materialLight } );
 
 		// sync proxy uniforms to the original light
 
@@ -700,7 +701,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 		// keep reference for size reset
 
-		resizableMaterials.push( materialLight );
+		resizableMaterials.push( { "material": materialLight } );
 
 		// sync proxy uniforms to the original light
 
@@ -736,7 +737,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 		// keep reference for size reset
 
-		resizableMaterials.push( materialLight );
+		resizableMaterials.push( { "material": materialLight } );
 
 		return meshLight;
 
@@ -851,6 +852,25 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 	};
 
+	this.addEffect = function ( effect, normalDepthUniform, colorUniform ) {
+
+		if ( effect.material && effect.uniforms ) {
+
+			if ( normalDepthUniform ) effect.uniforms[ normalDepthUniform ].value = compNormalDepth.renderTarget2;
+			if ( colorUniform )    	  effect.uniforms[ colorUniform ].value = compColor.renderTarget2;
+
+			if ( normalDepthUniform || colorUniform ) {
+
+				resizableMaterials.push( { "material": effect.material, "normalDepth": normalDepthUniform, "color": colorUniform } );
+
+			}
+
+		}
+
+		compFinal.insertPass( effect, -1 );
+
+	};
+
 	this.setScale = function ( scale ) {
 
 		currentScale = scale;
@@ -868,13 +888,19 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 		for ( var i = 0, il = resizableMaterials.length; i < il; i ++ ) {
 
-			var uniforms = resizableMaterials[ i ].uniforms;
+			var materialEntry = resizableMaterials[ i ];
 
-			uniforms[ "viewWidth" ].value = scaledWidth;
-			uniforms[ "viewHeight" ].value = scaledHeight;
+			var material = materialEntry.material;
+			var uniforms = material.uniforms;
 
-			if ( uniforms[ 'samplerColor' ] ) uniforms[ 'samplerColor' ].value = compColor.renderTarget2;
-			if ( uniforms[ 'samplerNormalDepth' ] ) uniforms[ 'samplerNormalDepth' ].value = compNormalDepth.renderTarget2;
+			var colorLabel = materialEntry.color !== undefined ? materialEntry.color : 'samplerColor';
+			var normalDepthLabel = materialEntry.normalDepth !== undefined ? materialEntry.normalDepth : 'samplerNormalDepth';
+
+			if ( uniforms[ colorLabel ] ) uniforms[ colorLabel ].value = compColor.renderTarget2;
+			if ( uniforms[ normalDepthLabel ] ) uniforms[ normalDepthLabel ].value = compNormalDepth.renderTarget2;
+
+			if ( uniforms[ 'viewWidth' ] ) uniforms[ "viewWidth" ].value = scaledWidth;
+			if ( uniforms[ 'viewHeight' ] ) uniforms[ "viewHeight" ].value = scaledHeight;
 
 		}
 
@@ -1117,6 +1143,20 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 		compositePass.material.blending = THREE.NoBlending;
 		compositePass.clear = true;
 
+		var defines;
+
+		switch ( tonemapping ) {
+
+			case THREE.SimpleOperator:    defines = { "TONEMAP_SIMPLE": true };    break;
+			case THREE.LinearOperator:    defines = { "TONEMAP_LINEAR": true };    break;
+			case THREE.ReinhardOperator:  defines = { "TONEMAP_REINHARD": true };  break;
+			case THREE.FilmicOperator:    defines = { "TONEMAP_FILMIC": true };    break;
+			case THREE.UnchartedOperator: defines = { "TONEMAP_UNCHARTED": true }; break;
+
+		}
+
+		compositePass.material.defines = defines;
+
 		// FXAA
 
 		effectFXAA = new THREE.ShaderPass( THREE.FXAAShader );
@@ -1138,6 +1178,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 			effectFXAA.enabled = false;
 			compositePass.renderToScreen = true;
+
 		}
 
 	};
@@ -1147,3 +1188,12 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 	createRenderTargets();
 
 };
+
+// tonemapping operator types
+
+THREE.NoOperator = 0;
+THREE.SimpleOperator = 1;
+THREE.LinearOperator = 2;
+THREE.ReinhardOperator = 3;
+THREE.FilmicOperator = 4;
+THREE.UnchartedOperator = 5;

+ 22 - 7
examples/webgl_lights_deferred_arealights.html

@@ -54,11 +54,13 @@
 
 		<script src="js/shaders/CopyShader.js"></script>
 		<script src="js/shaders/FXAAShader.js"></script>
+		<script src="js/shaders/ConvolutionShader.js"></script>
 
 		<script src="js/postprocessing/EffectComposer.js"></script>
 		<script src="js/postprocessing/RenderPass.js"></script>
 		<script src="js/postprocessing/ShaderPass.js"></script>
 		<script src="js/postprocessing/MaskPass.js"></script>
+		<script src="js/postprocessing/BloomPass.js"></script>
 
 
 		<script>
@@ -105,7 +107,7 @@
 
 				// renderer
 
-				renderer = new THREE.WebGLDeferredRenderer( { width: WIDTH, height: HEIGHT, scale: SCALE, antialias: true } );
+				renderer = new THREE.WebGLDeferredRenderer( { width: WIDTH, height: HEIGHT, scale: SCALE, antialias: true, tonemapping: THREE.FilmicOperator, brightness: 2.5 } );
 
 				renderer.domElement.style.position = "absolute";
 				renderer.domElement.style.top = MARGIN + "px";
@@ -114,6 +116,11 @@
 				var container = document.getElementById( 'container' );
 				container.appendChild( renderer.domElement );
 
+				// effects
+
+				var bloomEffect = new THREE.BloomPass( 0.65 );
+				renderer.addEffect( bloomEffect );
+
 				// camera
 
 				camera = new THREE.PerspectiveCamera( VIEW_ANGLE, WIDTH / HEIGHT, NEAR, FAR );
@@ -156,7 +163,15 @@
 			function createAreaEmitter( light ) {
 
 				var geometry = new THREE.CubeGeometry( 1, 1, 1 );
-				var material = new THREE.MeshBasicMaterial( { color: light.color.getHex() } );
+				var material = new THREE.MeshBasicMaterial( { color: light.color.getHex(), vertexColors: THREE.FaceColors } );
+
+				var backColor = 0x222222;
+
+				geometry.faces[ 5 ].color.setHex( backColor );
+				geometry.faces[ 4 ].color.setHex( backColor );
+				geometry.faces[ 2 ].color.setHex( backColor );
+				geometry.faces[ 1 ].color.setHex( backColor );
+				geometry.faces[ 0 ].color.setHex( backColor );
 
 				var emitter = new THREE.Mesh( geometry, material );
 
@@ -183,7 +198,7 @@
 			function initLights() {
 
 				areaLight1 = new THREE.AreaLight( 0xffffff, 1 );
-				areaLight1.position.set( 0.0001, 10.0001, -19.5001 );
+				areaLight1.position.set( 0.0001, 10.0001, -18.5001 );
 				areaLight1.rotation.set( -0.74719, 0.0001, 0.0001 );
 				areaLight1.width = 10;
 				areaLight1.height = 1;
@@ -228,7 +243,7 @@
 				var loader = new THREE.BinaryLoader();
 				loader.load( "obj/box/box.js", function ( geometry, materials ) {
 
-					var material = new THREE.MeshPhongMaterial( { color: 0xffaa55, specular: 0x888888, shininess: 10 } );
+					var material = new THREE.MeshPhongMaterial( { color: 0xffaa55, specular: 0x888888, shininess: 200 } );
 					var object = new THREE.Mesh( geometry, material );
 					object.scale.multiplyScalar( 2 );
 					scene.add( object );
@@ -363,13 +378,13 @@
 
 				var time = Date.now();
 
-				areaLight1.position.x = Math.sin( Date.now() * 0.001 ) * 10;
+				areaLight1.position.x = Math.sin( Date.now() * 0.001 ) * 9;
 				areaLight1.position.y = Math.sin( Date.now() * 0.0013 ) * 5 + 5;
 
-				areaLight2.position.y = Math.sin( Date.now() * 0.0011 ) * 5 + 5;
+				areaLight2.position.y = Math.sin( Date.now() * 0.0011 ) * 3 + 5;
 				areaLight2.position.z = Math.sin( Date.now() * 0.00113 ) * 10;
 
-				areaLight3.position.y = Math.sin( Date.now() * 0.00111 ) * 5 + 5;
+				areaLight3.position.y = Math.sin( Date.now() * 0.00111 ) * 3 + 5;
 				areaLight3.position.z = Math.sin( Date.now() * 0.001113 ) * 10;
 
 				// render