I've been trying to implement a microfacet specular BRDF based on the equations in Real Shading in UE4, but I'm getting weird ring-shaped artifacts in the highlights of rough surfaces:
Here's the relevant pieces of the fragment shader:
float D(float NoH, float roughness) {
float a = sqr(roughness);
float a2 = sqr(a);
float denom = PI * sqr(sqr(NoH) * (a2 - 1.0) + 1.0);
return a2 / denom;
}
float G1(float NoV, float k) {
float denom = NoV * (1.0 - k) + k;
return NoV / denom;
}
float G(float NoL, float NoV, float roughness) {
float k = sqr(roughness + 1) / 8.0;
return G1(NoL, k) * G1(NoV, k);
}
float F(float VoH, float ior) {
float f0 = sqr((1.0-ior)/(1.0+ior));
return f0 + (1.0 - f0) * exp2((-5.55473*VoH - 6.98316) * VoH);
}
vec3 brdf(in vec3 V, in vec3 L, in vec3 N, in Material mat) {
vec3 H = normalize(V+L);
float NoL = dot(N, L);
float NoV = dot(N, V);
float nom = D(dot(N, H), mat.roughness)
* F(dot(V, H), mat.ior)
* G(NoL, NoV, mat.roughness);
float denom = 4.0 * NoL * NoV;
return vec3(1) * nom / denom;
}
// ----------------------
void main() {
// ...
vec3 rd = normalize(frag_pos - camera_pos);
Material mat = materials[mat_index];
col = brdf(-rd, sun_dir, normal, mat);
// ...
}
Any idea what I'm doing wrong?