Browse Source

Merge pull request #7 from WestLangley/dev-phong

Clean up phong shader
Ben Adams 10 years ago
parent
commit
f9a58ee50e

+ 100 - 21
src/renderers/shaders/ShaderChunk/common.glsl

@@ -4,57 +4,136 @@
 #define LOG2 1.442695
 #define EPSILON 1e-6
 
-float square( in float a ) { return a*a; }
-vec2  square( in vec2 a )  { return vec2( a.x*a.x, a.y*a.y ); }
-vec3  square( in vec3 a )  { return vec3( a.x*a.x, a.y*a.y, a.z*a.z ); }
-vec4  square( in vec4 a )  { return vec4( a.x*a.x, a.y*a.y, a.z*a.z, a.w*a.w ); }
+float square( in float a ) { return a * a; }
+vec2  square( in vec2 a )  { return vec2( a.x * a.x, a.y * a.y ); }
+vec3  square( in vec3 a )  { return vec3( a.x * a.x, a.y * a.y, a.z * a.z ); }
+vec4  square( in vec4 a )  { return vec4( a.x * a.x, a.y * a.y, a.z * a.z, a.w * a.w ); }
+
 float saturate( in float a ) { return clamp( a, 0.0, 1.0 ); }
 vec2  saturate( in vec2 a )  { return clamp( a, 0.0, 1.0 ); }
 vec3  saturate( in vec3 a )  { return clamp( a, 0.0, 1.0 ); }
 vec4  saturate( in vec4 a )  { return clamp( a, 0.0, 1.0 ); }
+
 float average( in float a ) { return a; }
-float average( in vec2 a )  { return ( a.x + a.y) * 0.5; }
-float average( in vec3 a )  { return ( a.x + a.y + a.z) / 3.0; }
-float average( in vec4 a )  { return ( a.x + a.y + a.z + a.w) * 0.25; }
+float average( in vec2 a )  { return ( a.x + a.y ) * 0.5; }
+float average( in vec3 a )  { return ( a.x + a.y + a.z ) / 3.0; }
+float average( in vec4 a )  { return ( a.x + a.y + a.z + a.w ) * 0.25; }
+
 float whiteCompliment( in float a ) { return saturate( 1.0 - a ); }
-vec2  whiteCompliment( in vec2 a )  { return saturate( vec2(1.0) - a ); }
-vec3  whiteCompliment( in vec3 a )  { return saturate( vec3(1.0) - a ); }
-vec4  whiteCompliment( in vec4 a )  { return saturate( vec4(1.0) - a ); }
+vec2  whiteCompliment( in vec2 a )  { return saturate( vec2( 1.0 ) - a ); }
+vec3  whiteCompliment( in vec3 a )  { return saturate( vec3( 1.0 ) - a ); }
+vec4  whiteCompliment( in vec4 a )  { return saturate( vec4( 1.0 ) - a ); }
+
 vec3 transformDirection( in vec3 normal, in mat4 matrix ) {
+
 	return normalize( ( matrix * vec4( normal, 0.0 ) ).xyz );
+
 }
+
 // http://en.wikibooks.org/wiki/GLSL_Programming/Applying_Matrix_Transformations
 vec3 inverseTransformDirection( in vec3 normal, in mat4 matrix ) {
+
 	return normalize( ( vec4( normal, 0.0 ) * matrix ).xyz );
+
 }
-vec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal) {
+
+vec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {
+
 	float distance = dot( planeNormal, point-pointOnPlane );
+
 	return point - distance * planeNormal;
+
 }
+
 float sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {
+
 	return sign( dot( point - pointOnPlane, planeNormal ) );
+
 }
+
 vec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {
+
 	return pointOnLine + lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) );
+
 }
+
 float calcLightAttenuation( float lightDistance, float cutoffDistance, float decayExponent ) {
+
 	if ( decayExponent > 0.0 ) {
+
 	  return pow( saturate( 1.0 - lightDistance / cutoffDistance ), decayExponent );
+
 	}
+
 	return 1.0;
+
+}
+
+vec3 F_Schlick( in vec3 specularColor, in float dotLH ) {
+
+	return specularColor + ( 1.0 - specularColor ) * pow( 1.0 - dotLH, 5.0 );
+
+}
+
+float G_BlinnPhong_Implicit( /* in float dotNL, in float dotNV */ ) {
+
+	// geometry term is (n⋅l)(n⋅v) / 4(n⋅l)(n⋅v)
+
+	return 0.25;
+
+}
+
+float D_BlinnPhong( in float shininess, in float dotNH ) {
+
+	// factor of 1/PI in distribution term omitted
+
+	return ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );
+
+}
+
+vec3 BRDF_BlinnPhong( in vec3 specularColor, in float shininess, in vec3 normal, in vec3 lightDir, in vec3 viewDir ) {
+
+	vec3 halfDir = normalize( lightDir + viewDir );
+
+	//float dotNL = saturate( dot( normal, lightDir ) );
+	//float dotNV = saturate( dot( normal, viewDir ) );
+	float dotNH = saturate( dot( normal, halfDir ) );
+	float dotLH = saturate( dot( lightDir, halfDir ) );
+
+	vec3 F = F_Schlick( specularColor, dotLH );
+
+	float G = G_BlinnPhong_Implicit( /* dotNL, dotNV */ );
+
+	float D = D_BlinnPhong( shininess, dotNH );
+
+	return F * G * D;
+
 }
 
 vec3 inputToLinear( in vec3 a ) {
-#ifdef GAMMA_INPUT
-	return pow( a, vec3( float( GAMMA_FACTOR ) ) );
-#else
-	return a;
-#endif
+
+	#ifdef GAMMA_INPUT
+
+		return pow( a, vec3( float( GAMMA_FACTOR ) ) );
+
+	#else
+
+		return a;
+
+	#endif
+
 }
+
 vec3 linearToOutput( in vec3 a ) {
-#ifdef GAMMA_OUTPUT
-	return pow( a, vec3( 1.0 / float( GAMMA_FACTOR ) ) );
-#else
-	return a;
-#endif
+
+	#ifdef GAMMA_OUTPUT
+
+		return pow( a, vec3( 1.0 / float( GAMMA_FACTOR ) ) );
+
+	#else
+
+		return a;
+
+	#endif
+
 }

+ 44 - 122
src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl

@@ -16,8 +16,6 @@
 
 #endif
 
-vec3 viewPosition = normalize( vViewPosition );
-
 #ifdef USE_NORMALMAP
 
 	normal = perturbNormal2Arb( -vViewPosition, normal );
@@ -28,6 +26,8 @@ vec3 viewPosition = normalize( vViewPosition );
 
 #endif
 
+vec3 viewDir = normalize( vViewPosition );
+
 vec3 totalDiffuseLight = vec3( 0.0 );
 vec3 totalSpecularLight = vec3( 0.0 );
 
@@ -35,42 +35,29 @@ vec3 totalSpecularLight = vec3( 0.0 );
 
 	for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {
 
-		vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );
+		vec3 lightColor = pointLightColor[ i ];
+
+		vec3 lightPosition = pointLightPosition[ i ];
+		vec4 lPosition = viewMatrix * vec4( lightPosition, 1.0 );
 		vec3 lVector = lPosition.xyz + vViewPosition.xyz;
+		vec3 lightDir = normalize( lVector );
 
-		float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[ i ] );
+		// attenuation
 
-		lVector = normalize( lVector );
+		float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[ i ] );
 
 		// diffuse
 
-		float dotProduct = dot( normal, lVector );
-
-		#ifdef WRAP_AROUND
-
-			float pointDiffuseWeightFull = max( dotProduct, 0.0 );
-			float pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );
-
-			vec3 pointDiffuseWeight = mix( vec3( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );
-
-		#else
-
-			float pointDiffuseWeight = max( dotProduct, 0.0 );
-
-		#endif
+		vec3 cosineTerm = calcCosineTerm( normal, lightDir );
 
-		totalDiffuseLight += pointLightColor[ i ] * pointDiffuseWeight * attenuation;
+		totalDiffuseLight += lightColor * attenuation * cosineTerm;
 
-				// specular
+		// specular
 
-		vec3 pointHalfVector = normalize( lVector + viewPosition );
-		float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );
-		float pointSpecularWeight = specularStrength * max( pow( pointDotNormalHalf, shininess ), 0.0 );
+		vec3 brdf = BRDF_BlinnPhong( specular, shininess, normal, lightDir, viewDir );
 
-		float specularNormalization = ( shininess + 2.0 ) / 8.0;
+		totalSpecularLight += brdf * specularStrength * lightColor * attenuation * cosineTerm;
 
-		vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, pointHalfVector ), 0.0 ), 5.0 );
-		totalSpecularLight += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * attenuation * specularNormalization;
 
 	}
 
@@ -80,48 +67,36 @@ vec3 totalSpecularLight = vec3( 0.0 );
 
 	for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {
 
-		vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );
-		vec3 lVector = lPosition.xyz + vViewPosition.xyz;
-
-		float attenuation = calcLightAttenuation( length( lVector ), spotLightDistance[ i ], spotLightDecay[ i ] );
+		vec3 lightColor = spotLightColor[ i ];
 
-		lVector = normalize( lVector );
+		vec3 lightPosition = spotLightPosition[ i ];
+		vec4 lPosition = viewMatrix * vec4( lightPosition, 1.0 );
+		vec3 lVector = lPosition.xyz + vViewPosition.xyz;
+		vec3 lightDir = normalize( lVector );
 
-		float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );
+		float spotEffect = dot( spotLightDirection[ i ], normalize( lightPosition - vWorldPosition ) );
 
 		if ( spotEffect > spotLightAngleCos[ i ] ) {
 
-			spotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 );
-
-			// diffuse
-
-			float dotProduct = dot( normal, lVector );
-
-			#ifdef WRAP_AROUND
+			spotEffect = saturate( pow( saturate( spotEffect ), spotLightExponent[ i ] ) );
 
-				float spotDiffuseWeightFull = max( dotProduct, 0.0 );
-				float spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );
+			// attenuation
 
-				vec3 spotDiffuseWeight = mix( vec3( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );
+			float attenuation = calcLightAttenuation( length( lVector ), spotLightDistance[ i ], spotLightDecay[ i ] );
 
-			#else
+			attenuation *= spotEffect;
 
-				float spotDiffuseWeight = max( dotProduct, 0.0 );
+			// diffuse
 
-			#endif
+			vec3 cosineTerm = calcCosineTerm( normal, lightDir );
 
-			totalDiffuseLight += spotLightColor[ i ] * spotDiffuseWeight * attenuation * spotEffect;
+			totalDiffuseLight += lightColor * attenuation * cosineTerm;
 
 			// specular
 
-			vec3 spotHalfVector = normalize( lVector + viewPosition );
-			float spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );
-			float spotSpecularWeight = specularStrength * max( pow( spotDotNormalHalf, shininess ), 0.0 );
-
-			float specularNormalization = ( shininess + 2.0 ) / 8.0;
+			vec3 brdf = BRDF_BlinnPhong( specular, shininess, normal, lightDir, viewDir );
 
-			vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, spotHalfVector ), 0.0 ), 5.0 );
-			totalSpecularLight += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * attenuation * specularNormalization * spotEffect;
+			totalSpecularLight += brdf * specularStrength * lightColor * attenuation * cosineTerm;
 
 		}
 
@@ -133,59 +108,21 @@ vec3 totalSpecularLight = vec3( 0.0 );
 
 	for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {
 
-		vec3 dirVector = transformDirection( directionalLightDirection[ i ], viewMatrix );
+		vec3 lightColor = directionalLightColor[ i ];
 
-		// diffuse
-
-		float dotProduct = dot( normal, dirVector );
-
-		#ifdef WRAP_AROUND
-
-			float dirDiffuseWeightFull = max( dotProduct, 0.0 );
-			float dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );
-
-			vec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );
-
-		#else
+		vec3 lightDir = transformDirection( directionalLightDirection[ i ], viewMatrix );
 
-			float dirDiffuseWeight = max( dotProduct, 0.0 );
+		// diffuse
 
-		#endif
+		vec3 cosineTerm = calcCosineTerm( normal, lightDir );
 
-		totalDiffuseLight += directionalLightColor[ i ] * dirDiffuseWeight;
+		totalDiffuseLight += lightColor * cosineTerm;
 
 		// specular
 
-		vec3 dirHalfVector = normalize( dirVector + viewPosition );
-		float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );
-		float dirSpecularWeight = specularStrength * max( pow( dirDotNormalHalf, shininess ), 0.0 );
-
-		/*
-		// fresnel term from skin shader
-		const float F0 = 0.128;
-
-		float base = 1.0 - dot( viewPosition, dirHalfVector );
-		float exponential = pow( base, 5.0 );
-
-		float fresnel = exponential + F0 * ( 1.0 - exponential );
-		*/
-
-		/*
-		// fresnel term from fresnel shader
-		const float mFresnelBias = 0.08;
-		const float mFresnelScale = 0.3;
-		const float mFresnelPower = 5.0;
-
-		float fresnel = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( -viewPosition ), normal ), mFresnelPower );
-		*/
-
-		float specularNormalization = ( shininess + 2.0 ) / 8.0;
-
-		// 		dirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization * fresnel;
-
-		vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( dirVector, dirHalfVector ), 0.0 ), 5.0 );
-		totalSpecularLight += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;
+		vec3 brdf = BRDF_BlinnPhong( specular, shininess, normal, lightDir, viewDir );
 
+		totalSpecularLight += brdf * specularStrength * lightColor * cosineTerm;
 
 	}
 
@@ -195,38 +132,23 @@ vec3 totalSpecularLight = vec3( 0.0 );
 
 	for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {
 
-		vec3 lVector = transformDirection( hemisphereLightDirection[ i ], viewMatrix );
+		vec3 lightDir = transformDirection( hemisphereLightDirection[ i ], viewMatrix );
 
 		// diffuse
 
-		float dotProduct = dot( normal, lVector );
-		float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;
-
-		vec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );
-
-		totalDiffuseLight += hemiColor;
-
-		// specular (sky light)
+		float dotProduct = dot( normal, lightDir );
 
-		vec3 hemiHalfVectorSky = normalize( lVector + viewPosition );
-		float hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;
-		float hemiSpecularWeightSky = specularStrength * max( pow( max( hemiDotNormalHalfSky, 0.0 ), shininess ), 0.0 );
-
-		// specular (ground light)
+		float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;
 
-		vec3 lVectorGround = -lVector;
+		vec3 lightColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );
 
-		vec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );
-		float hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;
-		float hemiSpecularWeightGround = specularStrength * max( pow( max( hemiDotNormalHalfGround, 0.0 ), shininess ), 0.0 );
+		totalDiffuseLight += lightColor;
 
-		float dotProductGround = dot( normal, lVectorGround );
+		// specular (sky term only)
 
-		float specularNormalization = ( shininess + 2.0 ) / 8.0;
+		vec3 brdf = BRDF_BlinnPhong( specular, shininess, normal, lightDir, viewDir );
 
-		vec3 schlickSky = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, hemiHalfVectorSky ), 0.0 ), 5.0 );
-		vec3 schlickGround = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 0.0 ), 5.0 );
-		totalSpecularLight += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );
+		totalSpecularLight += brdf * specularStrength * lightColor * max( dotProduct, 0.0 );
 
 	}
 

+ 18 - 0
src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl

@@ -56,3 +56,21 @@ varying vec3 vViewPosition;
 	varying vec3 vNormal;
 
 #endif
+
+vec3 calcCosineTerm( in vec3 normal, in vec3 lightDir ) {
+
+	float dotProduct = dot( normal, lightDir );
+
+	vec3 cosineTerm = vec3( saturate( dotProduct ) );
+
+	#ifdef WRAP_AROUND
+
+		vec3 cosineTermHalf = vec3( saturate( 0.5 * dotProduct + 0.5 ) );
+
+		cosineTerm = mix( cosineTerm, cosineTermHalf, wrapRGB );
+
+	#endif
+
+	return cosineTerm;
+
+}