0
\$\begingroup\$

I'm currently attempting to implement BRDF lighting, and am hitting a bit of a snag with my specular term - the specular highlights aren't rendering correctly.

To make things simple, I'm using a single directional light rendering down the Z axis only, and manually specify the gloss/specularity of each of the following spheres.

Glossyness increases left to right, and Specularity increases bottom to top. Notice how the highlights seem shifted nearly 90 degrees upwards:

Specular Term enter image description here

Calculating the specular BRDF

I use the generic Fresnel Shlick eq:

Fresnel

For the NDF, I use the GGX Trowbridge-Reitz eq:

NDF

And for the Geometric Shadowing function, I use the Smith / Shlick-Beckmann eq:

GEO

vec3 BRDF_Specular(vec3 F0, vec3 1minusF0, vec3 WorldPos, vec3 Normal)
{   
    vec3 LightDirection         = vec3(0, 0, -1);
    vec3 ViewDirection          = normalize(EyePos - WorldPos);
    vec3 HalfVec                = normalize(LightDirection + ViewDirection);
    float NdotL                 = clamp(dot(Normal, LightDirection), 0.0, 1.0);
    float NdotV                 = clamp(dot(Normal, ViewDirection), 0.0, 1.0);
    float NdotH                 = clamp(dot(Normal, HalfVec), 0.0, 1.0);
    float VdotH                 = clamp(dot(ViewDirection, HalfVec), 0.0, 1.0);

    float Roughness             = max(1.0f - Gloss, 0.0); // Turn into roughness
    float Roughness_2           = (Roughness * Roughness);
    float NdotH_2               = NdotH * NdotH;

    /*  Normal Distribution Function 
        GGX (Trowbridge-Reitz) */
    float D0                    = (NdotH_2 * (a_2 - 1.0f) + 1.0f);
    float D                     = a_2 / (M_PI * (D0 * D0)); 

    /*  Fresnel
        Shlick  */
    vec3 Fs                     = F0 + 1minusF0 * pow(1.0 - VdotH, 5.0);

    /*  Geometric Shadowing
        Smith / Shlick-Beckmann */
    float k                     = a_2 / sqrt(2.0 / M_PI);
    float GV                    = NdotV / (NdotV * (1.0 - k) + k);
    float GL                    = NdotL / (NdotL * (1.0 - k) + k);
    float G                     = GV * GL;

    vec3 brdfspec               = vec3(max(( Fs * D * G ) / (4.0f * NdotL * NdotV), 0.0));
    return brdfspec;
}

I've been following so many different resources and mimicked many other implementations, and even reducing it down to this basic level I'm still having this issue. I don't know why I'm not getting proper results

I'm using a deferred renderer, I derive the World position of each fragment from the depth buffer, and store my normals in viewspace. I don't use a "Metalness" map, but instead use a single rgb specular map, hense why my Fresnel calculation uses Vec3's instead of floats.

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

Turns out I had miscalculated my camera position ever since I switched to a third person camera.

This in turn made my viewing direction vector point in the wrong direction, and systematically broke all the subsequent calculations.

Proper specular reflections

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .