Skip to content

Commit 66a1e4d

Browse files
committed
Lazy "PBR" Implementation
1 parent bcd021b commit 66a1e4d

File tree

9 files changed

+184
-25
lines changed

9 files changed

+184
-25
lines changed

src/Shader/GBufferPass.hlsl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ struct VertexOutput
1515

1616
SamplerState texSampler : register(s0);
1717
Texture2D tex : register(t0);
18-
Texture2D metalRough : register(t1);
18+
Texture2D ormTex : register(t1);
1919

2020
VertexOutput VertexMain(float4 position : POSITION, float4 normal : NORMAL, float2 uv : TEXCOORD)
2121
{
@@ -47,6 +47,7 @@ PixelOutput PixelMain(VertexOutput input)
4747
PixelOutput output;
4848
output.albedo = tex.Sample(texSampler, uvFlipped);
4949
output.normal = input.normal * 0.5f + 0.5f;
50+
output.orm = ormTex.Sample(texSampler, uvFlipped);
5051
output.position = input.vertexPos;
5152
return output;
5253
}

src/Shader/LightPass.hlsl

Lines changed: 95 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
#define PI 3.14159265359
2+
cbuffer ScreenQuadBuffer : register(b0)
3+
{
4+
float3 cameraPos;
5+
}
6+
17
struct VertexOutput
28
{
39
float4 position : SV_Position;
@@ -13,28 +19,109 @@ VertexOutput VertexMain(float4 position : POSITION0, float2 uv : TEXCOORD0)
1319
Texture2DMS<float4> albedo : register(t0);
1420
Texture2DMS<float4> normal : register(t1);
1521
Texture2DMS<float4> position : register(t2);
22+
Texture2DMS<float4> orm : register(t3);
1623

1724
struct PixelOutput
1825
{
1926
float4 screen : SV_Target0;
2027
};
2128

29+
float3 FresnelShlick(float cosTheta, float3 F0)
30+
{
31+
return F0 + (1.f - F0) * pow(saturate(1.f - cosTheta), 5.f);
32+
}
33+
34+
float DistributionGGX(float3 N, float3 H, float roughness)
35+
{
36+
float a = roughness * roughness;
37+
float a2 = a * a;
38+
float NdotH = max(dot(N, H), 0.0);
39+
float NdotH2 = NdotH * NdotH;
40+
41+
float num = a2;
42+
float denom = (NdotH * (a2 - 1.f) + 1.f);
43+
denom = PI * denom * denom;
44+
45+
return num / denom;
46+
}
47+
48+
float GeometrySchlickGGX(float NdotV, float roughness)
49+
{
50+
float r = (roughness + 1.f);
51+
float k = (r * r) / 8.f;
52+
53+
float num = NdotV;
54+
float denom = NdotV * (1.f - k) + k;
55+
56+
return num / denom;
57+
}
58+
59+
float GeometrySmith(float3 N, float3 V, float3 L, float roughness)
60+
{
61+
float NdotV = max(dot(N, V), 0.f);
62+
float NdotL = max(dot(N, L), 0.f);
63+
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
64+
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
65+
66+
return ggx1 * ggx2;
67+
}
68+
2269
PixelOutput PixelMain(VertexOutput input, uint index : SV_SampleIndex)
2370
{
24-
PixelOutput output;
71+
float3 lightPos = float3(0.f, 5.f, 5.f);
72+
float3 lightColor = float3(100.f, 100.f, 100.f);
73+
2574
float4 albedoColor = albedo.Load(input.position.xy, index);
2675
float4 nml = normalize(normal.Load(input.position.xy, index) * 2 - 1);
2776
float4 vertexPos = position.Load(input.position.xy, index);
2877

29-
float4 ambientColor = float4(0.1f, 0.1f, 0.1f, 1.f);
30-
float4 lightPos = float4(0.f, 200.f, 200.f, 1.f);
31-
float4 lightColor = float4(1.f, 1.f, 1.f, 1.f);
78+
/* ORM G-Buffer */
79+
float3 ormData = orm.Load(input.position.xy, index).rgb;
80+
float ao = ormData.r;
81+
float roughness = ormData.g;
82+
float metallic = ormData.b;
83+
84+
85+
float3 N = nml.xyz;
86+
float3 V = normalize(cameraPos - vertexPos.xyz);
87+
float3 F0 = float3(.04f, .04f, .04f);
88+
F0 = lerp(F0, albedoColor.xyz, metallic);
89+
90+
/* Reflectance equation */
91+
float3 Lo = float3(0.f, 0.f, 0.f);
3292

33-
float3 lightDir = normalize(lightPos.xyz - vertexPos.xyz);
34-
float LdotN = saturate(dot(lightDir, nml.xyz));
93+
/* Calculate light radiance */
94+
float3 L = normalize(lightPos - vertexPos.xyz);
95+
float3 H = normalize(V + L);
96+
float distance = length(lightPos - vertexPos.xyz);
97+
float attenuation = 1.0f / (distance * distance + 1.f);
98+
float3 radiance = lightColor * attenuation;
99+
radiance *= (1.0 + metallic * 0.2);
35100

36-
float4 outputColor = saturate(saturate(LdotN + ambientColor) * lightColor) * albedoColor;
101+
/* Cook torrance BRDF */
102+
float NDF = DistributionGGX(N, H, roughness);
103+
float G = GeometrySmith(N, V, L, roughness);
104+
float3 F = FresnelShlick(saturate(dot(H, V)), F0);
105+
106+
float3 kS = F;
107+
float3 kD = (1.0 - kS) * (1.0 - metallic);;
108+
kD *= 1.f - metallic;
109+
110+
float3 numerator = NDF * G * F;
111+
float denominator = 4.f * max(dot(N, V), 0.f) * max(dot(N, L), 0.f) + 0.0001f;
112+
float3 specular = numerator / denominator;
113+
114+
float NdotL = max(dot(N, L), 0.f);
115+
116+
Lo += (kD * albedoColor.xyz / PI + specular) * radiance * NdotL;
117+
118+
float3 ambient = float3(0.3f, 0.3f, 0.3f) * albedoColor.xyz * ao;
119+
ambient = lerp(ambient, albedoColor.xyz * ao * 0.2, metallic); // Los metales reflejan más el ambiente
120+
121+
float3 color = ambient + Lo;
122+
123+
PixelOutput output;
37124

38-
output.screen = outputColor;
125+
output.screen = float4(color.x, color.y, color.z, 1.f);
39126
return output;
40127
}

src/private/Core/Core.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ void Core::Init() {
1818

1919
this->m_renderer = new D3D12();
2020
m_renderer->Init(this->m_hwnd);
21-
m_sceneManager->Init();
2221
this->m_resMgr = ResourceManager::GetInstance();
2322
this->m_resMgr->Init();
2423
}

src/private/Core/GameObject/Component/Mesh.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include "Core/Scene/SceneManager.h"
66

77

8-
Mesh::Mesh(std::string name, Transform& parentTransform) : Component::Component(name) {
8+
Mesh::Mesh(std::string name, Transform* parentTransform) : Component::Component(name) {
99
this->m_core = Core::GetInstance();
1010
this->m_sceneMgr = SceneManager::GetInstance();
1111

@@ -26,10 +26,10 @@ Mesh::Mesh(std::string name, Transform& parentTransform) : Component::Component(
2626
UINT nWidth, nHeight = 0;
2727
this->m_core->GetWindowSize(nWidth, nHeight);
2828

29-
this->m_wvp.World = XMMatrixTranspose(XMMatrixIdentity() * XMMatrixTranslation(this->m_transform.location.x, this->m_transform.location.y, this->m_transform.location.z));
30-
this->m_wvp.World *= XMMatrixTranspose(XMMatrixRotationX(XMConvertToRadians(this->m_transform.rotation.x)));
31-
this->m_wvp.World *= XMMatrixTranspose(XMMatrixRotationY(XMConvertToRadians(this->m_transform.rotation.y)));
32-
this->m_wvp.World *= XMMatrixTranspose(XMMatrixRotationZ(XMConvertToRadians(this->m_transform.rotation.z)));
29+
this->m_wvp.World = XMMatrixTranspose(XMMatrixIdentity() * XMMatrixTranslation(this->m_transform->location.x, this->m_transform->location.y, this->m_transform->location.z));
30+
this->m_wvp.World *= XMMatrixTranspose(XMMatrixRotationX(XMConvertToRadians(this->m_transform->rotation.x)));
31+
this->m_wvp.World *= XMMatrixTranspose(XMMatrixRotationY(XMConvertToRadians(this->m_transform->rotation.y)));
32+
this->m_wvp.World *= XMMatrixTranspose(XMMatrixRotationZ(XMConvertToRadians(this->m_transform->rotation.z)));
3333

3434
this->m_wvp.View = XMMatrixTranspose(XMMatrixIdentity());
3535
this->m_wvp.Projection = XMMatrixTranspose(XMMatrixPerspectiveFovRH(XMConvertToRadians(70.f), static_cast<float>(nWidth) / static_cast<float>(nHeight), 0.01f, 3000.f));
@@ -122,13 +122,13 @@ void Mesh::InitConstantBuffer() {
122122
void Mesh::UpdateConstantBuffer() {
123123
UINT nWVPSize = (sizeof(this->m_wvp) + 255) & ~255;
124124
this->m_wvp.World = XMMatrixTranspose(XMMatrixIdentity());
125-
this->m_wvp.World *= XMMatrixTranspose(XMMatrixRotationX(XMConvertToRadians(this->m_transform.rotation.x)));
126-
this->m_wvp.World *= XMMatrixTranspose(XMMatrixRotationY(XMConvertToRadians(this->m_transform.rotation.y)));
127-
this->m_wvp.World *= XMMatrixTranspose(XMMatrixRotationZ(XMConvertToRadians(this->m_transform.rotation.z)));
125+
this->m_wvp.World *= XMMatrixTranspose(XMMatrixRotationX(XMConvertToRadians(this->m_transform->rotation.x)));
126+
this->m_wvp.World *= XMMatrixTranspose(XMMatrixRotationY(XMConvertToRadians(this->m_transform->rotation.y)));
127+
this->m_wvp.World *= XMMatrixTranspose(XMMatrixRotationZ(XMConvertToRadians(this->m_transform->rotation.z)));
128128
this->m_wvp.World *= XMMatrixTranspose(XMMatrixTranslation(
129-
this->m_transform.location.x,
130-
this->m_transform.location.y,
131-
this->m_transform.location.z));
129+
this->m_transform->location.x,
130+
this->m_transform->location.y,
131+
this->m_transform->location.z));
132132

133133
Transform cameraTransform = this->m_sceneMgr->GetCurrentScene()->GetCurrentCamera()->transform;
134134
this->m_wvp.View = XMMatrixTranspose(XMMatrixIdentity());
@@ -296,6 +296,7 @@ void Mesh::InitSampler(D3D12* renderer) {
296296

297297
UINT nActualIndex = nFirstIndex;
298298
for (std::pair<UINT, ComPtr<ID3D12Resource>> resource : this->m_textures) {
299+
if (nActualIndex > nLastIndex) break;
299300
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = { };
300301
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
301302
srvDesc.Texture2D.MipLevels = 1;
@@ -310,6 +311,7 @@ void Mesh::InitSampler(D3D12* renderer) {
310311
}
311312

312313
for (std::pair<UINT, ComPtr<ID3D12Resource>> resource : this->m_ORMTextures) {
314+
if (nActualIndex > nLastIndex) break;
313315
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = { };
314316
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
315317
srvDesc.Texture2D.MipLevels = 1;

src/private/Core/Renderer/D3D12.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ void D3D12::Init(HWND hwnd) {
141141
// We'll allocate the initial value for our ScreenQuad.
142142
this->m_cbvSrvHeap = new DescriptorHeap(4, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, true);
143143

144+
this->sceneMgr->Init();
145+
144146
this->m_screenQuad = new ScreenQuad();
145147
this->m_screenQuad->Init();
146148
this->InitGBufferShader();

src/private/Core/Renderer/ScreenQuad.cpp

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ ScreenQuad::ScreenQuad() {
55
this->m_core = Core::GetInstance();
66
this->m_renderer = nullptr;
77
this->m_shader = nullptr;
8+
this->m_sceneMgr = SceneManager::GetInstance();
9+
this->m_nSqCBuffIndex = -1;
810
}
911

1012
void ScreenQuad::Init() {
@@ -83,26 +85,31 @@ void ScreenQuad::D3D12Init(D3D12* renderer) {
8385
CD3DX12_DESCRIPTOR_RANGE normalRange;
8486
CD3DX12_DESCRIPTOR_RANGE positionRange;
8587
CD3DX12_DESCRIPTOR_RANGE ORMRange;
88+
CD3DX12_DESCRIPTOR_RANGE cbuffRange;
8689

8790
albedoRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0);
8891
normalRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 1);
8992
positionRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 2);
9093
ORMRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 3);
94+
cbuffRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0);
9195

9296
CD3DX12_ROOT_PARAMETER albedoParam;
9397
CD3DX12_ROOT_PARAMETER normalParam;
9498
CD3DX12_ROOT_PARAMETER positionParam;
9599
CD3DX12_ROOT_PARAMETER ORMParam;
100+
CD3DX12_ROOT_PARAMETER cbuffParam;
96101
albedoParam.InitAsDescriptorTable(1, &albedoRange, D3D12_SHADER_VISIBILITY_PIXEL);
97102
normalParam.InitAsDescriptorTable(1, &normalRange, D3D12_SHADER_VISIBILITY_PIXEL);
98103
positionParam.InitAsDescriptorTable(1, &positionRange, D3D12_SHADER_VISIBILITY_PIXEL);
99104
ORMParam.InitAsDescriptorTable(1, &ORMRange, D3D12_SHADER_VISIBILITY_PIXEL);
105+
cbuffParam.InitAsDescriptorTable(1, &cbuffRange, D3D12_SHADER_VISIBILITY_PIXEL);
100106

101107
D3D12_ROOT_PARAMETER rootParams[] = {
102108
albedoParam,
103109
normalParam,
104110
positionParam,
105-
ORMParam
111+
ORMParam,
112+
cbuffParam
106113
};
107114

108115
D3D12_ROOT_SIGNATURE_DESC rootDesc = { };
@@ -157,6 +164,7 @@ void ScreenQuad::D3D12Init(D3D12* renderer) {
157164
plDesc.SampleMask = UINT32_MAX;
158165

159166
ThrowIfFailed(this->m_dev->CreateGraphicsPipelineState(&plDesc, IID_PPV_ARGS(this->m_plState.GetAddressOf())));
167+
this->InitConstantBuffer();
160168
}
161169

162170
void ScreenQuad::Render() {
@@ -165,11 +173,54 @@ void ScreenQuad::Render() {
165173
}
166174
}
167175

176+
void ScreenQuad::InitConstantBuffer() {
177+
if (D3D12* renderer = dynamic_cast<D3D12*>(this->m_renderer)) {
178+
Camera* currentCamera = this->m_sceneMgr->GetCurrentScene()->GetCurrentCamera();
179+
180+
this->m_sqCBuffData.cameraPosition = XMFLOAT3(
181+
currentCamera->transform.location.x,
182+
currentCamera->transform.location.y,
183+
currentCamera->transform.location.z
184+
);
185+
186+
UINT nConstantBufferSize = (sizeof(this->m_sqCBuffData) + 255) & ~255;
187+
renderer->CreateBuffer(&this->m_sqCBuffData, nConstantBufferSize, m_sqCBuffer);
188+
189+
renderer->m_cbvSrvHeap->Allocate(1);
190+
this->m_nSqCBuffIndex = renderer->m_cbvSrvHeap->GetLastDescriptorIndex();
191+
Descriptor sqBuffDesc = renderer->m_cbvSrvHeap->GetDescriptor(this->m_nSqCBuffIndex);
192+
193+
D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = { };
194+
cbvDesc.BufferLocation = this->m_sqCBuffer->GetGPUVirtualAddress();
195+
cbvDesc.SizeInBytes = nConstantBufferSize;
196+
this->m_dev->CreateConstantBufferView(&cbvDesc, sqBuffDesc.cpuHandle);
197+
}
198+
}
199+
200+
void ScreenQuad::UpdateConstantBuffer() {
201+
Camera* currentCamera = this->m_sceneMgr->GetCurrentScene()->GetCurrentCamera();
202+
203+
this->m_sqCBuffData.cameraPosition = XMFLOAT3(
204+
currentCamera->transform.location.x,
205+
currentCamera->transform.location.y,
206+
currentCamera->transform.location.z
207+
);
208+
209+
UINT nConstantBufferSize = (sizeof(this->m_sqCBuffData) + 255) & ~255;
210+
211+
PVOID pData;
212+
ThrowIfFailed(this->m_sqCBuffer->Map(0, nullptr, &pData));
213+
memcpy(pData, &this->m_sqCBuffData, nConstantBufferSize);
214+
this->m_sqCBuffer->Unmap(0, nullptr);
215+
}
216+
168217
void ScreenQuad::D3D12Render(D3D12* renderer) {
218+
this->UpdateConstantBuffer();
169219
Descriptor albedoDesc = renderer->m_cbvSrvHeap->GetDescriptor(0);
170220
Descriptor normalDesc = renderer->m_cbvSrvHeap->GetDescriptor(1);
171221
Descriptor positionDesc = renderer->m_cbvSrvHeap->GetDescriptor(2);
172222
Descriptor materialDesc = renderer->m_cbvSrvHeap->GetDescriptor(3);
223+
Descriptor sqBuffDesc = renderer->m_cbvSrvHeap->GetDescriptor(this->m_nSqCBuffIndex);
173224
this->m_list->OMSetRenderTargets(1, &this->m_rtvDescriptor.cpuHandle, FALSE, nullptr);
174225
this->m_list->SetPipelineState(this->m_plState.Get());
175226
this->m_list->ClearRenderTargetView(this->m_rtvDescriptor.cpuHandle, RGBA{ 0.f, 0.f, 0.f, 1.f }, 0, nullptr);
@@ -183,6 +234,8 @@ void ScreenQuad::D3D12Render(D3D12* renderer) {
183234
this->m_list->SetGraphicsRootDescriptorTable(1, normalDesc.gpuHandle);
184235
this->m_list->SetGraphicsRootDescriptorTable(2, positionDesc.gpuHandle);
185236
this->m_list->SetGraphicsRootDescriptorTable(3, materialDesc.gpuHandle);
237+
this->m_list->SetGraphicsRootDescriptorTable(3, materialDesc.gpuHandle);
238+
this->m_list->SetGraphicsRootDescriptorTable(4, sqBuffDesc.gpuHandle);
186239

187240
this->m_list->DrawIndexedInstanced(this->m_indices.size(), 1, 0, 0, 0);
188241
}

src/private/Core/Scene/Scene.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Scene::Scene(std::string name) {
66
}
77

88
void Scene::Init() {
9-
Mesh* m_mesh = new Mesh("StaticMeshComponent", m_go->transform);
9+
Mesh* m_mesh = new Mesh("StaticMeshComponent", &m_go->transform);
1010
m_go->m_components.push_back(m_mesh);
1111
m_mesh->LoadModel("barrel.glb");
1212
this->AddGameObject(m_go);

src/public/Core/GameObject/Component/Mesh.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,10 @@ class Mesh : public Component {
7474
void InitPipeline();
7575
void InitSampler(D3D12* renderer);
7676

77-
Transform m_transform;
77+
Transform* m_transform;
7878
SceneManager* m_sceneMgr;
7979
public:
80-
Mesh(std::string name, Transform& parentTransform);
80+
Mesh(std::string name, Transform* parentTransform);
8181

8282
void Init();
8383
void Update();

src/public/Core/Renderer/ScreenQuad.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <Windows.h>
44
#include <d3d12.h>
55
#include <DirectXTK/d3dx12.h>
6+
#include <DXMath/DirectXMath.h>
67
#include <wrl.h>
78
#include <vector>
89
#include "Util.h"
@@ -14,6 +15,12 @@ using namespace Microsoft::WRL;
1415
class Core;
1516
class Renderer;
1617
class D3D12;
18+
class SceneManager;
19+
20+
21+
struct ScreenQuadBuffer {
22+
XMFLOAT3 cameraPosition;
23+
};
1724

1825
class ScreenQuad {
1926
private:
@@ -41,8 +48,16 @@ class ScreenQuad {
4148

4249
ComPtr<ID3D12RootSignature> m_rootSig;
4350
ComPtr<ID3D12PipelineState> m_plState;
51+
52+
SceneManager* m_sceneMgr;
53+
ComPtr<ID3D12Resource> m_sqCBuffer;
54+
ScreenQuadBuffer m_sqCBuffData;
55+
UINT m_nSqCBuffIndex;
4456

4557
Shader* m_shader;
58+
59+
void InitConstantBuffer();
60+
void UpdateConstantBuffer();
4661
public:
4762
ScreenQuad();
4863

0 commit comments

Comments
 (0)