Browse Source

WebGLDeferredRenderer: added support for environment mapping.

It's a hybrid solution, cubemap pixels are fetched and blended in color pass based on deferred normals from normal pass.
alteredq 12 years ago
parent
commit
b4a9081c27
2 changed files with 118 additions and 21 deletions
  1. 89 7
      examples/js/ShaderDeferred.js
  2. 29 14
      examples/js/renderers/WebGLDeferredRenderer.js

+ 89 - 7
examples/js/ShaderDeferred.js

@@ -21,7 +21,11 @@ THREE.ShaderDeferred = {
 				"specular" :  { type: "c", value: new THREE.Color( 0x111111 ) },
 				"shininess":  { type: "f", value: 30 },
 				"wrapAround": 		{ type: "f", value: 1 },
-				"additiveSpecular": { type: "f", value: 1 }
+				"additiveSpecular": { type: "f", value: 1 },
+
+				"samplerNormalDepth": { type: "t", value: null },
+				"viewWidth": 		{ type: "f", value: 800 },
+				"viewHeight": 		{ type: "f", value: 600 }
 			}
 
 		] ),
@@ -38,7 +42,25 @@ THREE.ShaderDeferred = {
 			THREE.ShaderChunk[ "color_pars_fragment" ],
 			THREE.ShaderChunk[ "map_pars_fragment" ],
 			THREE.ShaderChunk[ "lightmap_pars_fragment" ],
-			THREE.ShaderChunk[ "envmap_pars_fragment" ],
+
+			"#ifdef USE_ENVMAP",
+
+				"varying vec3 vWorldPosition;",
+
+				"uniform float reflectivity;",
+				"uniform samplerCube envMap;",
+				"uniform float flipEnvMap;",
+				"uniform int combine;",
+
+				"uniform bool useRefract;",
+				"uniform float refractionRatio;",
+
+				"uniform sampler2D samplerNormalDepth;",
+				"uniform float viewHeight;",
+				"uniform float viewWidth;",
+
+			"#endif",
+
 			THREE.ShaderChunk[ "fog_pars_fragment" ],
 			THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
 			THREE.ShaderChunk[ "specularmap_pars_fragment" ],
@@ -63,11 +85,61 @@ THREE.ShaderDeferred = {
 				THREE.ShaderChunk[ "specularmap_fragment" ],
 				THREE.ShaderChunk[ "lightmap_fragment" ],
 				THREE.ShaderChunk[ "color_fragment" ],
-				THREE.ShaderChunk[ "envmap_fragment" ],
-				THREE.ShaderChunk[ "shadowmap_fragment" ],
 
-				THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
+				"#ifdef USE_ENVMAP",
+
+					"vec2 texCoord = gl_FragCoord.xy / vec2( viewWidth, viewHeight );",
+					"vec4 normalDepth = texture2D( samplerNormalDepth, texCoord );",
+					"vec3 normal = normalDepth.xyz * 2.0 - 1.0;",
+
+					"vec3 reflectVec;",
+
+					"vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );",
+
+					"if ( useRefract ) {",
+
+						"reflectVec = refract( cameraToVertex, normal, refractionRatio );",
+
+					"} else { ",
+
+						"reflectVec = reflect( cameraToVertex, normal );",
+
+					"}",
+
+					"#ifdef DOUBLE_SIDED",
+
+						"float flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );",
+						"vec4 cubeColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );",
+
+					"#else",
+
+						"vec4 cubeColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );",
 
+					"#endif",
+
+					"#ifdef GAMMA_INPUT",
+
+						"cubeColor.xyz *= cubeColor.xyz;",
+
+					"#endif",
+
+					"if ( combine == 1 ) {",
+
+						"gl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularStrength * reflectivity );",
+
+					"} else if ( combine == 2 ) {",
+
+						"gl_FragColor.xyz += cubeColor.xyz * specularStrength * reflectivity;",
+
+					"} else {",
+
+						"gl_FragColor.xyz = mix( gl_FragColor.xyz, gl_FragColor.xyz * cubeColor.xyz, specularStrength * reflectivity );",
+
+					"}",
+
+				"#endif",
+
+				THREE.ShaderChunk[ "shadowmap_fragment" ],
 				THREE.ShaderChunk[ "fog_fragment" ],
 
 				//
@@ -120,12 +192,17 @@ THREE.ShaderDeferred = {
 
 			THREE.ShaderChunk[ "map_pars_vertex" ],
 			THREE.ShaderChunk[ "lightmap_pars_vertex" ],
-			THREE.ShaderChunk[ "envmap_pars_vertex" ],
 			THREE.ShaderChunk[ "color_pars_vertex" ],
 			THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
 			THREE.ShaderChunk[ "skinning_pars_vertex" ],
 			THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
 
+			"#ifdef USE_ENVMAP",
+
+				"varying vec3 vWorldPosition;",
+
+			"#endif",
+
 			"void main() {",
 
 				THREE.ShaderChunk[ "map_vertex" ],
@@ -139,9 +216,14 @@ THREE.ShaderDeferred = {
 				THREE.ShaderChunk[ "default_vertex" ],
 
 				THREE.ShaderChunk[ "worldpos_vertex" ],
-				THREE.ShaderChunk[ "envmap_vertex" ],
 				THREE.ShaderChunk[ "shadowmap_vertex" ],
 
+				"#ifdef USE_ENVMAP",
+
+					"vWorldPosition = worldPosition.xyz;",
+
+				"#endif",
+
 			"}"
 
 		].join("\n")

+ 29 - 14
examples/js/renderers/WebGLDeferredRenderer.js

@@ -63,7 +63,10 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 	//
 
 	var lightSceneFullscreen, lightSceneProxy;
-	var lightMaterials = [];
+
+	//
+
+	var resizableMaterials = [];
 
 	//
 
@@ -140,7 +143,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 		// 	morphs
 
 		var uniforms = THREE.UniformsUtils.clone( colorShader.uniforms );
-		var defines = { "USE_MAP": !! originalMaterial.map, "GAMMA_INPUT": true };
+		var defines = { "USE_MAP": !! originalMaterial.map, "USE_ENVMAP": !! originalMaterial.envMap, "GAMMA_INPUT": true };
 
 		var material = new THREE.ShaderMaterial( {
 
@@ -178,6 +181,23 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 		uniforms.map.value = originalMaterial.map;
 
+		if ( originalMaterial.envMap ) {
+
+			uniforms.envMap.value = originalMaterial.envMap;
+			uniforms.useRefract.value = originalMaterial.envMap.mapping instanceof THREE.CubeRefractionMapping;
+			uniforms.refractionRatio.value = originalMaterial.refractionRatio;
+			uniforms.combine.value = originalMaterial.combine;
+			uniforms.reflectivity.value = originalMaterial.reflectivity;
+			uniforms.flipEnvMap.value = ( originalMaterial.envMap instanceof THREE.WebGLRenderTargetCube ) ? 1 : -1;
+
+			uniforms.samplerNormalDepth.value = compNormalDepth.renderTarget2;
+			uniforms.viewWidth.value = scaledWidth;
+			uniforms.viewHeight.value = scaledHeight;
+
+			resizableMaterials.push( material );
+
+		}
+
 		material.vertexColors = originalMaterial.vertexColors;
 		material.morphTargets = originalMaterial.morphTargets;
 		material.morphNormals = originalMaterial.morphNormals;
@@ -352,7 +372,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 		// keep reference for size reset
 
-		lightMaterials.push( materialLight );
+		resizableMaterials.push( materialLight );
 
 		return meshLight;
 
@@ -399,7 +419,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 		// keep reference for size reset
 
-		lightMaterials.push( materialLight );
+		resizableMaterials.push( materialLight );
 
 		return meshLight;
 
@@ -432,7 +452,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 		// keep reference for size reset
 
-		lightMaterials.push( materialLight );
+		resizableMaterials.push( materialLight );
 
 		return meshLight;
 
@@ -547,20 +567,15 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 		compColor.renderTarget2.shareDepthFrom = compNormalDepth.renderTarget2;
 		compLight.renderTarget2.shareDepthFrom = compNormalDepth.renderTarget2;
 
-		for ( var i = 0, il = lightMaterials.length; i < il; i ++ ) {
+		for ( var i = 0, il = resizableMaterials.length; i < il; i ++ ) {
 
-			var uniforms = lightMaterials[ i ].uniforms;
+			var uniforms = resizableMaterials[ i ].uniforms;
 
 			uniforms[ "viewWidth" ].value = scaledWidth;
 			uniforms[ "viewHeight" ].value = scaledHeight;
 
-			uniforms[ 'samplerColor' ].value = compColor.renderTarget2;
-
-			if ( uniforms[ 'samplerNormalDepth' ] ) {
-
-				uniforms[ 'samplerNormalDepth' ].value = compNormalDepth.renderTarget2;
-
-			}
+			if ( uniforms[ 'samplerColor' ] ) uniforms[ 'samplerColor' ].value = compColor.renderTarget2;
+			if ( uniforms[ 'samplerNormalDepth' ] ) uniforms[ 'samplerNormalDepth' ].value = compNormalDepth.renderTarget2;
 
 		}