Correspondingly, the input layout also needs to be modified:
struct Vertex
{
XMFLOAT3 normal;
XMFLOAT4 color;
XMFLOAT2 uv;
XMFLOAT3 tangent;
};
To facilitate the transfer of the normal map's shader resource view to the GPU, we can record the index of the normal map in the descriptor header in the const buffer:
mInputLayout =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
{"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 1, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 1, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
{"TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 1, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}
};
The next step is to make changes at the GPU level. The original shader code needs to be modified. Firstly, the const buffer needs to add a normalIndex:
matConstants.normalMapIndex = object->mNormalTexture->mID;
Secondly, the vertex information passed to the vertex shader needs to be accompanied by a tangent:
struct MaterialData
{
float4 diffuseAlbedo;
float3 fresnelR0;
float shininess;
uint diffuseMapIndex;
uint normalIndex;
uint matPad0;
uint matPad1;
};
Finally, we will replace the place where normal was originally used directly with the information sampled from the normal map. It should be noted that the normal saved in the normal map is in TBN space and needs to be converted to world space:
struct VertexIn
{
float3 PosL : POSITION;
float3 NormalL : NORMAL;
float4 Color : COLOR;
float2 UV : TEXCOORD0;
float3 Tangent : TANGENT;
};
The final running effect is as follows:
.