forked from AmigurumiShaders/DX11Starter
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSDFRenderer.cpp
More file actions
351 lines (294 loc) · 13.2 KB
/
SDFRenderer.cpp
File metadata and controls
351 lines (294 loc) · 13.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
#include "SDFRenderer.h"
#include "Input.h"
#include "WICTextureLoader.h"
#include "BufferStructs.h"
#include "RaytracingHelper.h"
// Needed for a helper function to read compiled shader files from the hard drive
#pragma comment(lib, "d3dcompiler.lib")
#include <d3dcompiler.h>
//#include "SDFEntity.h"
#include <iostream>
void SDFRenderer::Init(bool vsync, std::shared_ptr<Camera> camera, std::shared_ptr<std::vector<SDFEntity>> entitiesRef)//, Game game)
{
this->vsync = vsync;
this->camera = camera;
this->entities = entitiesRef;
CreateRootSigAndPipelineState();
createTriangleForScreenQuad();
// Ensure the command list is closed going into Draw for the first time
commandList->Close();
}
SDFRenderer::~SDFRenderer()
{
}
// --------------------------------------------------------
// Clear the screen, redraw everything, present to the user
// --------------------------------------------------------
void SDFRenderer::Render()
{
DX12Helper& dx12HelperInst = DX12Helper::GetInstance();
//reset allocator for THIS buffer and set up the command list to use THIS allocator for THIS buffer
commandAllocators[currentSwapBuffer]->Reset();
commandList->Reset(commandAllocators[currentSwapBuffer].Get(), 0);
//dx12HelperInst.GetAllocatorByIndex(currentSwapBuffer)->Reset();
//commandList->Reset(dx12HelperInst.GetAllocatorByIndex(currentSwapBuffer).Get(), 0);
// Grab the current back buffer for this frame
Microsoft::WRL::ComPtr<ID3D12Resource> currentBackBuffer = backBuffers[currentSwapBuffer];
// Clearing the render target
{
// Transition the back buffer from present to render target
D3D12_RESOURCE_BARRIER rb = {};
rb.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
rb.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
rb.Transition.pResource = currentBackBuffer.Get();
rb.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
rb.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
rb.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
commandList->ResourceBarrier(1, &rb);
// Background color (Cornflower Blue in this case) for clearing
float material[] = { 0.4f, 0.6f, 0.75f, 1.0f };
// Clear the RTV
commandList->ClearRenderTargetView(
rtvHandles[currentSwapBuffer],
material,
0, 0); // No scissor rectangles
// Clear the depth buffer, too
commandList->ClearDepthStencilView(
dsvHandle,
D3D12_CLEAR_FLAG_DEPTH,
1.0f, // Max depth = 1.0f
0, // Not clearing stencil, but need a value
0, 0); // No scissor rects
}
// Rendering here!
{
// Set overall pipeline state
commandList->SetPipelineState(pipelineState.Get());
// Root sig (must happen before root descriptor table)
commandList->SetGraphicsRootSignature(rootSignature.Get());
// Set up other commands for rendering
commandList->OMSetRenderTargets(1, &rtvHandles[currentSwapBuffer], true, &dsvHandle);
commandList->RSSetViewports(1, &viewport);
commandList->RSSetScissorRects(1, &scissorRect);
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> descriptorHeap =
dx12HelperInst.GetCBVSRVDescriptorHeap();
commandList->SetDescriptorHeaps(1, descriptorHeap.GetAddressOf());
{
RaymarchVSExternalData externalData = {};
externalData.view = camera->GetView();
externalData.projection = camera->GetProjection();
DirectX::XMMATRIX v = DirectX::XMLoadFloat4x4(&externalData.view);
externalData.frustum[0] = camera->m_FrustumCorners[0];
externalData.frustum[1] = camera->m_FrustumCorners[1];
externalData.frustum[2] = camera->m_FrustumCorners[2];
externalData.frustum[3] = camera->m_FrustumCorners[3];
DirectX::XMStoreFloat4x4(&externalData.inverseViewProjection, XMMatrixInverse(0, v));
// //send to a chunk of a constant buffer heap, and grab the GPU handle we need to draw
D3D12_GPU_DESCRIPTOR_HANDLE handleVS = dx12HelperInst.FillNextConstantBufferAndGetGPUDescriptorHandle((void*)(&externalData), sizeof(externalData));
commandList->SetGraphicsRootDescriptorTable(0, handleVS);
}
// Pixel shader data and cbuffer setup
{
// TODO: should be made as member variable
//this is like if TroomTroom made a video about writing code lol
if (entities->size() > 0)//only do this if there is at least one entity
{
/*
TODO: Below should be moved inside Camera class
*/
XMFLOAT3 pos = camera->GetTransform()->GetPosition();
masterPSData.cameraPosition = XMFLOAT3A(pos.x, pos.y, pos.z);
XMStoreFloat3(&(masterPSData.cameraForward), camera->GetForward());
XMStoreFloat3(&(masterPSData.cameraRight), camera->GetRight());
XMStoreFloat3(&(masterPSData.cameraUp), camera->GetUp());
masterPSData.bgColor = XMFLOAT3(0.0f, 0.0f, 0.0f);
masterPSData.time = (float)ImGui::GetTime();
//// Send this to a chunk of the constant buffer heap
//// and grab the GPU handle for it so we can set it for this draw
D3D12_GPU_DESCRIPTOR_HANDLE cbHandlePS =
dx12HelperInst.FillNextConstantBufferAndGetGPUDescriptorHandle(
(void*)(&masterPSData), sizeof(RaymarchPSExternalData));
//// Set this constant buffer handle
//// Note: This assumes that descriptor table 1 is the
//// place to put this particular descriptor. This
//// is based on how we set up our root signature.
commandList->SetGraphicsRootDescriptorTable(1, cbHandlePS);
}
}
// Set them using IASetVertexBuffers() and IASetIndexBuffer()
commandList->IASetVertexBuffers(0, 1, &vbView);
commandList->DrawInstanced(3, 1, 0, 0); //first is the PER INSTANCE index count. second is HOW MANY of the INSTANCES themselves
RenderImGui();
//Present
{
// Transition back to present
D3D12_RESOURCE_BARRIER rb = {};
rb.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
rb.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
rb.Transition.pResource = currentBackBuffer.Get();
rb.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
rb.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
rb.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
commandList->ResourceBarrier(1, &rb);
// Must occur BEFORE present
dx12HelperInst.CloseAndExecuteCommandList();
// Present the current back buffer
swapChain->Present(vsync ? 1 : 0, 0);
//// Figure out which buffer is next
currentSwapBuffer = dx12HelperInst.SyncSwapChain(currentSwapBuffer);
}
}
}
void SDFRenderer::createTriangleForScreenQuad()
{
float vertex_data_array[] = {
0.0f, 0.5f, 0.0f, // point at top
0.5f, -0.5f, 0.0f, // point at bottom-right
-0.5f, -0.5f, 0.0f, // point at bottom-left
};
UINT vertex_stride = 3 * sizeof(float);
DX12Helper& dx12Helper = DX12Helper::GetInstance();
vertexBuffer = dx12Helper.CreateStaticBuffer(vertex_stride, 3, &vertex_data_array[0]);
vbView.StrideInBytes = vertex_stride;
vbView.SizeInBytes = vertex_stride * 3;
vbView.BufferLocation = vertexBuffer->GetGPUVirtualAddress();
}
void SDFRenderer::CreateRootSigAndPipelineState()
{
//since we are friend of DXCore just call the path functions from Game
// Blobs to hold raw shader byte code used in several steps below
//Microsoft::WRL::ComPtr<ID3DBlob> vertexShaderByteCode;
//Microsoft::WRL::ComPtr<ID3DBlob> pixelShaderByteCode;
// Load shaders
{
// Read our compiled vertex shader code into a blob
// - Essentially just "open the file and plop its contents here"
D3DReadFileToBlob(Utils::GetFullPathTo_Wide(L"RaymarchVS.cso").c_str(), vertexShaderByteCode.GetAddressOf());
D3DReadFileToBlob(Utils::GetFullPathTo_Wide(L"RaymarchPS.cso").c_str(), pixelShaderByteCode.GetAddressOf());
}
// Input layout
const unsigned int inputElementCount = 1;
D3D12_INPUT_ELEMENT_DESC inputElements[inputElementCount] = {};
{
inputElements[0].AlignedByteOffset = D3D12_APPEND_ALIGNED_ELEMENT;
inputElements[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; // R32 G32 B32 = float3
inputElements[0].SemanticName = "SV_VertexID"; // Name must match semantic in shader
inputElements[0].SemanticIndex = 0; // This is the first semantic of this type
}
// Root Signature
{
// Describe the range of CBVs needed for the vertex shader
D3D12_DESCRIPTOR_RANGE cbvRangeVS = {};
cbvRangeVS.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
cbvRangeVS.NumDescriptors = 1;
cbvRangeVS.BaseShaderRegister = 0;
cbvRangeVS.RegisterSpace = 0;
cbvRangeVS.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
// Describe the range of CBVs needed for the pixel shader
D3D12_DESCRIPTOR_RANGE cbvRangePS = {};
cbvRangePS.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
cbvRangePS.NumDescriptors = 1;
cbvRangePS.BaseShaderRegister = 0;
cbvRangePS.RegisterSpace = 0;
cbvRangePS.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
// Create a range of SRV's for textures
D3D12_DESCRIPTOR_RANGE srvRange = {};
srvRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
srvRange.NumDescriptors = 4; // Set to max number of textures at once (match pixel shader!)
srvRange.BaseShaderRegister = 0; // Starts at s0 (match pixel shader!)
srvRange.RegisterSpace = 0;
srvRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
// Create the root parameters
D3D12_ROOT_PARAMETER rootParams[3] = {};
// CBV table param for vertex shader
rootParams[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
rootParams[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
rootParams[0].DescriptorTable.NumDescriptorRanges = 1;
rootParams[0].DescriptorTable.pDescriptorRanges = &cbvRangeVS;
// CBV table param for vertex shader
rootParams[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
rootParams[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
rootParams[1].DescriptorTable.NumDescriptorRanges = 1;
rootParams[1].DescriptorTable.pDescriptorRanges = &cbvRangePS;
// SRV table param
rootParams[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
rootParams[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
rootParams[2].DescriptorTable.NumDescriptorRanges = 1;
rootParams[2].DescriptorTable.pDescriptorRanges = &srvRange;
// Create a single static sampler (available to all pixel shaders at the same slot)
// Note: This is in lieu of having materials have their own samplers for this demo
D3D12_STATIC_SAMPLER_DESC anisoWrap = {};
anisoWrap.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
anisoWrap.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
anisoWrap.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
anisoWrap.Filter = D3D12_FILTER_ANISOTROPIC;
anisoWrap.MaxAnisotropy = 16;
anisoWrap.MaxLOD = D3D12_FLOAT32_MAX;
anisoWrap.ShaderRegister = 0; // register(s0)
anisoWrap.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
D3D12_STATIC_SAMPLER_DESC samplers[] = { anisoWrap };
// Describe and serialize the root signature
D3D12_ROOT_SIGNATURE_DESC rootSig = {};
rootSig.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
rootSig.NumParameters = ARRAYSIZE(rootParams);
rootSig.pParameters = rootParams;
rootSig.NumStaticSamplers = ARRAYSIZE(samplers);
rootSig.pStaticSamplers = samplers;
ID3DBlob* serializedRootSig = 0;
ID3DBlob* errors = 0;
D3D12SerializeRootSignature(
&rootSig,
D3D_ROOT_SIGNATURE_VERSION_1,
&serializedRootSig,
&errors);
// Check for errors during serialization
if (errors != 0)
{
OutputDebugString((char*)errors->GetBufferPointer());
}
// Actually create the root sig
device->CreateRootSignature(
0,
serializedRootSig->GetBufferPointer(),
serializedRootSig->GetBufferSize(),
IID_PPV_ARGS(rootSignature.GetAddressOf()));
}
// Pipeline state
{
// Describe the pipeline state
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
// -- Input assembler related ---
psoDesc.InputLayout.NumElements = inputElementCount;
psoDesc.InputLayout.pInputElementDescs = inputElements;
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
// Root sig
psoDesc.pRootSignature = rootSignature.Get();
// -- Shaders (VS/PS) ---
psoDesc.VS.pShaderBytecode = vertexShaderByteCode->GetBufferPointer();
psoDesc.VS.BytecodeLength = vertexShaderByteCode->GetBufferSize();
psoDesc.PS.pShaderBytecode = pixelShaderByteCode->GetBufferPointer();
psoDesc.PS.BytecodeLength = pixelShaderByteCode->GetBufferSize();
// -- Render targets ---
psoDesc.NumRenderTargets = 1;
psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
psoDesc.DSVFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
psoDesc.SampleDesc.Count = 1;
psoDesc.SampleDesc.Quality = 0;
// -- States ---
psoDesc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
psoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_BACK;
psoDesc.RasterizerState.DepthClipEnable = true;
psoDesc.DepthStencilState.DepthEnable = true;
psoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS;
psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
psoDesc.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE;
psoDesc.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_ZERO;
psoDesc.BlendState.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD;
psoDesc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
// -- Misc ---
psoDesc.SampleMask = 0xffffffff;
// Create the pipe state object
device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(pipelineState.GetAddressOf()));
}
}