Where to calculate TBN matrix?

Started by
13 comments, last by 215648 9 years, 10 months ago

Thanks both.
@Newtechnology: how would you do that with just one normalize in the PS, you skip normalizing the vectors when they come into the PS? (normal, bitangent and tangent)

@OsmanB: but do I need the view vector per pixel instead of per vertex?


//---------------------------------------------------------------------------------------
// Transforms a normal map sample to world space.
//---------------------------------------------------------------------------------------
float3 NormalSampleToWorldSpace(float3 normalMapSample, float3 unitNormalW, float3 tangentW)
{
// Uncompress each component from [0,1] to [-1,1].
float3 normalT = 2.0f*normalMapSample - 1.0f;
 
// Build orthonormal basis.
float3 N = unitNormalW;
float3 T = normalize(tangentW - dot(tangentW, N)*N);
float3 B = cross(N, T);
 
float3x3 TBN = float3x3(T, B, N);
 
// Transform from tangent space to world space.
float3 bumpedNormalW = mul(normalT, TBN);
 
return bumpedNormalW;
}
 
//In pixel shader
 
float3 normalMapSample = gNormalMap.Sample(samLinear, pin.Tex).rgb;
float3 bumpedNormalW = NormalSampleToWorldSpace(normalMapSample, pin.NormalW, pin.TangentW);

this approach calculates bitangent in pixel shader.

Advertisement

Thanks, in my case it would come down to this:


VS_OUTPUT VS_function(VS_INPUT input)
{
	VS_OUTPUT Out = (VS_OUTPUT)0;

// more stuff

	#ifdef USENORMALMAP
	// Worldspace to Tangent space for normalMapping
	Out.TangentWorld	= mul(input.Tangent, (float3x3)World);
	Out.BiNormalWorld	= mul(input.Binormal, (float3x3)World);
	Out.NormalWorld	= mul(input.Normal, (float3x3)World);
	#else
	Out.Normal = normalize(mul(input.Normal, (float3x3)World));
	#endif

}

// and the PS

float4 PS_function(VS_OUTPUT input): COLOR0
{
// more stuff

	#ifdef USENORMALMAP
	float3x3 worldToTangent = float3x3(input.TangentWorld,
						     input.BiNormalWorld,
						     input.NormalWorld);
	
	float3 finalNormal = normalize(2.0 * (tex2D(normalMapSampler, input.TexCoord).xyz) - 1.0);
	finalNormal = normalize(mul(finalNormal, worldToTangent));

	#else
	float3 finalNormal = normalize(input.Normal);
	#endif


I do indeed see no visual difference. Save me quite some normalizations now.

Maybe I can do the same when I don't use normal mapping, only normalize the normal in te PS, not in the VS also?

@OsmanB: thanks, I think I can pass the viewdir like this:


// in the VS

	Out.ViewDir = CameraPos - Out.wPos.xyz;

// then in the ps

	float3 ViewDir = normalize(input.ViewDir);

The result is so much nicer, and correct now probably smile.png

@Newtechnology: thanks, I tried it out sending just 2 out of 3 and calculating the bitangent in the PS, but I don't see the avantages yet (maybe that's about taste), I might do it when I'm gonna use DXT5 compressed normal maps where I leave 1 channel out and calculate it through the other 2. I've read that this gives higher quality results, didn't see that yet.

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

@Newtechnology: thanks, I tried it out sending just 2 out of 3 and calculating the bitangent in the PS, but I don't see the avantages yet (maybe that's about taste), I might do it when I'm gonna use DXT5 compressed normal maps where I leave 1 channel out and calculate it through the other 2. I've read that this gives higher quality results, didn't see that yet.

you save memory by storing only tangent.

Ok, but on the other hand it costs performance to calculate it every run of the pixelshader smile.png

Probably an example of possible 'pre-optimization', untill I would do some profiling

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Ok, but on the other hand it costs performance to calculate it every run of the pixelshader smile.png

Probably an example of possible 'pre-optimization', untill I would do some profiling

that calculation won't slow down any modern GPU. Although if you have 100 models each with 10,000 vertices, then also it [bitangent] would only take 0.99 MB of space.

This topic is closed to new replies.

Advertisement