Jump to content
• ### What is your GameDev Story?

• Advertisement

# Cook-Torrance G term

This topic is 1120 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

## Recommended Posts

Hello,

I am trying to implement the cook torrance lighting model. I use the GGX Trowbridge-Reitz function as D, the Schlick approximation as F, and Smith for G.

I am following the equations from this : http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf

Looking at the result of the functions alone, it seems that D is working :

My code :

float G_Schlick( vec3 normal, vec3 v, float k )
{
float ndotv = abs( dot( normal, v ) );

float den = ndotv * ( 1.0 - k ) + k;
return ndotv / den;
}

float Geometric_Smith( vec3 normal, vec3 lightDir, vec3 viewDir, float roughness )
{
float k = ( roughness + 1 ) * ( roughness + 1 ) / 8;
//float k = roughness * sqrt( 2 / pi );

return G_Schlick( normal, lightDir, k ) * G_Schlick( normal, viewDir, k );
}

void main()
{
float error = 0.01;
float roughness = clamp( material.roughness - error, 0.0, 1.0 ) + error;

vec3 normal = normalize( Normal );
vec3 viewDir = normalize( cameraPos - Position );
vec3 lightDir = normalize( lightPos - Position );

vec3 half = normalize( viewDir + lightDir );

float D = GGX_TrowbridgeReitz( normalize( Normal ), half, roughness );
float G = Geometric_Smith( normal, lightDir, viewDir, roughness );

float ndotl = max( dot( normal, lightDir ), 0.0 );
float ndotv = max( dot( normal, viewDir ), 0.0 );

// i dont know how to visualize G, so I tried 3 things
vec3 finalColor = vec3( G );
vec3 finalColor = vec3( G / ( 4.0 * ndotl * ndotv ) );
vec3 finalColor = vec3( G / ( ndotl * ndotv ) );

Color = vec4( finalColor, 1.0 );
}


I tried with the normal and the half vector as "normal" parameter, and it seems that normal gives the best results, but some resources says that the half vector should be used.

Results with roughness = 0 :

And with roughness = 1.0 :

( The light source is just on top of the sphere )

What am I doing wrong? According to this image, the results seems to be very different :

Thanks.

Edited by Aulaulz

#### Share this post

##### Share on other sites
Advertisement

Just had a very quick look (I'm in a rush) and it seems like you are not applying gamma correction.

You might want to read this.

Edited by DrakeFG

#### Share this post

##### Share on other sites

I don't recognize what you're calling Smith vis/geo?

Here's the code I use for vis/geo terms, basically verbatim implementations of the formulas with the usual "not shipping yet, roughness * roughness everywhere."

// Visibility terms

/// Smith GGX Visibility
///     nDotL: dot-prod of surface normal and light direction
///     nDotV: dot-prod of surface normal and view direction
///     roughness: surface roughness
float SmithGGXVisibility(in float nDotL, in float nDotV, in float roughness)
{
float rough2 = roughness * roughness;
float gSmithV = nDotV + sqrt(nDotV * (nDotV - nDotV * rough2) + rough2);
float gSmithL = nDotL + sqrt(nDotL * (nDotL - nDotL * rough2) + rough2);
return 1.0 / (gSmithV * gSmithL);
}

float SchlickG1(in float factor, in float rough2)
{
return 1.0 / (factor * (1.0 - rough2) + rough2);
}

/// Schlick approximation of Smith GGX
///     nDotL: dot product of surface normal and light direction
///     nDotV: dot product of surface normal and view direction
///     roughness: surface roughness
float SchlickVisibility(float nDotL, float nDotV, float roughness)
{
const float rough2 = roughness * roughness;
return (SchlickG1(nDotL, rough2) * SchlickG1(nDotV, rough2)) * 0.25;
}


What really strikes me as odd is your use of "roughness + 1"? If you were working smoothness instead of roughness that'd be "1 - roughness,"  but I can't really make any assumptions about whether you're renormalizing inputs or such.

What's the deal with the division by 8?

#### Share this post

##### Share on other sites

Sorry for the late answer. I was not using gamma correction because the link I am following is not using it ( since the screenshots are just showing the D and G functions separately ). I tried it anyway, and the results are just brighter, but the shape doesn't really change.

To be honest I am really lost with this, so I might have used the wrong words.

What I call Smith is G = G1(V) + G1(L).

The incrementation of roughness and the division by 8 are coming from the unreal paper here :

I use a roughness between 0 and 1, 1 means the surface is very rough.

I tried your code, but I still got strange results.

With 0 roughness :

With 1 roughness :

Shouldnt the surface be white with roughness = 0?

My code :

float schlickG1( float factor, float r2 )
{
return 1.0 / ( factor * ( 1.0 - r2 ) + r2 );
}

float visibility( float ndotl, float ndotv, float roughness )
{
float r2 = roughness * roughness + 0.01;
return schlickG1( ndotl, r2 ) * schlickG1( ndotv, r2 ) * 0.25;
}

void main()
{
vec3 normal = normalize( Normal );
vec3 lightDir = normalize( lightPos );
vec3 viewDir = normalize( cameraPos );

float ndotl = ( dot( normal, lightDir ) );
float ndotv = ( dot( normal, viewDir ) );

float v = visibility( ndotl, ndotv, material.roughness );

vec3 finalColor = vec3( v );

Color = vec4( finalColor, 1.0 );
}


Thanks for your answers guys!

Edited by Aulaulz

#### Share this post

##### Share on other sites

Does anyone have an answer?

Edited by Aulaulz

#### Share this post

##### Share on other sites

I use similar code but with differences :

// [Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"].
float SchlickFunc( in float v, in float k )
{
return 1.0f / ( v * ( 1.0f - k ) + k );
}

// [Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"].
float Vis_Schlick( in float Roughness, in float NoV, in float NoL )
{
float k = ( Roughness * Roughness ) * 0.5f;
return SchlickFunc( NoL, k ) * SchlickFunc( NoV, k );
}

#### Share this post

##### Share on other sites

• Advertisement
• Advertisement
• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

(You must login to your GameDev.net account.)

• ### Popular Now

• 13
• 9
• 15
• 14
• 46
• Advertisement
• ### Forum Statistics

• Total Topics
634067
• Total Posts
3015323
×

## Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!