Skip to content

Commit

Permalink
Feature: Normal Mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
InsaneZeroGame committed Aug 1, 2024
1 parent 270dfcf commit 0760ddd
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 44 deletions.
3 changes: 3 additions & 0 deletions engine/components.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ constexpr int ROOT_PARA_FRAME_SOURCE_TABLE = 1;//lights,clusters
constexpr int ROOT_PARA_COMPONENT_DATA = 2;
constexpr int ROOT_PARA_DIFFUSE_COLOR_TEXTURE = 3;
constexpr int ROOT_PARA_SHADOW_MAP = 4;
constexpr int ROOT_PARA_NORMAL_MAP_TEXTURE = 5;

namespace ECS
{
Expand Down Expand Up @@ -37,6 +38,8 @@ namespace ECS
bool mHasNormal;
bool mHasUV;
bool mAllByControlPoint;
bool mHasTangent;
bool mHasBitangent;
DirectX::SimpleMath::Vector3 Rotation;
DirectX::SimpleMath::Vector3 Scale;
DirectX::SimpleMath::Vector3 Translation;
Expand Down
72 changes: 72 additions & 0 deletions engine/fbx_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1918,6 +1918,12 @@ bool AssetLoader::FbxLoader::LoadStaticMesh(FbxMesh* pMesh) {
// If normal or UV is by polygon vertex, record all vertex attributes by polygon vertex.
newMesh.mHasNormal = pMesh->GetElementNormalCount() > 0;
newMesh.mHasUV = pMesh->GetElementUVCount() > 0;
if (newMesh.mHasUV)
{
pMesh->GenerateTangentsData(0);
}
newMesh.mHasTangent = pMesh->GetElementTangentCount() > 0;
newMesh.mHasBitangent = pMesh->GetElementBinormalCount() > 0;
FbxGeometryElement::EMappingMode lNormalMappingMode = FbxGeometryElement::eNone;
FbxGeometryElement::EMappingMode lUVMappingMode = FbxGeometryElement::eNone;
if (newMesh.mHasNormal) {
Expand Down Expand Up @@ -1966,6 +1972,9 @@ bool AssetLoader::FbxLoader::LoadStaticMesh(FbxMesh* pMesh) {
FbxVector4 lCurrentVertex;
FbxVector4 lCurrentNormal;
FbxVector2 lCurrentUV;
FbxVector4 lCurrentTangent;
FbxVector4 lCurrentBitangent;

if (newMesh.mAllByControlPoint) {
const FbxGeometryElementNormal* lNormalElement = NULL;
const FbxGeometryElementUV* lUVElement = NULL;
Expand Down Expand Up @@ -2005,6 +2014,8 @@ bool AssetLoader::FbxLoader::LoadStaticMesh(FbxMesh* pMesh) {
newMesh.mVertices[lIndex].textureCoord[0] = static_cast<float>(lCurrentUV[0]);
newMesh.mVertices[lIndex].textureCoord[1] = static_cast<float>(lCurrentUV[1]);
}


}
}

Expand Down Expand Up @@ -2049,6 +2060,67 @@ bool AssetLoader::FbxLoader::LoadStaticMesh(FbxMesh* pMesh) {
newMesh.mVertices[lVertexCount].textureCoord[0] = static_cast<float>(lCurrentUV[0]);
newMesh.mVertices[lVertexCount].textureCoord[1] = static_cast<float>(lCurrentUV[1]);
}
if (newMesh.mHasTangent)
{
FbxGeometryElementTangent* leTangent = pMesh->GetElementTangent();

if (leTangent->GetMappingMode() == FbxGeometryElement::eByPolygonVertex)
{
FbxVector4 tangnet;
switch (leTangent->GetReferenceMode())
{
case FbxGeometryElement::eDirect:
tangnet = leTangent->GetDirectArray().GetAt(lVertexCount);
newMesh.mVertices[lVertexCount].tangent[0] = tangnet[0];
newMesh.mVertices[lVertexCount].tangent[1] = tangnet[1];
newMesh.mVertices[lVertexCount].tangent[2] = tangnet[2];
break;
case FbxGeometryElement::eIndexToDirect:
{
int id = leTangent->GetIndexArray().GetAt(lVertexCount);
tangnet = leTangent->GetDirectArray().GetAt(id);
newMesh.mVertices[lVertexCount].tangent[0] = tangnet[0];
newMesh.mVertices[lVertexCount].tangent[1] = tangnet[1];
newMesh.mVertices[lVertexCount].tangent[2] = tangnet[2];
break;
}
break;
default:
break; // other reference modes not shown here!
}
}

}

if (newMesh.mHasBitangent)
{
FbxGeometryElementBinormal* leBinormal = pMesh->GetElementBinormal();

if (leBinormal->GetMappingMode() == FbxGeometryElement::eByPolygonVertex)
{
FbxVector4 Bitangent;
switch (leBinormal->GetReferenceMode())
{
case FbxGeometryElement::eDirect:
Bitangent = leBinormal->GetDirectArray().GetAt(lVertexCount);
newMesh.mVertices[lVertexCount].bitangent[0] = Bitangent[0];
newMesh.mVertices[lVertexCount].bitangent[1] = Bitangent[1];
newMesh.mVertices[lVertexCount].bitangent[2] = Bitangent[2];
break;
case FbxGeometryElement::eIndexToDirect:
{
int id = leBinormal->GetIndexArray().GetAt(lVertexCount);
Bitangent = leBinormal->GetDirectArray().GetAt(id);
newMesh.mVertices[lVertexCount].bitangent[0] = Bitangent[0];
newMesh.mVertices[lVertexCount].bitangent[1] = Bitangent[1];
newMesh.mVertices[lVertexCount].bitangent[2] = Bitangent[2];
}
break;
default:
break; // other reference modes not shown here!
}
}
}
}
}
++lVertexCount;
Expand Down
4 changes: 3 additions & 1 deletion engine/graphics_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ namespace Renderer
struct Vertex
{
std::array<float, 4> pos;
std::array<float, 4> normal;
std::array<float, 3> normal;
std::array<float, 3> tangent;
std::array<float, 3> bitangent;
std::array<float, 2> textureCoord;
};

Expand Down
1 change: 0 additions & 1 deletion engine/obj_model_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ std::vector<ECS::StaticMesh>& AssetLoader::ObjModelLoader::LoadAssetFromFile(std
vertex.normal[0] = attrib.normals[3 * idx.normal_index + 0];
vertex.normal[1] = attrib.normals[3 * idx.normal_index + 1];
vertex.normal[2] = attrib.normals[3 * idx.normal_index + 2];
vertex.normal[3] = 1.0f;
//vertex.color[0] = diffuse[0];
//vertex.color[1] = diffuse[1];
//vertex.color[2] = diffuse[2];
Expand Down
57 changes: 35 additions & 22 deletions renderer/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,14 +239,7 @@ void Renderer::BaseRenderer::CreateRenderTask()
renderEntities.each([=](auto entity, auto& renderComponent, auto& transformComponent) {
auto modelMatrix = transformComponent.GetModelMatrix();

//if (mTextureMap.find(renderComponent.NormalMap) == mTextureMap.end())
//{
// mGraphicsCmd->SetGraphicsRootDescriptorTable(6, mTextureMap["defaultNormal"]->GetSRVGpu());
//}
//else
//{
// mGraphicsCmd->SetGraphicsRootDescriptorTable(6, mTextureMap[renderComponent.NormalMap]->GetSRVGpu());
//}

OjbectData objData = {};
objData.ModelMatrix = modelMatrix;
objData.DiffuseColor = renderComponent.mBaseColor;
Expand All @@ -255,7 +248,8 @@ void Renderer::BaseRenderer::CreateRenderTask()
//Render
for (const auto& [matid,subMesh] : renderComponent.mSubMeshes)
{
auto subMeshTextureName = renderComponent.mMatTextureName[matid];
auto subMeshTextureName = renderComponent.mMatBaseColorName[matid];
auto subMeshNormalMapName = renderComponent.mMatNormalMapName[matid];

if (mTextureMap.find(subMeshTextureName) == mTextureMap.end())
{
Expand All @@ -266,6 +260,15 @@ void Renderer::BaseRenderer::CreateRenderTask()
mGraphicsCmd->SetGraphicsRootDescriptorTable(ROOT_PARA_DIFFUSE_COLOR_TEXTURE, mTextureMap[subMeshTextureName]->GetSRVGpu());
}

if (mTextureMap.find(subMeshNormalMapName) == mTextureMap.end())
{
mGraphicsCmd->SetGraphicsRootDescriptorTable(ROOT_PARA_NORMAL_MAP_TEXTURE, mTextureMap["defaultNormal"]->GetSRVGpu());
}
else
{
mGraphicsCmd->SetGraphicsRootDescriptorTable(ROOT_PARA_NORMAL_MAP_TEXTURE, mTextureMap[subMeshNormalMapName]->GetSRVGpu());
}

mGraphicsCmd->DrawIndexedInstanced((UINT)subMesh.TriangleCount * 3, 1, renderComponent.StartIndexLocation + subMesh.IndexOffset,
renderComponent.BaseVertexLocation, 0);
}
Expand Down Expand Up @@ -721,8 +724,10 @@ void Renderer::BaseRenderer::CreatePipelineState()
std::vector<D3D12_INPUT_ELEMENT_DESC> elements =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 16, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 28, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "BINORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 40, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 52, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }

};
lDesc.InputLayout.NumElements = static_cast<UINT>(elements.size());
Expand Down Expand Up @@ -832,23 +837,16 @@ void Renderer::BaseRenderer::CreateRootSignature()
diffuseRange.RegisterSpace = 0;
diffuseRange.OffsetInDescriptorsFromTableStart = 0;

D3D12_DESCRIPTOR_RANGE normalRange = {};
normalRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
normalRange.NumDescriptors = 1;
normalRange.BaseShaderRegister = 6;
normalRange.RegisterSpace = 0;
normalRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;

D3D12_DESCRIPTOR_RANGE roughnessRange = {};
roughnessRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
roughnessRange.NumDescriptors = 1;
roughnessRange.BaseShaderRegister = 7;
roughnessRange.RegisterSpace = 0;
roughnessRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;

std::vector<D3D12_DESCRIPTOR_RANGE> ranges = { diffuseRange,normalRange,roughnessRange };
diffuseColorTexture.DescriptorTable.NumDescriptorRanges = (UINT)ranges.size();
diffuseColorTexture.DescriptorTable.pDescriptorRanges = ranges.data();
std::vector<D3D12_DESCRIPTOR_RANGE> diffuseRanges = { diffuseRange,roughnessRange };
diffuseColorTexture.DescriptorTable.NumDescriptorRanges = (UINT)diffuseRanges.size();
diffuseColorTexture.DescriptorTable.pDescriptorRanges = diffuseRanges.data();
diffuseColorTexture.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;

D3D12_ROOT_PARAMETER shadowMap = {};
Expand All @@ -864,13 +862,28 @@ void Renderer::BaseRenderer::CreateRootSignature()
shadowMap.DescriptorTable.pDescriptorRanges = shadowmapranges.data();
shadowMap.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;

D3D12_ROOT_PARAMETER normalMapTexture = {};
normalMapTexture.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
D3D12_DESCRIPTOR_RANGE normalRange = {};
normalRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
normalRange.NumDescriptors = 1;
normalRange.BaseShaderRegister = 6;
normalRange.RegisterSpace = 0;
normalRange.OffsetInDescriptorsFromTableStart = 0;
std::vector<D3D12_DESCRIPTOR_RANGE> normalMapRanges = { normalRange };
normalMapTexture.DescriptorTable.NumDescriptorRanges = (UINT)normalMapRanges.size();
normalMapTexture.DescriptorTable.pDescriptorRanges = normalMapRanges.data();
normalMapTexture.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;


std::vector<D3D12_ROOT_PARAMETER> parameters =
{
frameDataCBV,//0
frameResourceTable,//1
componentData,//2
diffuseColorTexture,//3
shadowMap//4
shadowMap,//4,
normalMapTexture,
};

//Samplers
Expand Down
10 changes: 8 additions & 2 deletions renderer/shaders/ForwardPS.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,19 @@ float4 main(PSInput input) : SV_TARGET
return (diffuse + ambient) * colorAfterCorrection;
#else
float2 uvCoordFlip = float2(input.UVCoord.x, 1.0 - input.UVCoord.y);
float2 normalPacked = normalTexture.Sample(defaultSampler, uvCoordFlip).xy * 2.0f - 1.0f;
float normal_z = sqrt(1.0f - normalPacked.x * normalPacked.x - normalPacked.y * normalPacked.y);
float3 normal_normalized = normalize(float3(normalPacked.x, normalPacked.y, normal_z));
float3x3 tbn = float3x3(normalize(input.tangent), normalize(input.bitangent), normalize(input.normal));
float3 normalWS = normalize(mul(normal_normalized, tbn));
float3 normalVS = mul(float4(normalWS, 0.0f), frameData.ViewMatrix);
float4 diffuseColor = defaultTexture.Sample(defaultSampler, uvCoordFlip);
//float4 diffuseColor = float4(input.color);
float4 DirLightViewSpace = mul(float4(input.DirectionalLightDir.xyz, 0.0), frameData.ViewMatrix);
float3 directionalLight = ApplyLightCommon(
diffuseColor.xyz,
diffuseColor.xyz,
0, 0, input.normalViewSpace.xyz, input.viewsSpacePos,
0, 0, normalVS, input.viewsSpacePos,
DirLightViewSpace, input.DirectionalLightColor) * frameData.DirectionalLightDir.w;
//return float4(directionalLight, 1.0f);
float3 pointLight = float3(0.0,0.0,0.0);
Expand All @@ -163,7 +169,7 @@ float4 main(PSInput input) : SV_TARGET
pointLight += ApplyPointLight(
diffuseColor.xyz,
diffuseColor.xyz,
0, 0, input.normalViewSpace.xyz,
0, 0, normalVS,
input.viewsSpacePos.xyz,
input.viewsSpacePos.xyz,
lightViewSpace.xyz,
Expand Down
28 changes: 15 additions & 13 deletions renderer/shaders/ForwardVS.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@
ConstantBuffer<FrameData> frameData : register(b0);
ConstantBuffer<ObjectData> objData : register(b4);

PSInput main(float4 pos : POSITION,float4 normal : NORMAL,float2 textureCoord:TEXCOORD)
PSInput main(VSInput vsInput)
{
PSInput input;
float4 modelSpacePos = mul(pos, objData.ModelMatrix);
input.position = mul(modelSpacePos, frameData.ViewPrj);
input.viewsSpacePos = mul(modelSpacePos, frameData.View);
input.normalViewSpace = mul(float4(normal.xyz, 0.0), frameData.NormalMatrix);
input.UVCoord = textureCoord;
input.color = float4(objData.DiffuseColor, 1.0f);
input.normal = normal.xyz;
input.DirectionalLightDir = frameData.DirectionalLightDir.xyz;
input.DirectionalLightColor = frameData.DirectionalLightColor.xyz;
input.shadowCoord = mul(modelSpacePos, frameData.ShadowViewPrjMatrix);
return input;
PSInput psInput;
float4 modelSpacePos = mul(vsInput.pos, objData.ModelMatrix);
psInput.position = mul(modelSpacePos, frameData.ViewPrj);
psInput.viewsSpacePos = mul(modelSpacePos, frameData.View);
psInput.normalViewSpace = mul(float4(vsInput.normal.xyz, 0.0), frameData.NormalMatrix);
psInput.UVCoord = vsInput.textureCoord;
psInput.color = float4(objData.DiffuseColor, 1.0f);
psInput.normal = vsInput.normal.xyz;
psInput.DirectionalLightDir = frameData.DirectionalLightDir.xyz;
psInput.DirectionalLightColor = frameData.DirectionalLightColor.xyz;
psInput.shadowCoord = mul(modelSpacePos, frameData.ShadowViewPrjMatrix);
psInput.tangent = vsInput.tangent;
psInput.bitangent = vsInput.bitangent;
return psInput;
}
6 changes: 3 additions & 3 deletions renderer/shaders/SkyboxVS.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

ConstantBuffer<FrameData> frameData : register(b0);

SkyBoxPsInput main(float4 pos : POSITION, float4 normal : NORMAL, float2 textureCoord : TEXCOORD)
SkyBoxPsInput main(VSInput vsInput)
{
SkyBoxPsInput output;
float4x4 viewMatrixWithOutTranslation = frameData.View;
viewMatrixWithOutTranslation._14_24_34_44 = float4(0.0, 0.0, 0.0, 1.0);
viewMatrixWithOutTranslation._41_42_43_44 = float4(0.0, 0.0, 0.0, 1.0);
output.pos = mul(mul(pos, viewMatrixWithOutTranslation), frameData.Prj);
output.texcoord = pos.xyz;
output.pos = mul(mul(vsInput.pos, viewMatrixWithOutTranslation), frameData.Prj);
output.texcoord = vsInput.pos.xyz;
return output;
}
11 changes: 11 additions & 0 deletions renderer/shaders/shader_common.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ struct PSInput
float4 position : SV_POSITION;
float4 color : COLOR0;
float3 normal : NORMAL0;
float3 tangent : TANGNET0;
float3 bitangent : BITANGNET0;
float4 normalViewSpace : NORMAL1;
float3 DirectionalLightDir : COLOR1;
float3 DirectionalLightColor : COLOR2;
Expand All @@ -11,6 +13,15 @@ struct PSInput
float4 shadowCoord : POSITION0;
};

struct VSInput
{
float4 pos : POSITION;
float3 normal : NORMAL;
float3 tangent : TANGENT0;
float3 bitangent : BINORMAL0;
float2 textureCoord : TEXCOORD;
};


struct Light
{
Expand Down
6 changes: 4 additions & 2 deletions renderer/skybox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ void Renderer::Skybox::CreatePipelineState()
std::vector<D3D12_INPUT_ELEMENT_DESC> elements =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 16, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 28, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "BINORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 40, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 52, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }

};
lDesc.InputLayout.NumElements = static_cast<UINT>(elements.size());
Expand Down

0 comments on commit 0760ddd

Please sign in to comment.