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\$
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\$

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.