I'm still working on my BRDF equations. Theoretically, all equations are correct, but the hilights are super sharp. I'm not sure if this is a result of me not using Image-Based Lighting (I currently use just an env map with a LOD function). I'm using materials from here: http://freepbr.com/c/base-materials/ - I use Specular/Gloss but the materials use the fragment shader to convert it.
Material Frag Shader (Excerpt) (Specifically, the Metalness-Roughness shader):
float Roughness = baseSpecular.a;
if (uTexRoughEnabled == 1)
Roughness = texture(texRoughness, UV).r;
float Metalness = texture(texSpecular, UV).r;
// 1 - Roughness becomes Glossiness
specular = vec4(mix(vec3(0.4), albedo.rgb, Metalness), 1-Roughness);
albedo = vec4(mix(albedo.rgb, vec3(0), Metalness), 1-Roughness);
Lighting Functions:
vec3 Light_F(in vec3 Specular, in float VH) {
// Fresnel Schlick
return Specular + (1-Specular) * pow(1-VH, 5.0f);
}
float Light_D(in float alpha, in float NH) {
// GGX
float alphaSqr = alpha*alpha;
float denom = NH * NH * (alphaSqr - 1) + 1;
return alphaSqr / (pi * denom * denom);
}
float Light_V( in float NL, in float NV, in float alpha ) {
// Frostbite's GGX
float Lambda_GGXV = NL * sqrt (( - NV * alpha + NV ) * NV + alpha );
float Lambda_GGXL = NV * sqrt (( - NL * alpha + NL ) * NL + alpha );
return 0.5f / ( Lambda_GGXV + Lambda_GGXL );
}
vec3 Light_Diffuse(in float NV, in float NL, in vec3 Normal, in float alpha, in vec3 Albedo, in vec3 eyeDir, in vec3 lightDir) {
// Oren-Nayar
float gamma = dot( eyeDir - Normal * NV, lightDir - Normal * NL);
float A = 1.0f - 0.5f * (alpha / (alpha + 0.57f));
float B = 0.45f * (alpha / (alpha + 0.09));
float diffAlpha = max( acos( NV ), acos( NL ) );
float diffBeta = min( acos( NV ), acos( NL ) );
float C = sin(diffAlpha) * tan(diffBeta);
return Albedo * (A + B * max( 0.0f, gamma ) * C) / pi;
}
Final lighting function in deferred renderer:
vec3 LightCalc(in vec3 Albedo, in vec4 WorldPos, in vec4 Specular, in vec3 Normal, in samplerCube envMap, in vec3 lightPos, in float lightAtten, in vec4 lightColor) {
vec3 lightDir = WorldPos.xyz - lightPos;
vec3 eyeDir = normalize(eyePos - WorldPos.xyz);
vec3 eyeReflect = reflect(-eyeDir, Normal);
float Distance = length(lightDir);
lightDir = -normalize(lightDir);
float Attenuation = clamp(1 - pow(Distance / lightAtten, 4), 0, 1);
Attenuation = Attenuation*Attenuation/(Distance*Distance+1);
vec3 AmbientColor = vec3(Albedo.xyz)*0.01;
float Roughness = 1-Specular.a;
float alpha = Roughness * Roughness;
vec3 H = normalize(eyeDir + lightDir);
float NL = clamp(dot(Normal, lightDir), 0, 1);
float NH = clamp(dot(Normal, H), 0, 1);
float NV = clamp(dot(Normal, eyeDir), 0, 1);
float LH = clamp(dot(lightDir, H), 0, 1);
float VH = clamp(dot(eyeDir, H), 0, 1);
float lod = compute_lod(alpha, 1, NH);
vec3 reflectDir = normalize(eyeReflect);
vec3 reflectPix = textureLod(envMap, reflectDir, lod).rgb;
float D = Light_D(alpha, NH);
vec3 F = Light_F(clamp(Specular.rgb, 0.018, 0.95), LH);
float Vis = Light_V(NL, NV, alpha);
vec3 Spec = (D * F * Vis) * reflectPix;
vec3 Diffuse = Light_Diffuse(NV, NL, Normal, alpha, Albedo.rgb, eyeDir, lightDir);
vec3 lightModifier = lightColor.xyz*lightColor.w*Attenuation;
return NL*(Spec + max(Diffuse, AmbientColor))*lightModifier;
}
Feel free to point out any mistakes I made, even if not related to the issue. I've tested the materials in Unreal, and they looked correct. I doubt this is solely due to the lack of Image-Based Lighting. I also doubt this is an issue with using point lighting. Additionally, if I turn down the roughness by a lot, it becomes too dark a high roughness to be the issue.