Problem on physical material

Started by
12 comments, last by Alundra 10 years ago

Hi all,

I'm working on physical material to change because phong is dead nowadays.

Here the code I currently use to compute the specular factor :


// [Walter et al. 2007, "Microfacet models for refraction through rough surfaces"].
float D_GGX( in float Roughness, in float NoH )
{
  float m = Roughness * Roughness;
  float m2 = m * m;
  float d = ( NoH * m2 - NoH ) * NoH + 1.0f;
  return m2 / ( d*d );
}

// Tuned to match behavior of Smith.
// [Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"].
float G_Schlick( in float Roughness, in float NoV, in float NoL )
{
  float k = (Roughness * Roughness) * 0.5f;
  float G_SchlickV = NoV * (1.0f - k) + k;
  float G_SchlickL = NoL * (1.0f - k) + k;
  return 0.25f / ( G_SchlickV * G_SchlickL );
}

// [Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"]
float3 F_Schlick( in float3 SpecularColor, in float VoH )
{
  return SpecularColor + ( 1.0f - SpecularColor ) * exp2( (-5.55473f * VoH - 6.98316f) * VoH );
}

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 VdotH = max( 0.0f, dot( ViewDirection, HalfDirection ) );
  
  // Generalized microfacet specular.
  float D = D_GGX( Roughness, NdotH );
  float G = G_Schlick( Roughness, NdotV, NdotL );
  float3 F = F_Schlick( SurfaceData.SpecularColor, VdotH );
  
  // Return the specular factor.
  return D * G * F;
}

The problem is I have artifact sometimes on different settings or angles.

Thanks for the help

Advertisement

Here a screenshot of artifacts :

http://uppix.com/f-PhysicalArtifact533ae2f30015ebcb.png

I suggest you get nVidia nSight if you have a nVidia card, AMD Perfstudio 2 if you have an AMD card and Intel's equivalent if you have an Intel iGPU.

Use that software's framedebugger to debug your shaders.

"What? It disintegrated. By definition, it cannot be fixed." - Gru - Dispicable me

"Dude, the world is only limited by your imagination" - Me

First guess: either shadowmapping or NaN. The latter would be the case if you divide by 0 (eg in D_GGX or G_Schlick), so try to clamp the results before dividing by 0.

PS:


because phong is dead nowadays.

This is only true for photorealistic rendering, not for NPR. I would bet that NPR games will have a large share in the market in the future wink.png

Were those functions copied from Unreal 4 shaders? Maybe they expect a different input (range?).

It's a mix of unreal 4 shader code, paper of Brian Karis and article of Sebastien Lagarde.

I looked on SpecularAA of Matt Petineo, can be nice to add that to avoid aliasing on specular (normal map).

All work fine, just on directional light when you have this angle of view (pretty on top on a specific side).

I tried to change the max function with an epsilon (0.001f) on each against 0.0f, the problem still the same.

I tried to scale the static mesh who is the level by 5, the problem still the same.

Links:

http://seblagarde.wordpress.com/2011/08/17/hello-world/

http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf

UnrealEngine4 Shader = BRDF.usf

That screenshot really indicates to me either unbiased shadow-mapping or overlapping double-sided polygons.
If you want to prove it is your shader itself, disable parts of it until that goes away. In doing so, you will not only prove it is the shader but also figure out what part of the shader it is and likely be able to fix it, or at least ask a narrower question.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

I have disabled the specular on directionalLight (you can see the comment at the end of function) :


void Directional( in SURFACE_DATA SurfaceData, in DIRECTIONAL_LIGHT Light, inout float3 Result )
{
  float3 LightDirection = normalize( -Light.Direction );
  float NdotL = max( 0.0f, dot( SurfaceData.Normal, LightDirection ) );
  if( NdotL > 0.0f )
  {    
    // Compute the specular factor.
    float3 SpecFactor = ComputeSpecFactor( SurfaceData, LightDirection, NdotL );
    
    // Accumulate the light results.
    //Result += Light.Intensity * Light.Color * (SurfaceData.DiffuseColor * NdotL + SpecFactor);
    Result += Light.Intensity * Light.Color * (SurfaceData.DiffuseColor * NdotL);
  }
}

The problem is away without specular :

http://uppix.com/f-ProbNoSpec533c1fc10015ee2a.png

The problem still the same with just :


Result += SpecFactor;

I had no problems with PhongShading, it's not a problem of geometry I guess. I just changed the ComputeSpecFactor function to move to physical.

On all other side there is no prob but only on this side with the directional light artifacts are visible, here decomposed D/F/G on the bad side :

D : http://uppix.com/f-ProbD533c225e0015ee2f.png
F : http://uppix.com/f-ProbF533c226e0015ee31.png
G : http://uppix.com/f-ProbG533c227e0015ee32.png

Looks like the G term is the likely culprit.

For starters, schlick's G is

G1(x) = dot(n, x) / ( dot(n, x) * (1-k) + k )

G(L, V, H) = G1(L) * G1(V)

I don't know where that 0.25 in your numerator came from, but at the least you're missing an NoL * NoV, and I'm pretty sure that doesn't cancel out. Epic's paper mentions using a remapping of roughness to (roughness+1)/2 before squaring it, which guarantees a non-zero denominator.

Your math for G is probably exploding for surfaces that don't have normals facing one of the two directions, and a roughness of 0.

Additionally, your D term formulation might start misbehaving as NoH approaches 1, but the artifacting in that term is probably supposed to get masked off by the missing NoL * NoV in the G term.

This topic is closed to new replies.

Advertisement