Browse Source

add energy perserving rgb/monochrome modes. add BRDF_OrenNayar.

Ben Houston 9 years ago
parent
commit
b101729331

+ 28 - 2
src/renderers/shaders/ShaderChunk/common.glsl

@@ -8,6 +8,16 @@
 #define saturate(a) clamp( a, 0.0, 1.0 )
 #define whiteCompliment(a) ( 1.0 - saturate( a ) )
 
+float luminance( const in vec3 color ) {
+    const vec3 W = vec3(0.2125, 0.7154, 0.0721);
+    return dot( color, W );
+}
+
+float average( const in vec3 color ) {
+    const vec3 W = vec3(0.3333, 0.3333, 0.3333);
+    return dot( color, W );
+}
+
 vec3 transformDirection( in vec3 normal, in mat4 matrix ) {
 
 	return normalize( ( matrix * vec4( normal, 0.0 ) ).xyz );
@@ -94,11 +104,27 @@ struct ReflectedLight {
 
 void BRDF_Lambert( const in IncidentLight incidentLight, const in vec3 normal, const in vec3 diffuseColor, inout ReflectedLight reflectedLight ) {
 
-	reflectedLight.diffuse += incidentLight.color * diffuseColor * ( saturate( dot( normal, incidentLight.direction ) ) );
+	reflectedLight.diffuse += incidentLight.color * diffuseColor * ( saturate( dot( normal, incidentLight.direction ) ) * RECIPROCAL_PI );
+
+}
+
+void BRDF_OrenNayar( const in IncidentLight incidentLight, const in vec3 normal, const in vec3 viewDir, const in vec3 diffuse, const in float roughness, inout ReflectedLight reflectedLight ) {
+
+	vec3 halfDir = normalize( incidentLight.direction + viewDir );
+	float dotVH = saturate( dot( viewDir, halfDir ) );
+	float dotNV = saturate( dot( normal, viewDir ) );
+	float dotNL = saturate( dot( normal, incidentLight.direction ) );
+
+	float m2 = roughness * roughness;
+	float termA = 1.0 - 0.5 * m2 / (m2 + 0.33);
+	float Cosri = 2.0 * dotVH - 1.0 - dotNV * dotNL;
+	float termB = 0.45 * m2 / (m2 + 0.09) * Cosri * ( Cosri >= 0.0 ? min( 1.0, dotNL / dotNV ) : dotNL );
+
+	reflectedLight.diffuse = incidentLight.color * diffuse * ( RECIPROCAL_PI * ( dotNL * termA + termB ) );
 
-	// the above should be scaled by '' * RECIPROCAL_PI'
 }
 
+
 vec3 F_Schlick( const in vec3 F0, const in float dotLH ) {
 
 	// Original approximation by Christophe Schlick '94

+ 6 - 13
src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl

@@ -1,19 +1,12 @@
-vLightFront = vec3( 0.0 );
-
-#ifdef DOUBLE_SIDED
-
-	vLightBack = vec3( 0.0 );
-
-#endif
-
 vec3 normal = normalize( transformedNormal );
+vec3 backNormal = -normal;
+
 vec3 diffuse = vec3( 1.0 );
 
 IncidentLight incidentLight;
 ReflectedLight frontReflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ) );
 ReflectedLight backReflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ) );
 
-vec3 backNormal = -normal;
 
 #if MAX_POINT_LIGHTS > 0
 
@@ -57,7 +50,7 @@ vec3 backNormal = -normal;
 
 		getDirIncidentLight( directionalLights[ i ], incidentLight );
 
-		vLightFront += BRDF_Lambert( incidentLight, normal, diffuse, frontReflectedLight );
+		BRDF_Lambert( incidentLight, normal, diffuse, frontReflectedLight );
 
 		#ifdef DOUBLE_SIDED
 
@@ -89,10 +82,10 @@ vec3 backNormal = -normal;
 
 #endif
 
-vLightFront += ambientLightColor + frontReflectedLight.diffuse;
+vLightFront = ambientLightColor + frontReflectedLight.diffuse;
 
 #ifdef DOUBLE_SIDED
 
-	vLightBack += ambientLightColor + backReflectedLight.diffuse;
+	vLightBack = ambientLightColor + backReflectedLight.diffuse;
 
-#endif
+#endif

+ 20 - 6
src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl

@@ -1,17 +1,28 @@
 vec3 viewDir = normalize( vViewPosition );
 
-ReflectedLight directReflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ) );
-ReflectedLight indirectReflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ) );
-
 vec3 diffuse = diffuseColor.rgb;
 
 #ifdef METAL
 
-	diffuse *= specular;
+	diffuse = vec3( 0.0 );
+
+#endif
+
+#define ENERGY_PRESERVING_MONOCHROME
+
+#ifdef ENERGY_PRESERVING_RGB
+
+	diffuse *= whiteCompliment( specular );
+
+#elif defined( ENERGY_PRESERVING_MONOCHROME )
+
+	diffuse *= whiteCompliment( luminance( specular ) );
 
 #endif
 
 IncidentLight incidentLight;
+ReflectedLight directReflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ) );
+ReflectedLight indirectReflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ) );
 
 #if MAX_POINT_LIGHTS > 0
 
@@ -20,10 +31,10 @@ IncidentLight incidentLight;
 		getPointIncidentLight( pointLights[ i ], -vViewPosition, incidentLight );
 
 		BRDF_Lambert( incidentLight, normal, diffuse, directReflectedLight );
+		//BRDF_OrenNayar( incidentLight, normal, viewDir, diffuse, 0.5, directReflectedLight );
 
 		BRDF_BlinnPhong( incidentLight, normal, viewDir, specular, shininess, directReflectedLight );
 
-
 	}
 
 #endif
@@ -32,9 +43,10 @@ IncidentLight incidentLight;
 
 	for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {
 
-		getSpotLightDirect( spotLights[ i ], -vViewPosition, incidentLight );
+		getSpotIncidentLight( spotLights[ i ], -vViewPosition, incidentLight );
 
 		BRDF_Lambert( incidentLight, normal, diffuse, directReflectedLight );
+		//BRDF_OrenNayar( incidentLight, normal, viewDir, diffuse, 0.5, directReflectedLight );
 
 		BRDF_BlinnPhong( incidentLight, normal, viewDir, specular, shininess, directReflectedLight );
 
@@ -49,6 +61,7 @@ IncidentLight incidentLight;
 		getDirIncidentLight( directionalLights[ i ], incidentLight );
 
 		BRDF_Lambert( incidentLight, normal, diffuse, directReflectedLight );
+		//BRDF_OrenNayar( incidentLight, normal, viewDir, diffuse, 0.5, directReflectedLight );
 
 		BRDF_BlinnPhong( incidentLight, normal, viewDir, specular, shininess, directReflectedLight );
 
@@ -63,6 +76,7 @@ IncidentLight incidentLight;
 		getHemisphereIncidentLight( hemisphereLights[ i ], normal, incidentLight );
 
 		BRDF_Lambert( incidentLight, normal, diffuse, indirectReflectedLight );
+		//BRDF_OrenNayar( incidentLight, normal, viewDir, diffuse, 0.5, indirectReflectedLight );
 
 	}