فهرست منبع

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 سال پیش
والد
کامیت
b4a9081c27
2فایلهای تغییر یافته به همراه118 افزوده شده و 21 حذف شده
  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;
 
 		}