• Advertisement
Sign in to follow this  

PBR minimum roughness ?

This topic is 430 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

Hi,

Here the BRDF used everywhere :

float3 Diffuse_Lambert( in float3 DiffuseColor )
{
  return DiffuseColor * ( 1.0f / PI );
}

float D_GGX( in float m2, in float NoH )
{
  return m2 / ( PI * pow( NoH * NoH * ( m2 - 1.0f ) + 1.0f, 2.0f ) );
}

float Vis_GGX_Func( in float NoX, in float m2 )
{
  return 1.0f / ( NoX + sqrt( m2 + ( 1.0f - m2 ) * NoX * NoX ) );
}

float Vis_GGX( in float m2, in float NoL, in float NoV )
{
  return Vis_GGX_Func( NoL, m2 ) * Vis_GGX_Func( NoV, m2 );
}

float3 F_Schlick( in float3 SpecularColor, in float LoH )
{
  return SpecularColor + ( 1.0f - SpecularColor ) * pow( 1.0f - LoH, 5.0f );
}

float3 ComputeSpecFactor( in SURFACE_DATA SurfaceData, in float3 LightDirection, in float NdotL )
{
  // Variables used to compute the lighting factor.
  float3 ViewDirection = normalize( -SurfaceData.Position );
  float3 HalfDirection = normalize( LightDirection + ViewDirection );
  
  // Compute the lighting factors.
  float NdotH = max( 0.0f, dot( SurfaceData.Normal, HalfDirection ) );
  float NdotV = max( 0.0f, dot( SurfaceData.Normal, ViewDirection ) );
  float LdotH = max( 0.0f, dot( LightDirection, HalfDirection ) );

  // Compute the m2 factor.
  float m = SurfaceData.Roughness * SurfaceData.Roughness;
  float m2 = m * m;
  
  // Generalized microfacet specular.
  float D = D_GGX( m2, NdotH );
  float Vis = Vis_GGX( m2, NdotL, NdotV );
  float3 F = F_Schlick( SurfaceData.SpecularColor, LdotH );
  
  // Return the specular factor.
  return D * Vis * F;
}

I actually clamp the roughness in the range [0.08, 1.0].

A better solution exists ? A better value as minimum exists ?

Thanks

Edited by Alundra

Share this post


Link to post
Share on other sites
Advertisement

Yeah GGX explodes if it's roughness value reaches zero (and also gets some crazy numerical imprecision bugs if it's close to zero), so I remap my roughness textures into some range like (0.05,1) too.

 

There's a similar problem in Blinn-Phong (both the traditional version and the "PBR" version of it) where specular exponent of zero will cause it go explode (as xy can be undefined behaviour in some cases where y is zero) so it's typical to remap your textures to some range like (1,10000).

Share this post


Link to post
Share on other sites

Ok, thanks, that confirms this is not a mistake but really needed.

When you say remap, you mean a real remap [0, 1] to [0.08, 1] or a simple clamp to always have 0.08 until it's upper than this value ?

Edited by Alundra

Share this post


Link to post
Share on other sites
if you'd clamp, you'd waste a bit of range, hence you should really remap for best quality. unless your source data is already the same precision as the final data (e.g. 8 bit), then remapping would harm you more than doing the clamp in the shader.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement