# Problem on physical material

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

## Recommended Posts

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

Edited by Alundra

##### Share on other sites

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.

##### Share on other sites

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:

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

Edited by Ashaman73

##### Share on other sites

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

##### Share on other sites

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.

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

Edited by Alundra

##### Share on other sites
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

##### Share on other sites

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 :

##### Share on other sites

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.

##### Share on other sites

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.

• ### What is your GameDev Story?

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

• 15
• 14
• 10
• 9
• 11
• ### Forum Statistics

• Total Topics
634096
• Total Posts
3015493
×