Browse Source

Modify indirect terms

Panagiotis Christopoulos Charitos 7 years ago
parent
commit
822b11e589
4 changed files with 41 additions and 35 deletions
  1. 1 4
      programs/LightShading.ankiprog
  2. 8 23
      programs/Reflections.ankiprog
  3. 27 4
      shaders/LightFunctions.glsl
  4. 5 4
      shaders/Pack.glsl

+ 1 - 4
programs/LightShading.ankiprog

@@ -69,7 +69,7 @@ const float SUBSURFACE_MIN = 0.05;
 	vec3 frag2Light = light.posRadius.xyz - worldPos; \
 	vec3 l = normalize(frag2Light); \
 	float nol = max(0.0, dot(normal, l)); \
-	vec3 specC = computeSpecularColorBrdf(viewDir, l, normal, specCol, light.specularColorRadius.rgb, a2, nol); \
+	vec3 specC = computeSpecularColorBrdf(viewDir, l, normal, specCol, light.specularColorRadius.rgb, roughness, nol); \
 	vec3 diffC = computeDiffuseColor(diffCol, light.diffuseColorShadowmapId.rgb); \
 	float att = computeAttenuationFactor(light.posRadius.w, frag2Light); \
 	float lambert = nol;
@@ -119,9 +119,6 @@ void main()
 	// Ambient and emissive color
 	vec3 outC = diffCol * emission;
 
-	// Don't allow zero a2 because we may end up with division with zero
-	float a2 = computeRoughnesSquared(roughness);
-
 	// Point lights
 	vec3 viewDir = normalize(u_cameraPos - worldPos);
 	count = u_lightIndices[idxOffset++];

+ 8 - 23
programs/Reflections.ankiprog

@@ -208,17 +208,6 @@ void readReflectionsAndIrradianceFromProbes(
 	}
 }
 
-vec3 computeSpecIndirectFactor(vec3 worldPos, vec3 normal, float roughness, vec3 specColor)
-{
-	vec3 viewDir = normalize(u_cameraPos - worldPos);
-	float ndotv = dot(normal, viewDir);
-
-	vec2 envBRDF = texture(u_integrationLut, vec2(roughness, ndotv)).xy;
-	vec3 specIndirectTerm = specColor * envBRDF.x + envBRDF.y;
-
-	return specIndirectTerm;
-}
-
 void main()
 {
 	// Compute a global invocation ID that takes the checkerboard pattern into account
@@ -251,8 +240,11 @@ void main()
 	vec3 worldPos = worldPos4.xyz / worldPos4.w;
 
 	// Compute how much reflections we need
-	float a2 = computeRoughnesSquared(gbuffer.roughness);
-	vec3 specIndirectTerm = computeSpecIndirectFactor(worldPos, gbuffer.normal, a2, gbuffer.specular);
+	vec3 specIndirectTerm;
+	vec3 diffIndirectTerm;
+	vec3 viewDir = normalize(u_cameraPos - worldPos);
+	computeSpecAndDiffuseIndirectFactors(viewDir, gbuffer, u_integrationLut, specIndirectTerm, diffIndirectTerm);
+	
 	bool runSslr = 
 		max(max(specIndirectTerm.x, specIndirectTerm.y), specIndirectTerm.z) > 0.05;
 
@@ -301,19 +293,12 @@ void main()
 			idxOffset, worldPos, gbuffer.normal, gbuffer.roughness, probeCol, indirectCol);
 	}
 
-	vec3 outColor = indirectCol * gbuffer.diffuse;
-
 	// Combine the SSR and probe reflections and write the result
-	{
-		vec3 finalRefl = mix(probeCol, sslrCol, sslrFactor);
-		finalRefl = specIndirectTerm * finalRefl;
-
-		outColor += finalRefl;
-	}
+	vec3 finalRefl = mix(probeCol, sslrCol, sslrFactor);
 
-	// Apply SSAO
+	// Compute the final color
 	float ssao = textureLod(u_ssaoTex, uv, 0.0).r;
-	outColor *= ssao;
+	vec3 outColor = (indirectCol * diffIndirectTerm + finalRefl * specIndirectTerm) * ssao;
 
 	// Store the color for the resolve
 	s_pixels[gl_LocalInvocationID.y][gl_LocalInvocationID.x] = outColor;

+ 27 - 4
shaders/LightFunctions.glsl

@@ -9,6 +9,7 @@
 #define ANKI_SHADERS_LIGHT_FUNCTIONS_GLSL
 
 #include "shaders/Functions.glsl"
+#include "shaders/Pack.glsl"
 
 const float LIGHT_FRUSTUM_NEAR_PLANE = 0.1 / 4.0;
 const uint SHADOW_SAMPLE_COUNT = 16;
@@ -163,11 +164,33 @@ vec3 computeCubemapVecCheap(in vec3 r, in float R2, in vec3 f)
 	return r;
 }
 
-float computeRoughnesSquared(float roughness)
+vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness)
 {
-	float a2 = roughness * 0.95 + 0.05;
-	a2 *= a2 * a2;
-	return a2;
+	// Make sure that we won't end up with a zero in pow()
+	float a = 1.0 - cosTheta;
+	a = max(a, EPSILON);
+
+	return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(a, 5.0);
+}
+
+// Compute the factors that will be used to calculat the final specular and diffuse indirect terms
+void computeSpecAndDiffuseIndirectFactors(
+	vec3 viewDir, GbufferInfo gbuffer, sampler2D integrationLut, out vec3 specIndirectTerm, out vec3 diffIndirectTerm)
+{
+	float ndotv = dot(gbuffer.normal, viewDir);
+
+	// Reflectance
+	vec3 F0 = mix(gbuffer.specular, gbuffer.diffuse, gbuffer.metallic);
+	vec3 F = fresnelSchlickRoughness(max(ndotv, 0.0), F0, gbuffer.roughness);
+
+	vec2 envBRDF = texture(integrationLut, vec2(gbuffer.roughness, ndotv)).xy;
+	specIndirectTerm = F * envBRDF.x + envBRDF.y;
+
+	vec3 kS = F;
+	vec3 kD = 1.0 - kS;
+	kD *= 1.0 - gbuffer.metallic;
+
+	diffIndirectTerm = kD * gbuffer.diffuse;
 }
 
 #endif

+ 5 - 4
shaders/Pack.glsl

@@ -165,6 +165,11 @@ void readRoughnessSpecularFromGBuffer(in sampler2D rt1, in vec2 uv, out float ro
 	vec4 comp = textureLod(rt1, uv, 0.0);
 	specular = comp.xyz;
 	roughness = comp.w;
+
+	// Fix roughness
+	const float MIN_ROUGHNESS = 0.5;
+	roughness = roughness * (1.0 - MIN_ROUGHNESS) + MIN_ROUGHNESS;
+	roughness *= roughness;
 }
 
 // Read from the G buffer
@@ -181,10 +186,6 @@ void readGBuffer(in sampler2D rt0, in sampler2D rt1, in sampler2D rt2, in vec2 u
 	comp = textureLod(rt2, uv, lod);
 	g.normal = signedOctDecode(comp.xyw);
 	g.emission = comp.z * MAX_EMISSION;
-
-	// Fix values
-	g.specular = mix(g.specular, g.diffuse, g.metallic);
-	g.diffuse *= (1.0 - g.metallic);
 }
 
 #endif