Strange artefact on BRDF shader

Started by
2 comments, last by RobM 2 years, 3 months ago

Hi

I'm getting a strange artefact when rendering my terrain at glancing angles when facing the directional light. I think it's something to do with my normal mapping but I'm not sure. Here's a screenshot of the final render:

Greyish artefact in the middle of the screen

I'm using a standard BRDF algorithm which is essentially this:

// D = normal distribution
// V = geometry function
// F = fresnel
// fullyLit = 0 in shadow, 1 not in shadow
// Normal = terrain normal
float D = D_GGX(newDot, Roughness) / PI;
float V = GeometrySmith(Normal, -incident, -toLight, Roughness);
F = lerp(F, Albedo, Metalness);

float3 numerator = D * V * F;

float denominator = 4.0 * saturate(dot(Normal, -incident)) * saturate(dot(Normal, -toLight)) / PI;

specular = numerator / max(denominator, 0.001) * fullyLit;

The D_GGX and GeometrySmith methods are pretty standard I believe:

float D_GGX(float NoH, float a) {
	float a2 = a * a;
	float NoH2 = NoH * NoH;
	
	float nom = a2;
	float denom = (NoH2 * (a2 - 1.0) + 1.0);
	denom = PI * denom * denom;

	return nom / denom;
}

float GeometrySchlickGGX(float NdotV, float k)
{
	float nom = NdotV;
	float denom = NdotV * (1.0 - k) + k;
	
	return nom / denom;
}

float GeometrySmith(float3 N, float3 V, float3 L, float k)
{
	float NdotV = max(dot(N, V), 0.0);
	float NdotL = max(dot(N, L), 0.0);
	float ggx1 = GeometrySchlickGGX(NdotV, k);
	float ggx2 = GeometrySchlickGGX(NdotL, k);

	return ggx1 * ggx2;
}

In terms of normals, I'm using tessellation for my terrain and I'm using a global normal map (8192x8192) so I just sample that normal map in the pixel shader. I then immediately compute the tangent and binormal using the following code:

float3 terrNorm = v3.Sample(TexSamplerPointClamp, float2((input.UV + 4096) / 8192)).rbg;
float3 geoNormal = (terrNorm * 2.0f) - 1.0f;
float3 geoTangent = normalize(cross(geoNormal, float3(0, 0, 1)));
float3 geoBinormal = normalize(cross(geoTangent, geoNormal));

I then sample the normal texture and apply the normal, tangent and binormal like this:

float3 v12 = v13.Sample(TexSamplerPointWrap, v11.xy);
// decompress normal
v12 = (v12 * 2.0f) - 1.0f;
v12 = (v12.x * geoTangent) + (v12.y * geoBinormal) + (v12.z * geoNormal);
float3 Normal = v12.xyz;

Does this look correct? The lighting does look correct to me, here's a shot of the directional light away from glancing angle:

After doing a bit of debugging, it looks like the artefact is coming from the specular component so I returned the distribution part of it here:

And the Geometry function here (all values multiplied by 50 to see the 0 areas):

So it looks like it's something to do with the geometry function, but having checked mine against what I've seen on the web, it looks identical. It looks like it's caused by the normal map of the detail texture, because if I leave that out, I don't get this artefact. And it only happens when the normal of the terrain added to the detail normal end up almost at the half vector between incident and light.

I saw a very similar post here: https://computergraphics.stackexchange.com/questions/8239/cook-torrance-specular-brdf-artifact?noredirect=1&lq=1 - and although they've used a pretty bad example image, the issue is the same but there wasn't much to go on - unless my tangent/binormal code is wrong, but I've done tests on it and it looks okay to me.

Scratching my head a bit on this one, anybody seen anything similar?…

Advertisement

Parallax?

@elspar2 sorry, what do you mean? Are you asking if I'm using it or suggesting that I do use it.

I'm not using it, it's just a simple normal map blended with the normal map of the terrain.

This topic is closed to new replies.

Advertisement