Jump to content
  • Advertisement
Sign in to follow this  

DX11 Normals and TBN Matrices

Recommended Posts

Posted (edited)

Hello everyone,

I've been during the past few days trying to fix sunlight on my sphere which have some bugs in it. For starters I'm using this code: https://github.com/Illation/ETEngine/blob/master/source/Engine/Shaders/PlanetPatch.glsl to calculate my normals instead of using a normal map.

I'm then using this guide: http://www.thetenthplanet.de/archives/1180
To get my TBN Matrix. I have 2 main issues I'm working to solve when reworking this code. First I get seams in the normal map along the equator and from pole to pole. The normal also seems to move when I move my camera. 

Here is a video showing what I mean, the color is the normal calculated with the TBN matrix and as the camera moves it moves along with it. Nothing is multiplied by the view matrix or anything.

Here is my code Vertex Shader:

	output.normal = mul(finalPos, worldMatrix);
	output.viewVector = (mul(cameraPos.xyz, worldMatrix) - mul(finalPos, worldMatrix));

	mapCoords = normalize(finalPos);
	output.mapCoord = float2((0.5f + (atan2(mapCoords.z, mapCoords.x) / (2 * 3.14159265f))), (0.5f - (asin(mapCoords.y) / 3.14159265f)));

	output.position = mul(float4(finalPos, 1.0f), worldMatrix);
	output.position = mul(output.position, viewMatrix);
	output.position = mul(output.position, projectionMatrix);

	return output;

and also what might be more important, the pixel shader:

float3x3 GetTBNMatrix(float3 normalVector, float3 posVector, float2 uv)
	float3 dp1, dp2, dp2perp, dp1perp, T, B;
	float2 duv1, duv2;
	float invMax;

	dp1 = ddx(posVector);
	dp2 = ddy(posVector);
	duv1 = ddx(uv);
	duv2 = ddx(uv);

	dp2perp = cross(dp2, normalVector);
	dp1perp = cross(normalVector, dp1);

	// * -1 due to being LH coordinate system
	T = (dp2perp * duv1.x + dp1perp * duv2.x) * -1;
	B = (dp2perp * duv1.y + dp1perp * duv2.y) * -1;

	invMax = rsqrt(max(dot(T, T), dot(B, B)));

    return float3x3(T * invMax, B * invMax, normalVector);

float GetHeight(float2 uv)
	return shaderTexture.SampleLevel(sampleType, uv, 0).r * (21.229f + 8.2f);

float3 CalculateNormal(float3 normalVector, float3 viewVector, float2 uv)
	float textureWidth, textureHeight, hL, hR, hD, hU;
	float3 texOffset, N;
	float3x3 TBN;

	shaderTexture.GetDimensions(textureWidth, textureHeight);

	texOffset = float3((1.0f / textureWidth), (1.0f / textureHeight), 0.0f);

	hL = GetHeight(uv - texOffset.xz);
	hR = GetHeight(uv + texOffset.xz);
	hD = GetHeight(uv + texOffset.zy);
	hU = GetHeight(uv - texOffset.zy);

	N = normalize(float3((hL - hR), (hU - hD), 2.0f));

	TBN = GetTBNMatrix(normalVector, -viewVector, uv);

	return mul(TBN, N);

float4 MarsPixelShader(PixelInputType input) : SV_TARGET
	float3 normal;
	float lightIntensity, color;
	float4 finalColor;

	normal = normalize(CalculateNormal(normalize(input.normal), normalize(input.viewVector), input.mapCoord));

    lightIntensity = saturate(dot(normal, normalize(-lightDirection)));

    color = saturate(diffuseColor * lightIntensity);

	return float4(normal.rgb, 1.0f);//float4(color, color, color, 1.0f);

Hope anyone can help shine some light on this problem for me

Best Regards and Thanks in advance


Edited by Toastmastern

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Advertisement

Important Information

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

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!