Hi,
I am taking a crack at implementing PBR lighting in my game-engine and I have managed to get it working but it seems to produce this odd hole with blackness surrounding it which I cannot seem to figure out.
I have tried visually outputting each term D, G, F and also the specular term to see what might be the issue but I don't see it when outputting them individually. I was wondering if anyone has experienced this issue before and could point me in the right direction of where I might be doing wrong.
const float PI = 3.14159265359;
vec3 fresnel_schlick(float cosTheta, vec3 F0)
{
return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
}
float beckmann_distribution(vec3 Normal, vec3 HalfDir, float roughness)
{
float a = roughness * roughness; // beckmann roughness is r * r
float a2 = a * a;
float NdotH = max(dot(Normal, HalfDir), 0.0);
float NdotH2 = NdotH * NdotH;
float num = exp((NdotH2 - 1.0) / (a2 * NdotH2));
float denom = PI * a2 * NdotH2 * NdotH2;
return num / denom;
}
float masking_term(vec3 Normal, vec3 HalfDir, vec3 LightDirection, vec3 ViewDirection)
{
float NdotH = max(dot(Normal, HalfDir), 0.0);
float NdotV = max(dot(Normal, ViewDirection), 0.0);
float VdotH = max(dot(ViewDirection, HalfDir), 0.0);
float NdotL = max(dot(Normal, LightDirection), 0.0);
float term1 = 2 * NdotH * NdotV / VdotH;
float term2 = 2 * NdotH * NdotL / VdotH;
float term = min(1, min(term1, term2));
return term;
}
void main() {
vec4 lightColour = Light.color;
vec4 lightPosition = Light.position;
vec3 WorldPos = FragPosition.xyz;
vec3 normal = normalize(normals);
vec3 LightDirection = normalize(lightPosition.xyz - WorldPos);
vec3 ViewDirection = normalize(ubo.position.xyz - WorldPos);
vec3 HalfDir = normalize(ViewDirection + LightDirection);
// Texture sampling
vec3 color = texture(textures[push.base_texture], uv).xyz;
float metallic = texture(textures[push.metalness_texture], uv).r;
float roughness = texture(textures[push.roughness_texture], uv).r;
vec3 alpha = texture(textures[push.alphamask_texture], uv).rgb;
// Lighting calc
vec3 F0 = vec3(0.04);
F0 = mix(F0, color, metallic);
vec3 F = fresnel_schlick(max(dot(HalfDir, ViewDirection), 0.0), F0);
// Normal distrbutin function
float d = beckmann_distribution(normal, HalfDir, roughness);
// Geometry masking term
float g = masking_term(normal, HalfDir, LightDirection, ViewDirection);
vec3 num = d * F * g;
float epsilon = 0.0001;
float denom = 4 * max(dot(normal, ViewDirection), 0.0) * max(dot(normal, LightDirection), 0.0) + epsilon;
vec3 specular = num / denom;
float NdotL = max(dot(normal, LightDirection), 0.0);
vec3 L_diffuse = (color / PI) * ((vec3(1.0) - F) * (1.0 - metallic)) * lightColour.xyz * NdotL;
float ambientAmount = 0.2;
vec3 ambient = vec3(ambientAmount) * color;
vec3 shading = ambient + L_diffuse + specular;
outColor = vec4(vec3(shading), 1.0);
}