What I have is a planet, for this planet I have a height map and normal map. What I'm trying to achieve is to map the normal around the sphere that consist of my planet. I've read up on TBN matrix and how to calculate it. Everything I'm explaining in this post takes place in the domain shader.
I know that the normal is correct, since I get some shadow from the light on it but it looks weird since it 2D in 3D world if you know what I mean.
I will split up the shader code first and then post it all in the end.
First I take 3 points on my height map:
heightMapCoord1 = uvwCoord.x * patch[0].heightMapCoord + uvwCoord.y * patch[1].heightMapCoord + uvwCoord.z * patch[2].heightMapCoord;
heightMapCoord2.x = ((heightMapCoord1.x * 46080.0f) + 1.0f) / 46080.0f;
heightMapCoord2.y = heightMapCoord1.y;
heightMapCoord3.x = heightMapCoord1.x;
heightMapCoord3.y = ((heightMapCoord1.y * 22528.0f) + 1.0f) / 22528.0f;
I then sample the height map to get 3 different Z values for my future vectors: heightMapSample1 = heightMapTexture.SampleLevel(sampleType, heightMapCoord1, 0);
heightMapSample2 = heightMapTexture.SampleLevel(sampleType, heightMapCoord2, 0);
heightMapSample3 = heightMapTexture.SampleLevel(sampleType, heightMapCoord3, 0);
The next step is to create the 3 different vectors normalMappingVector1 = float3(heightMapCoord1.x, heightMapCoord1.y, heightMapSample1);
normalMappingVector2 = float3(heightMapCoord2.x, heightMapCoord2.y, heightMapSample2);
normalMappingVector3 = float3(heightMapCoord3.x, heightMapCoord3.y, heightMapSample2);
I then create cross the vectors between vector 2-1 and 3-1 normalMappingNormal = normalize(cross((normalMappingVector2 - normalMappingVector1), (normalMappingVector3 - normalMappingVector1)));
These code that follows is to calculate the tangent coef = 1 / ((heightMapCoord2.x * heightMapCoord3.y) - (heightMapCoord3.x * heightMapCoord2.y));
normalMappingTangent.x = coef * ((normalMappingVector2.x * heightMapCoord3.y) + (normalMappingVector3.x * -heightMapCoord2.y));
normalMappingTangent.y = coef * ((normalMappingVector2.y * heightMapCoord3.y) + (normalMappingVector3.y * -heightMapCoord2.y));
normalMappingTangent.z = coef * ((normalMappingVector2.z * heightMapCoord3.y) + (normalMappingVector3.z * -heightMapCoord2.y));
Normalize it and calculate the Bi-tangent normalMappingTangent = normalize(normalMappingTangent);
normalMappingBiTangent = normalize(cross(normalMappingNormal, normalMappingTangent));
I then use all the 3 vectors I have gotten and combining them to a Matrix and then mul my Normal(this normal is taken from the normal map and not calculated) float3x3 TBN = float3x3(normalMappingTangent, normalMappingBiTangent, normalMappingNormal);
normal = mul(TBN, normal);
Here is the full shader codeTexture2D<float> heightMapTexture;
Texture2D colorMapTexture;
Texture2D normalMapTexture;
SamplerState sampleType;
SamplerState colorSampleType;
SamplerState normalSampleType;
cbuffer MatrixBuffer
{
matrix worldMatrix;
matrix viewMatrix;
matrix projectionMatrix;
};
cbuffer LightBuffer
{
float4 diffuseColor;
float3 lightDirection;
float padding;
};
struct ConstantOutputType
{
float edges[3] : SV_TessFactor;
float inside : SV_InsideTessFactor;
};
struct HullOutputType
{
float3 position : POSITION;
float4 color : COLOR;
float3 sphereNormal : NORMAL;
float2 heightMapCoord : TEXCOORD0;
float2 colorMapCoord : TEXCOORD1;
};
struct PixelInputType
{
float4 position : SV_POSITION;
float4 color : COLOR;
};
[domain("tri")]
PixelInputType PlanetDomainShader(ConstantOutputType input, float3 uvwCoord : SV_DomainLocation, const OutputPatch<HullOutputType, 3> patch)
{
float3 vertexPosition;
float3 sphereNormal;
float2 heightMapCoord1;
float2 heightMapCoord2;
float2 heightMapCoord3;
float2 colorMapCoord;
PixelInputType output;
float heightMapSample1;
float heightMapSample2;
float heightMapSample3;
float4 colorMapSample;
float3 normalMapSample;
float3 sunLightDir;
float sunLightIntensity;
float4 sunLightColor;
float3 normalMappingVector1;
float3 normalMappingVector2;
float3 normalMappingVector3;
float3 normalMappingNormal;
float coef;
float3 normalMappingTangent;
float3 normalMappingBiTangent;
float3 normal;
sunLightDir = -lightDirection;
heightMapCoord1 = uvwCoord.x * patch[0].heightMapCoord + uvwCoord.y * patch[1].heightMapCoord + uvwCoord.z * patch[2].heightMapCoord;
heightMapCoord2.x = ((heightMapCoord1.x * 46080.0f) + 1.0f) / 46080.0f;
heightMapCoord2.y = heightMapCoord1.y;
heightMapCoord3.x = heightMapCoord1.x;
heightMapCoord3.y = ((heightMapCoord1.y * 22528.0f) + 1.0f) / 22528.0f;
colorMapCoord = uvwCoord.x * patch[0].colorMapCoord + uvwCoord.y * patch[1].colorMapCoord + uvwCoord.z * patch[2].colorMapCoord;
vertexPosition = uvwCoord.x * patch[0].position + uvwCoord.y * patch[1].position + uvwCoord.z * patch[2].position;
sphereNormal = uvwCoord.x * patch[0].sphereNormal + uvwCoord.y * patch[1].sphereNormal + uvwCoord.z * patch[2].sphereNormal;
heightMapSample1 = heightMapTexture.SampleLevel(sampleType, heightMapCoord1, 0);
heightMapSample2 = heightMapTexture.SampleLevel(sampleType, heightMapCoord2, 0);
heightMapSample3 = heightMapTexture.SampleLevel(sampleType, heightMapCoord3, 0);
colorMapSample = colorMapTexture.SampleLevel(colorSampleType, colorMapCoord, 0);
normalMapSample = normalMapTexture.SampleLevel(normalSampleType, heightMapCoord1, 0).rgb;
normal.x = (normalMapSample.r * 2) - 1;
normal.y = (normalMapSample.g * 2) - 1;
normal.b = (normalMapSample.b * 2) - 1;
normalMappingVector1 = float3(heightMapCoord1.x, heightMapCoord1.y, heightMapSample1);
normalMappingVector2 = float3(heightMapCoord2.x, heightMapCoord2.y, heightMapSample2);
normalMappingVector3 = float3(heightMapCoord3.x, heightMapCoord3.y, heightMapSample2);
normalMappingNormal = normalize(cross((normalMappingVector2 - normalMappingVector1), (normalMappingVector3 - normalMappingVector1)));
coef = 1 / ((heightMapCoord2.x * heightMapCoord3.y) - (heightMapCoord3.x * heightMapCoord2.y));
normalMappingTangent.x = coef * ((normalMappingVector2.x * heightMapCoord3.y) + (normalMappingVector3.x * -heightMapCoord2.y));
normalMappingTangent.y = coef * ((normalMappingVector2.y * heightMapCoord3.y) + (normalMappingVector3.y * -heightMapCoord2.y));
normalMappingTangent.z = coef * ((normalMappingVector2.z * heightMapCoord3.y) + (normalMappingVector3.z * -heightMapCoord2.y));
normalMappingTangent = normalize(normalMappingTangent);
normalMappingBiTangent = normalize(cross(normalMappingNormal, normalMappingTangent));
vertexPosition.x = vertexPosition.x + (sphereNormal.x * ((heightMapSample1 * 29429.0f) - 8200.0f));
vertexPosition.y = vertexPosition.y + (sphereNormal.y * ((heightMapSample1 * 29429.0f) - 8200.0f));
vertexPosition.z = vertexPosition.z + (sphereNormal.z * ((heightMapSample1 * 29429.0f) - 8200.0f));
output.position = mul(float4(vertexPosition, 1.0f), worldMatrix);
output.position = mul(output.position, viewMatrix);
output.position = mul(output.position, projectionMatrix);
float3x3 TBN = float3x3(normalMappingTangent, normalMappingBiTangent, normalMappingNormal);
TBN = transpose(TBN);
normal = mul(TBN, normalMappingNormal);
sunLightIntensity = saturate(dot(normal, sunLightDir));
sunLightColor = saturate(diffuseColor * sunLightIntensity);
output.color = sunLightColor * colorMapSample;
return output;
}
I hope anyone can recognize what I'm trying to do here. I've read on many sites that precalculating the normal, tangent and bitangent is easier on the GPU but I'mdeadset on getting this to work.
Worth noting is that I have taken this code from http://www.fabiensanglard.net/bumpMapping/index.php, and then trying to combine it with other things I've read:
generateNormalAndTangent(float3 v1, float3 v2, text2 st1, text2 st2)
{
float3 normal = v1.crossProduct(v2);
float coef = 1/ (st1.u * st2.v - st2.u * st1.v);
float3 tangent;
tangent.x = coef * ((v1.x * st2.v) + (v2.x * -st1.v));
tangent.y = coef * ((v1.y * st2.v) + (v2.y * -st1.v));
tangent.z = coef * ((v1.z * st2.v) + (v2.z * -st1.v));
float3 binormal = normal.crossProduct(tangent);
}
Thanks in advanceToastmastern