1

So I've been working on a Directx11/hlsl rendering engine with the goal of creating a realistic planet which you can view from both on the surface and also at a planetary level. The planet is a normalized cube, which is procedurally generated using noise and as you move closer to the surface of the planet, a binary-based triangle tree splits until the desired detail level is reached. I got vertex normal calculations to work correctly, and I recently started trying to implement normal mapping for my terrain textures, and I have gotten something that seems to work for the most part. However, when the sun is pointing almost perpendicular to the ground (90 degrees), it is way more lit up

than it should be.

However, from the opposite angle (270 degrees), I am getting something that seems more manageable, but may as well be just as off.

The debug lines that are being rendered are the normal, tangent, and bitangents (which all appear to be correct and fit the topology of the terrain)

Here is my shader code:

Vertex shader:

PSIn mainvs(VSIn input)
{
PSIn output;

output.WorldPos = mul(float4(input.Position, 1.f), Instances[input.InstanceID].WorldMatrix); // pass pixel world position as opposed to screen space position for lighitng calculations
output.Position = mul(output.WorldPos, CameraViewProjectionMatrix);
output.TexCoord = input.TexCoord;
output.CameraPos = CameraPosition;

output.Normal = normalize(mul(input.Normal, (float3x3)Instances[input.InstanceID].WorldMatrix));
float3 Tangent = normalize(mul(input.Tangent, (float3x3)Instances[input.InstanceID].WorldMatrix));
float3 Bitangent = normalize(cross(output.Normal, Tangent));

output.TBN = transpose(float3x3(Tangent, Bitangent, output.Normal));

return output;
}

Pixel shader (Texcoord scalar is for smaller textures closer to planet surface):

float3 FetchNormalVector(float2 TexCoord)
{
    float3 Color = NormalTex.Sample(Samp, TexCoord * TexcoordScalar);
    Color *= 2.f;
    return normalize(float3(Color.x - 1.f, Color.y - 1.f, Color.z - 1.f));
}

float3 LightVector = -SunDirection;
float3 TexNormal = FetchNormalVector(input.TexCoord);
float3 WorldNormal = normalize(mul(input.TBN, TexNormal));
float nDotL = max(0.0, dot(WorldNormal, LightVector));
float4 SampleColor = float4(1.f, 1.f, 1.f, 1.f);
SampleColor *= nDotL;

return float4(SampleColor.xyz, 1.f);

Thanks in advance, and let me know if you have any insight as to what could be the issue here.

Edit 1: I tried it with a fixed blue value instead of sampling from the normal texture, which gives me the correct and same results as if I had not applied mapping (as expected). Still don't have a lead on what would be causing this issue.

Edit 2: I just noticed the strangest thing. At 0, 0, +Z, there are these hard seams that only appear with normal mapping enabled enter image description here It's a little hard to see, but it seems almost like there are multiple tangents associated to the same vertex (since I'm not using indexing yet) because the debug lines appear to split on the seams. Here is my code that I'm using to generate the tangents (bitangents are calculated in the vertex shader using cross(Normal, Tangent))

v3& p0 = Chunk.Vertices[0].Position;
v3& p1 = Chunk.Vertices[1].Position;
v3& p2 = Chunk.Vertices[2].Position;

v2& uv0 = Chunk.Vertices[0].UV;
v2& uv1 = Chunk.Vertices[1].UV;
v2& uv2 = Chunk.Vertices[2].UV;

v3 deltaPos1 = p1 - p0;
v3 deltaPos2 = p2 - p0;

v2 deltaUV1 = uv1 - uv0;
v2 deltaUV2 = uv2 - uv0;

f32 r = 1.f / (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x);
v3 Tangent = (deltaPos1 * deltaUV2.y - deltaPos2 * deltaUV1.y) * r;

Chunk.Vertices[0].Tangent = Normalize(Tangent - (Chunk.Vertices[0].Normal * DotProduct(Chunk.Vertices[0].Normal, Tangent)));
Chunk.Vertices[1].Tangent = Normalize(Tangent - (Chunk.Vertices[1].Normal * DotProduct(Chunk.Vertices[1].Normal, Tangent)));
Chunk.Vertices[2].Tangent = Normalize(Tangent - (Chunk.Vertices[2].Normal * DotProduct(Chunk.Vertices[2].Normal, Tangent)));

Also for reference, this is the main article I was looking at while implementing all of this: link

Edit 3: Here is an image of the planet from a distance with normal mapping enabled: enter image description here

And one from the same angle without: enter image description here

  • Might not be related to your issue, but you should transform your vertex normal with the transposed inverse world matrix instead of the regular world matrix, otherwise vertex normals will not behave properly with non-uniform scaling. – Bizzarrus Aug 30 '20 at 14:29
  • Thanks @Bizzarrus, I just implemented your advice. Unfortunately, the only transformations currently applied to the sphere vertices are scale, which get normalized out during processing. – TheApplePieGod Aug 30 '20 at 15:34

0 Answers0