0
$\begingroup$

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:

The artifacts

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?

$\endgroup$
1
$\begingroup$

It turns out that the ring was happening from a negative divided by a negative, so adding nom = max(nom, 0.0); fixed the problem. The new highlight, amplified:

Correct result

$\endgroup$
  • $\begingroup$ Please consider marking this as the accepted answer. $\endgroup$ – ivokabel Jul 22 at 8:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.