Browse Source

Refactored normal map shader to use standard lights.

Updated SceneLoader to use this new shader for normal mapped materials.

Added handling of ambient light to scene parser.

For the moment kept also old normal map shader, still need to convert examples.
alteredq 14 years ago
parent
commit
457b7a6000
2 changed files with 271 additions and 50 deletions
  1. 259 2
      src/extras/ShaderUtils.js
  2. 12 48
      src/extras/io/SceneLoader.js

+ 259 - 2
src/extras/ShaderUtils.js

@@ -157,8 +157,8 @@ THREE.ShaderUtils = {
 
 
 				"void main() {",
 				"void main() {",
 
 
-					"vec3 diffuseTex = vec3( 1.0, 1.0, 1.0 );",
-					"vec3 aoTex = vec3( 1.0, 1.0, 1.0 );",
+					"vec3 diffuseTex = vec3( 1.0 );",
+					"vec3 aoTex = vec3( 1.0 );",
 					"vec3 specularTex = vec3( 1.0, 1.0, 1.0 );",
 					"vec3 specularTex = vec3( 1.0, 1.0, 1.0 );",
 
 
 					"vec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;",
 					"vec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;",
@@ -295,6 +295,263 @@ THREE.ShaderUtils = {
 
 
 		},
 		},
 
 
+		'normal2' : {
+
+			uniforms: THREE.UniformsUtils.merge( [
+
+				THREE.UniformsLib[ "lights" ],
+
+				{
+
+				"enableAO"		: { type: "i", value: 0 },
+				"enableDiffuse"	: { type: "i", value: 0 },
+				"enableSpecular": { type: "i", value: 0 },
+
+				"tDiffuse"	: { type: "t", value: 0, texture: null },
+				"tNormal"	: { type: "t", value: 2, texture: null },
+				"tSpecular"	: { type: "t", value: 3, texture: null },
+				"tAO"		: { type: "t", value: 4, texture: null },
+
+				"uNormalScale": { type: "f", value: 1.0 },
+
+				"tDisplacement": { type: "t", value: 5, texture: null },
+				"uDisplacementBias": { type: "f", value: -0.5 },
+				"uDisplacementScale": { type: "f", value: 2.5 },
+
+				"uDiffuseColor": { type: "c", value: new THREE.Color( 0xeeeeee ) },
+				"uSpecularColor": { type: "c", value: new THREE.Color( 0x111111 ) },
+				"uAmbientColor": { type: "c", value: new THREE.Color( 0x050505 ) },
+				"uShininess": { type: "f", value: 30 },
+				"uOpacity": { type: "f", value: 1 }
+
+				}
+
+			] ),
+
+			fragmentShader: [
+
+				"uniform vec3 uAmbientColor;",
+				"uniform vec3 uDiffuseColor;",
+				"uniform vec3 uSpecularColor;",
+				"uniform float uShininess;",
+				"uniform float uOpacity;",
+
+				"uniform bool enableDiffuse;",
+				"uniform bool enableSpecular;",
+				"uniform bool enableAO;",
+
+				"uniform sampler2D tDiffuse;",
+				"uniform sampler2D tNormal;",
+				"uniform sampler2D tSpecular;",
+				"uniform sampler2D tAO;",
+
+				"uniform float uNormalScale;",
+
+				"varying vec3 vTangent;",
+				"varying vec3 vBinormal;",
+				"varying vec3 vNormal;",
+				"varying vec2 vUv;",
+
+				"uniform vec3 ambientLightColor;",
+
+				"#if MAX_DIR_LIGHTS > 0",
+					"uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];",
+					"uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];",
+				"#endif",
+
+				"#if MAX_POINT_LIGHTS > 0",
+					"uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
+					"varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
+				"#endif",
+
+				"varying vec3 vViewPosition;",
+
+				"void main() {",
+
+					"gl_FragColor = vec4( 1.0 );",
+
+					"vec4 mColor = vec4( uDiffuseColor, uOpacity );",
+					"vec4 mSpecular = vec4( uSpecularColor, uOpacity );",
+
+					"vec3 specularTex = vec3( 1.0 );",
+
+					"vec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;",
+					"normalTex.xy *= uNormalScale;",
+					"normalTex = normalize( normalTex );",
+
+					"if( enableDiffuse )",
+						"gl_FragColor = gl_FragColor * texture2D( tDiffuse, vUv );",
+
+					"if( enableAO )",
+						"gl_FragColor = gl_FragColor * texture2D( tAO, vUv );",
+
+					"if( enableSpecular )",
+						"specularTex = texture2D( tSpecular, vUv ).xyz;",
+
+					"mat3 tsb = mat3( vTangent, vBinormal, vNormal );",
+					"vec3 finalNormal = tsb * normalTex;",
+
+					"vec3 normal = normalize( finalNormal );",
+					"vec3 viewPosition = normalize( vViewPosition );",
+
+					// point lights
+
+					"#if MAX_POINT_LIGHTS > 0",
+
+						"vec4 pointTotal  = vec4( 0.0 );",
+
+						"for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
+
+							"vec3 pointVector = normalize( vPointLight[ 0 ].xyz );",
+							"vec3 pointHalfVector = normalize( vPointLight[ 0 ].xyz + vViewPosition );",
+							"float pointDistance = vPointLight[ i ].w;",
+
+							"float pointDotNormalHalf = dot( normal, pointHalfVector );",
+							"float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );",
+
+							"float pointSpecularWeight = 0.0;",
+							"if ( pointDotNormalHalf >= 0.0 )",
+								"pointSpecularWeight = specularTex.r * pow( pointDotNormalHalf, uShininess );",
+
+							"pointTotal  += pointDistance * vec4( pointLightColor[ 0 ], 1.0 ) * ( mColor * pointDiffuseWeight + mSpecular * pointSpecularWeight * pointDiffuseWeight );",
+
+						"}",
+
+					"#endif",
+
+					// directional lights
+
+					"#if MAX_DIR_LIGHTS > 0",
+
+						"vec4 dirTotal  = vec4( 0.0 );",
+
+						"for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
+
+							"vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ 0 ], 0.0 );",
+
+							"vec3 dirVector = normalize( lDirection.xyz );",
+							"vec3 dirHalfVector = normalize( lDirection.xyz + vViewPosition );",
+
+							"float dirDotNormalHalf = dot( normal, dirHalfVector );",
+							"float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );",
+
+							"float dirSpecularWeight = 0.0;",
+							"if ( dirDotNormalHalf >= 0.0 )",
+								"dirSpecularWeight = specularTex.r * pow( dirDotNormalHalf, uShininess );",
+
+							"dirTotal  += vec4( directionalLightColor[ 0 ], 1.0 ) * ( mColor * dirDiffuseWeight + mSpecular * dirSpecularWeight * dirDiffuseWeight );",
+
+						"}",
+
+					"#endif",
+
+					// all lights contribution summation
+
+					"vec4 totalLight = vec4( ambientLightColor * uAmbientColor, uOpacity );",
+
+					"#if MAX_DIR_LIGHTS > 0",
+						"totalLight += dirTotal;",
+					"#endif",
+
+					"#if MAX_POINT_LIGHTS > 0",
+						"totalLight += pointTotal;",
+					"#endif",
+
+					"gl_FragColor = gl_FragColor * totalLight;",
+
+				"}"
+
+			].join("\n"),
+
+			vertexShader: [
+
+				"attribute vec4 tangent;",
+
+				"#ifdef VERTEX_TEXTURES",
+
+					"uniform sampler2D tDisplacement;",
+					"uniform float uDisplacementScale;",
+					"uniform float uDisplacementBias;",
+
+				"#endif",
+
+				"varying vec3 vTangent;",
+				"varying vec3 vBinormal;",
+				"varying vec3 vNormal;",
+				"varying vec2 vUv;",
+
+				"#if MAX_POINT_LIGHTS > 0",
+
+					"uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
+					"uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
+
+					"varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
+
+				"#endif",
+
+				"varying vec3 vViewPosition;",
+
+				"void main() {",
+
+					"vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
+					"vViewPosition = cameraPosition - mPosition.xyz;",
+
+					"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
+					"vNormal = normalize( normalMatrix * normal );",
+
+					// tangent and binormal vectors
+
+					"vTangent = normalize( normalMatrix * tangent.xyz );",
+
+					"vBinormal = cross( vNormal, vTangent ) * tangent.w;",
+					"vBinormal = normalize( vBinormal );",
+
+					"vUv = uv;",
+
+					// point lights
+
+					"#if MAX_POINT_LIGHTS > 0",
+
+						"for( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {",
+
+							"vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
+
+							"vec3 lVector = lPosition.xyz - mvPosition.xyz;",
+
+							"float lDistance = 1.0;",
+
+							"if ( pointLightDistance[ i ] > 0.0 )",
+								"lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
+
+							"lVector = normalize( lVector );",
+
+							"vPointLight[ i ] = vec4( lVector, lDistance );",
+
+						"}",
+
+					"#endif",
+
+					// displacement mapping
+
+					"#ifdef VERTEX_TEXTURES",
+
+						"vec3 dv = texture2D( tDisplacement, uv ).xyz;",
+						"float df = uDisplacementScale * dv.x + uDisplacementBias;",
+						"vec4 displacedPosition = vec4( vNormal.xyz * df, 0.0 ) + mvPosition;",
+						"gl_Position = projectionMatrix * displacedPosition;",
+
+					"#else",
+
+						"gl_Position = projectionMatrix * mvPosition;",
+
+					"#endif",
+
+				"}"
+
+			].join("\n")
+
+		},
+		
 		/* -------------------------------------------------------------------------
 		/* -------------------------------------------------------------------------
 		//	Cube map shader
 		//	Cube map shader
 		 ------------------------------------------------------------------------- */
 		 ------------------------------------------------------------------------- */

+ 12 - 48
src/extras/io/SceneLoader.js

@@ -404,6 +404,10 @@ THREE.SceneLoader.prototype = {
 					light = new THREE.PointLight( hex, intensity, d );
 					light = new THREE.PointLight( hex, intensity, d );
 					light.position.set( p[0], p[1], p[2] );
 					light.position.set( p[0], p[1], p[2] );
 
 
+				} else if ( l.type == "ambient" ) {
+
+					light = new THREE.AmbientLight( hex );
+
 				}
 				}
 
 
 				result.scene.addLight( light );
 				result.scene.addLight( light );
@@ -686,7 +690,7 @@ THREE.SceneLoader.prototype = {
 
 
 				if ( m.parameters.normalMap ) {
 				if ( m.parameters.normalMap ) {
 
 
-					var shader = THREE.ShaderUtils.lib[ "normal" ];
+					var shader = THREE.ShaderUtils.lib[ "normal2" ];
 					var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
 					var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
 
 
 					var diffuse = m.parameters.color;
 					var diffuse = m.parameters.color;
@@ -694,32 +698,6 @@ THREE.SceneLoader.prototype = {
 					var ambient = m.parameters.ambient;
 					var ambient = m.parameters.ambient;
 					var shininess = m.parameters.shininess;
 					var shininess = m.parameters.shininess;
 
 
-					var pointLight;
-					var directionalLight;
-					var ambientLight;
-
-					// take first of each light type (normal map shader supports just one light of each type)
-
-					for ( var i = 0; i < result.scene.lights.length; i ++ ) {
-
-						light = result.scene.lights[ i ];
-
-						if( ! ambientLight && ( light instanceof THREE.AmbientLight ) ) {
-
-							ambientLight = light;
-
-						} else if( ! pointLight && ( light instanceof THREE.PointLight ) ) {
-
-							pointLight = light;
-
-						} else if( ! directionalLight && ( light instanceof THREE.DirectionalLight ) ) {
-
-							directionalLight = light;
-
-						}
-
-					}
-
 					uniforms[ "tNormal" ].texture = result.textures[ m.parameters.normalMap ];
 					uniforms[ "tNormal" ].texture = result.textures[ m.parameters.normalMap ];
 
 
 					if ( m.parameters.normalMapFactor ) {
 					if ( m.parameters.normalMapFactor ) {
@@ -738,33 +716,19 @@ THREE.SceneLoader.prototype = {
 					uniforms[ "enableAO" ].value = false;
 					uniforms[ "enableAO" ].value = false;
 					uniforms[ "enableSpecular" ].value = false;
 					uniforms[ "enableSpecular" ].value = false;
 
 
-					if ( pointLight ) {
-
-						uniforms[ "uPointLightPos" ].value = pointLight.position;
-						uniforms[ "uPointLightColor" ].value = pointLight.color;
-
-					}
-
-					if ( directionalLight ) {
-
-						uniforms[ "uDirLightPos" ].value = directionalLight.position;
-						uniforms[ "uDirLightColor" ].value = directionalLight.color;
-
-					}
-
-					if ( ambientLight ) {
-
-						uniforms[ "uAmbientLightColor" ].value = ambientLight.color;
-
-					}
-
 					uniforms[ "uDiffuseColor" ].value.setHex( diffuse );
 					uniforms[ "uDiffuseColor" ].value.setHex( diffuse );
 					uniforms[ "uSpecularColor" ].value.setHex( specular );
 					uniforms[ "uSpecularColor" ].value.setHex( specular );
 					uniforms[ "uAmbientColor" ].value.setHex( ambient );
 					uniforms[ "uAmbientColor" ].value.setHex( ambient );
 
 
 					uniforms[ "uShininess" ].value = shininess;
 					uniforms[ "uShininess" ].value = shininess;
 
 
-					var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms };
+					if ( m.parameters.opacity ) {
+
+						uniforms[ "uOpacity" ].value = m.parameters.opacity;
+
+					}
+
+					var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true };
 
 
 					material = new THREE.MeshShaderMaterial( parameters );
 					material = new THREE.MeshShaderMaterial( parameters );