In my Direct Light Physically Based Renderer, when I set the roughness too low (ie. 0.0 or close) the specular reflection doesn't show, not even at high resolutions and at perfect angle with the camera / light position.
I'm using Cook-Torrance's BRDF with Schlick Smith GGX Geometry Function, Shlick Fresnel Function and Trowbridge-Reitz GGX Normal Distribution Function.
I suspect the whole reason behind this is because when the roughness is 0.0, the result of the Normal Distribution Function is also 0.0 and, consequently, the specular part will also be null.
// Trowbridge-Reitz GGX Normal Distribution Function
float NormalDistributionFunction(vec3 N, vec3 H, float roughness) {
float a = roughness * roughness;
float aSquare = a * a;
float NdotH = max(dot(N, H), 0.0);
float NdotHSquare = NdotH * NdotH;
float numerator = aSquare;
float denominator = (NdotHSquare * (aSquare - 1.0) + 1.0);
denominator = PI * denominator * denominator;
return numerator / denominator;
}
// Cook-Torrance Bidirectional Reflective Distribution Function
vec3 BRDF(vec3 L, vec3 V, vec3 N, vec3 radiance, vec4 albedo, float metallic, float roughness, vec3 F0) {
vec3 H = normalize (V + L);
float D = NormalDistributionFunction(N, H, roughness);
float G = GeometryFunction(N, V, L, roughness);
vec3 F = FresnelFunction(max(dot(H, V), 0.0), F0);
vec3 numerator = D * G * F;
float denominator = 4 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.001; // Prevent division by zero.
vec3 specular = numerator / denominator;
vec3 kS = F;
vec3 kD = vec3(1.0) - kS;
kD *= 1.0 - metallic;
float NdotL = max(dot(N, L), 0.0);
vec3 color = (kD * albedo.rgb / PI + specular) * radiance * NdotL;
return color;
}
Does this physically make sense?
The only workaround I see is either not using a perfect mirror value of 0.0 roughness or always clamp the minimum value to something like 0.04.