core: Define VK_USE_PLATFORM_XCB_KHR before including vkd3d_utils.h.
[vkmodelviewer.git] / ModelViewer / ModelViewer.cpp
blobc1129f3f275db1a0999db4ef06bf0c0011dce393
1 //
2 // Copyright (c) Microsoft. All rights reserved.
3 // This code is licensed under the MIT License (MIT).
4 // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
5 // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
6 // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
7 // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
8 //
9 // Developed by Minigraph
11 // Author(s): Alex Nankervis
12 // James Stanard
15 #include "GameCore.h"
16 #include "GraphicsCore.h"
17 #include "CameraController.h"
18 #include "BufferManager.h"
19 #include "Camera.h"
20 #include "Model.h"
21 #include "GpuBuffer.h"
22 #include "CommandContext.h"
23 #include "SamplerManager.h"
24 #include "TemporalEffects.h"
25 #include "MotionBlur.h"
26 #include "DepthOfField.h"
27 #include "PostEffects.h"
28 #include "SSAO.h"
29 #include "FXAA.h"
30 #include "SystemTime.h"
31 #include "TextRenderer.h"
32 #include "ShadowCamera.h"
33 #include "ParticleEffectManager.h"
34 #include "GameInput.h"
35 #include "./ForwardPlusLighting.h"
37 // To enable wave intrinsics, uncomment this macro and #define DXIL in Core/GraphcisCore.cpp.
38 // Run CompileSM6Test.bat to compile the relevant shaders with DXC.
39 //#define _WAVE_OP
41 #include "compiled_shaders/DepthViewerVS.h"
42 #include "compiled_shaders/DepthViewerPS.h"
43 #include "compiled_shaders/ModelViewerVS.h"
44 #include "compiled_shaders/ModelViewerPS.h"
45 #ifdef _WAVE_OP
46 #include "compiled_shaders/DepthViewerVS_SM6.h"
47 #include "compiled_shaders/ModelViewerVS_SM6.h"
48 #include "compiled_shaders/ModelViewerPS_SM6.h"
49 #endif
50 #include "compiled_shaders/WaveTileCountPS.h"
52 using namespace GameCore;
53 using namespace Math;
54 using namespace Graphics;
56 class ModelViewer : public GameCore::IGameApp
58 public:
60 ModelViewer( void ) {}
62 virtual void Startup( void ) override;
63 virtual void Cleanup( void ) override;
65 virtual void Update( float deltaT ) override;
66 virtual void RenderScene( void ) override;
68 private:
70 void RenderLightShadows(GraphicsContext& gfxContext);
72 enum eObjectFilter { kOpaque = 0x1, kCutout = 0x2, kTransparent = 0x4, kAll = 0xF, kNone = 0x0 };
73 void RenderObjects( GraphicsContext& Context, const Matrix4& ViewProjMat, eObjectFilter Filter = kAll );
74 void CreateParticleEffects();
75 Camera m_Camera;
76 std::auto_ptr<CameraController> m_CameraController;
77 Matrix4 m_ViewProjMatrix;
78 D3D12_VIEWPORT m_MainViewport;
79 D3D12_RECT m_MainScissor;
81 RootSignature m_RootSig;
82 GraphicsPSO m_DepthPSO;
83 GraphicsPSO m_CutoutDepthPSO;
84 GraphicsPSO m_ModelPSO;
85 #ifdef _WAVE_OP
86 GraphicsPSO m_DepthWaveOpsPSO;
87 GraphicsPSO m_ModelWaveOpsPSO;
88 #endif
89 GraphicsPSO m_CutoutModelPSO;
90 GraphicsPSO m_ShadowPSO;
91 GraphicsPSO m_CutoutShadowPSO;
92 GraphicsPSO m_WaveTileCountPSO;
94 D3D12_CPU_DESCRIPTOR_HANDLE m_DefaultSampler;
95 D3D12_CPU_DESCRIPTOR_HANDLE m_ShadowSampler;
96 D3D12_CPU_DESCRIPTOR_HANDLE m_BiasedDefaultSampler;
98 D3D12_CPU_DESCRIPTOR_HANDLE m_ExtraTextures[6];
99 Model m_Model;
100 std::vector<bool> m_pMaterialIsCutout;
102 Vector3 m_SunDirection;
103 ShadowCamera m_SunShadow;
106 CREATE_APPLICATION( ModelViewer )
108 ExpVar m_SunLightIntensity("Application/Lighting/Sun Light Intensity", 4.0f, 0.0f, 16.0f, 0.1f);
109 ExpVar m_AmbientIntensity("Application/Lighting/Ambient Intensity", 0.1f, -16.0f, 16.0f, 0.1f);
110 NumVar m_SunOrientation("Application/Lighting/Sun Orientation", -0.5f, -100.0f, 100.0f, 0.1f );
111 NumVar m_SunInclination("Application/Lighting/Sun Inclination", 0.75f, 0.0f, 1.0f, 0.01f );
112 NumVar ShadowDimX("Application/Lighting/Shadow Dim X", 5000, 1000, 10000, 100 );
113 NumVar ShadowDimY("Application/Lighting/Shadow Dim Y", 3000, 1000, 10000, 100 );
114 NumVar ShadowDimZ("Application/Lighting/Shadow Dim Z", 3000, 1000, 10000, 100 );
116 BoolVar ShowWaveTileCounts("Application/Forward+/Show Wave Tile Counts", false);
117 #ifdef _WAVE_OP
118 BoolVar EnableWaveOps("Application/Forward+/Enable Wave Ops", true);
119 #endif
121 void ModelViewer::Startup( void )
123 SamplerDesc DefaultSamplerDesc;
124 DefaultSamplerDesc.MaxAnisotropy = 8;
126 m_RootSig.Reset(5, 2);
127 m_RootSig.InitStaticSampler(0, DefaultSamplerDesc, D3D12_SHADER_VISIBILITY_PIXEL);
128 m_RootSig.InitStaticSampler(1, SamplerShadowDesc, D3D12_SHADER_VISIBILITY_PIXEL);
129 m_RootSig[0].InitAsConstantBuffer(0, D3D12_SHADER_VISIBILITY_VERTEX);
130 m_RootSig[1].InitAsConstantBuffer(0, D3D12_SHADER_VISIBILITY_PIXEL);
131 m_RootSig[2].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 6, D3D12_SHADER_VISIBILITY_PIXEL);
132 m_RootSig[3].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 64, 6, D3D12_SHADER_VISIBILITY_PIXEL);
133 m_RootSig[4].InitAsConstants(1, 2, D3D12_SHADER_VISIBILITY_VERTEX);
134 m_RootSig.Finalize(L"ModelViewer", D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
136 DXGI_FORMAT ColorFormat = g_SceneColorBuffer.GetFormat();
137 DXGI_FORMAT DepthFormat = g_SceneDepthBuffer.GetFormat();
139 D3D12_INPUT_ELEMENT_DESC vertElem[] =
141 { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
142 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
143 { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
144 { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
145 { "BITANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
148 // Depth-only (2x rate)
149 m_DepthPSO.SetRootSignature(m_RootSig);
150 m_DepthPSO.SetRasterizerState(RasterizerDefault);
151 m_DepthPSO.SetBlendState(BlendNoColorWrite);
152 m_DepthPSO.SetDepthStencilState(DepthStateReadWrite);
153 m_DepthPSO.SetInputLayout(_countof(vertElem), vertElem);
154 m_DepthPSO.SetPrimitiveTopologyType(D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE);
155 m_DepthPSO.SetRenderTargetFormats(0, nullptr, DepthFormat);
156 m_DepthPSO.SetVertexShader(g_pDepthViewerVS, sizeof(g_pDepthViewerVS));
157 m_DepthPSO.Finalize();
159 // Depth-only shading but with alpha testing
160 m_CutoutDepthPSO = m_DepthPSO;
161 m_CutoutDepthPSO.SetPixelShader(g_pDepthViewerPS, sizeof(g_pDepthViewerPS));
162 m_CutoutDepthPSO.SetRasterizerState(RasterizerTwoSided);
163 m_CutoutDepthPSO.Finalize();
165 // Depth-only but with a depth bias and/or render only backfaces
166 m_ShadowPSO = m_DepthPSO;
167 m_ShadowPSO.SetRasterizerState(RasterizerShadow);
168 m_ShadowPSO.SetRenderTargetFormats(0, nullptr, g_ShadowBuffer.GetFormat());
169 m_ShadowPSO.Finalize();
171 // Shadows with alpha testing
172 m_CutoutShadowPSO = m_ShadowPSO;
173 m_CutoutShadowPSO.SetPixelShader(g_pDepthViewerPS, sizeof(g_pDepthViewerPS));
174 m_CutoutShadowPSO.SetRasterizerState(RasterizerShadowTwoSided);
175 m_CutoutShadowPSO.Finalize();
177 // Full color pass
178 m_ModelPSO = m_DepthPSO;
179 m_ModelPSO.SetBlendState(BlendDisable);
180 m_ModelPSO.SetDepthStencilState(DepthStateTestEqual);
181 m_ModelPSO.SetRenderTargetFormats(1, &ColorFormat, DepthFormat);
182 m_ModelPSO.SetVertexShader( g_pModelViewerVS, sizeof(g_pModelViewerVS) );
183 m_ModelPSO.SetPixelShader( g_pModelViewerPS, sizeof(g_pModelViewerPS) );
184 m_ModelPSO.Finalize();
186 #ifdef _WAVE_OP
187 m_DepthWaveOpsPSO = m_DepthPSO;
188 m_DepthWaveOpsPSO.SetVertexShader( g_pDepthViewerVS_SM6, sizeof(g_pDepthViewerVS_SM6) );
189 m_DepthWaveOpsPSO.Finalize();
191 m_ModelWaveOpsPSO = m_ModelPSO;
192 m_ModelWaveOpsPSO.SetVertexShader( g_pModelViewerVS_SM6, sizeof(g_pModelViewerVS_SM6) );
193 m_ModelWaveOpsPSO.SetPixelShader( g_pModelViewerPS_SM6, sizeof(g_pModelViewerPS_SM6) );
194 m_ModelWaveOpsPSO.Finalize();
195 #endif
197 m_CutoutModelPSO = m_ModelPSO;
198 m_CutoutModelPSO.SetRasterizerState(RasterizerTwoSided);
199 m_CutoutModelPSO.Finalize();
201 // A debug shader for counting lights in a tile
202 m_WaveTileCountPSO = m_ModelPSO;
203 m_WaveTileCountPSO.SetPixelShader(g_pWaveTileCountPS, sizeof(g_pWaveTileCountPS));
204 m_WaveTileCountPSO.Finalize();
206 Lighting::InitializeResources();
208 m_ExtraTextures[0] = g_SSAOFullScreen.GetSRV();
209 m_ExtraTextures[1] = g_ShadowBuffer.GetSRV();
211 TextureManager::Initialize(MODELVIEWER_DATADIR "/textures/");
212 ASSERT(m_Model.Load(MODELVIEWER_DATADIR "/models/sponza.h3d"), "Failed to load model");
213 ASSERT(m_Model.m_Header.meshCount > 0, "Model contains no meshes");
215 // The caller of this function can override which materials are considered cutouts
216 m_pMaterialIsCutout.resize(m_Model.m_Header.materialCount);
217 for (uint32_t i = 0; i < m_Model.m_Header.materialCount; ++i)
219 const Model::Material& mat = m_Model.m_pMaterial[i];
220 if (std::string(mat.texDiffusePath).find("thorn") != std::string::npos ||
221 std::string(mat.texDiffusePath).find("plant") != std::string::npos ||
222 std::string(mat.texDiffusePath).find("chain") != std::string::npos)
224 m_pMaterialIsCutout[i] = true;
226 else
228 m_pMaterialIsCutout[i] = false;
232 CreateParticleEffects();
234 float modelRadius = Length(m_Model.m_Header.boundingBox.max - m_Model.m_Header.boundingBox.min) * .5f;
235 const Vector3 eye = (m_Model.m_Header.boundingBox.min + m_Model.m_Header.boundingBox.max) * .5f + Vector3(modelRadius * .5f, 0.0f, 0.0f);
236 m_Camera.SetEyeAtUp( eye, Vector3(kZero), Vector3(kYUnitVector) );
237 m_Camera.SetZRange( 1.0f, 10000.0f );
238 m_CameraController.reset(new CameraController(m_Camera, Vector3(kYUnitVector)));
240 MotionBlur::Enable = true;
241 TemporalEffects::EnableTAA = true;
242 FXAA::Enable = false;
243 PostEffects::EnableHDR = true;
244 PostEffects::EnableAdaptation = true;
245 SSAO::Enable = true;
247 Lighting::CreateRandomLights(m_Model.GetBoundingBox().min, m_Model.GetBoundingBox().max);
249 m_ExtraTextures[2] = Lighting::m_LightBuffer.GetSRV();
250 m_ExtraTextures[3] = Lighting::m_LightShadowArray.GetSRV();
251 m_ExtraTextures[4] = Lighting::m_LightGrid.GetSRV();
252 m_ExtraTextures[5] = Lighting::m_LightGridBitMask.GetSRV();
255 void ModelViewer::Cleanup( void )
257 m_Model.Clear();
260 namespace Graphics
262 extern EnumVar DebugZoom;
265 void ModelViewer::Update( float deltaT )
267 ScopedTimer _prof(L"Update State");
269 if (GameInput::IsFirstPressed(GameInput::kLShoulder))
270 DebugZoom.Decrement();
271 else if (GameInput::IsFirstPressed(GameInput::kRShoulder))
272 DebugZoom.Increment();
274 m_CameraController->Update(deltaT);
275 m_ViewProjMatrix = m_Camera.GetViewProjMatrix();
277 float costheta = cosf(m_SunOrientation);
278 float sintheta = sinf(m_SunOrientation);
279 float cosphi = cosf(m_SunInclination * 3.14159f * 0.5f);
280 float sinphi = sinf(m_SunInclination * 3.14159f * 0.5f);
281 m_SunDirection = Normalize(Vector3( costheta * cosphi, sinphi, sintheta * cosphi ));
283 // We use viewport offsets to jitter sample positions from frame to frame (for TAA.)
284 // D3D has a design quirk with fractional offsets such that the implicit scissor
285 // region of a viewport is floor(TopLeftXY) and floor(TopLeftXY + WidthHeight), so
286 // having a negative fractional top left, e.g. (-0.25, -0.25) would also shift the
287 // BottomRight corner up by a whole integer. One solution is to pad your viewport
288 // dimensions with an extra pixel. My solution is to only use positive fractional offsets,
289 // but that means that the average sample position is +0.5, which I use when I disable
290 // temporal AA.
291 TemporalEffects::GetJitterOffset(m_MainViewport.TopLeftX, m_MainViewport.TopLeftY);
293 m_MainViewport.Width = (float)g_SceneColorBuffer.GetWidth();
294 m_MainViewport.Height = (float)g_SceneColorBuffer.GetHeight();
295 m_MainViewport.MinDepth = 0.0f;
296 m_MainViewport.MaxDepth = 1.0f;
298 m_MainScissor.left = 0;
299 m_MainScissor.top = 0;
300 m_MainScissor.right = (LONG)g_SceneColorBuffer.GetWidth();
301 m_MainScissor.bottom = (LONG)g_SceneColorBuffer.GetHeight();
304 void ModelViewer::RenderObjects( GraphicsContext& gfxContext, const Matrix4& ViewProjMat, eObjectFilter Filter )
306 struct VSConstants
308 Matrix4 modelToProjection;
309 Matrix4 modelToShadow;
310 XMFLOAT3 viewerPos;
311 } vsConstants;
312 vsConstants.modelToProjection = ViewProjMat;
313 vsConstants.modelToShadow = m_SunShadow.GetShadowMatrix();
314 XMStoreFloat3(&vsConstants.viewerPos, m_Camera.GetPosition());
316 gfxContext.SetDynamicConstantBufferView(0, sizeof(vsConstants), &vsConstants);
318 uint32_t materialIdx = 0xFFFFFFFFul;
320 uint32_t VertexStride = m_Model.m_VertexStride;
322 for (uint32_t meshIndex = 0; meshIndex < m_Model.m_Header.meshCount; meshIndex++)
324 const Model::Mesh& mesh = m_Model.m_pMesh[meshIndex];
326 uint32_t indexCount = mesh.indexCount;
327 uint32_t startIndex = mesh.indexDataByteOffset / sizeof(uint16_t);
328 uint32_t baseVertex = mesh.vertexDataByteOffset / VertexStride;
330 if (mesh.materialIndex != materialIdx)
332 if ((m_pMaterialIsCutout[mesh.materialIndex] && !(Filter & kCutout))
333 || (!m_pMaterialIsCutout[mesh.materialIndex] && !(Filter & kOpaque)))
334 continue;
336 materialIdx = mesh.materialIndex;
337 gfxContext.SetDynamicDescriptors(2, 0, 6, m_Model.GetSRVs(materialIdx) );
340 gfxContext.SetConstants(4, baseVertex, materialIdx);
342 gfxContext.DrawIndexed(indexCount, startIndex, baseVertex);
346 void ModelViewer::RenderLightShadows(GraphicsContext& gfxContext)
348 using namespace Lighting;
350 ScopedTimer _prof(L"RenderLightShadows", gfxContext);
352 static uint32_t LightIndex = 0;
353 if (LightIndex >= MaxLights)
354 return;
356 m_LightShadowTempBuffer.BeginRendering(gfxContext);
358 gfxContext.SetPipelineState(m_ShadowPSO);
359 RenderObjects(gfxContext, m_LightShadowMatrix[LightIndex], kOpaque);
360 gfxContext.SetPipelineState(m_CutoutShadowPSO);
361 RenderObjects(gfxContext, m_LightShadowMatrix[LightIndex], kCutout);
363 m_LightShadowTempBuffer.EndRendering(gfxContext);
365 gfxContext.TransitionResource(m_LightShadowTempBuffer, D3D12_RESOURCE_STATE_GENERIC_READ);
366 gfxContext.TransitionResource(m_LightShadowArray, D3D12_RESOURCE_STATE_COPY_DEST);
368 gfxContext.CopySubresource(m_LightShadowArray, LightIndex, m_LightShadowTempBuffer, 0);
370 gfxContext.TransitionResource(m_LightShadowArray, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
372 ++LightIndex;
375 void ModelViewer::RenderScene( void )
377 static bool s_ShowLightCounts = false;
378 if (ShowWaveTileCounts != s_ShowLightCounts)
380 static bool EnableHDR;
381 if (ShowWaveTileCounts)
383 EnableHDR = PostEffects::EnableHDR;
384 PostEffects::EnableHDR = false;
386 else
388 PostEffects::EnableHDR = EnableHDR;
390 s_ShowLightCounts = ShowWaveTileCounts;
393 GraphicsContext& gfxContext = GraphicsContext::Begin(L"Scene Render");
395 ParticleEffects::Update(gfxContext.GetComputeContext(), Graphics::GetFrameTime());
397 uint32_t FrameIndex = TemporalEffects::GetFrameIndexMod2();
399 struct DECLSPEC_ALIGN(16)
401 Vector3 sunDirection;
402 Vector3 sunLight;
403 Vector3 ambientLight;
404 float ShadowTexelSize[4];
406 float InvTileDim[4];
407 uint32_t TileCount[4];
408 uint32_t FirstLightIndex[4];
409 uint32_t FrameIndexMod2;
410 } psConstants;
412 psConstants.sunDirection = m_SunDirection;
413 psConstants.sunLight = Vector3(1.0f, 1.0f, 1.0f) * m_SunLightIntensity;
414 psConstants.ambientLight = Vector3(1.0f, 1.0f, 1.0f) * m_AmbientIntensity;
415 psConstants.ShadowTexelSize[0] = 1.0f / g_ShadowBuffer.GetWidth();
416 psConstants.InvTileDim[0] = 1.0f / Lighting::LightGridDim;
417 psConstants.InvTileDim[1] = 1.0f / Lighting::LightGridDim;
418 psConstants.TileCount[0] = Math::DivideByMultiple(g_SceneColorBuffer.GetWidth(), Lighting::LightGridDim);
419 psConstants.TileCount[1] = Math::DivideByMultiple(g_SceneColorBuffer.GetHeight(), Lighting::LightGridDim);
420 psConstants.FirstLightIndex[0] = Lighting::m_FirstConeLight;
421 psConstants.FirstLightIndex[1] = Lighting::m_FirstConeShadowedLight;
422 psConstants.FrameIndexMod2 = FrameIndex;
424 // Set the default state for command lists
425 auto pfnSetupGraphicsState = [&](void)
427 gfxContext.SetRootSignature(m_RootSig);
428 gfxContext.SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
429 gfxContext.SetIndexBuffer(m_Model.m_IndexBuffer.IndexBufferView());
430 gfxContext.SetVertexBuffer(0, m_Model.m_VertexBuffer.VertexBufferView());
433 pfnSetupGraphicsState();
435 RenderLightShadows(gfxContext);
438 ScopedTimer _prof(L"Z PrePass", gfxContext);
440 gfxContext.SetDynamicConstantBufferView(1, sizeof(psConstants), &psConstants);
443 ScopedTimer _prof(L"Opaque", gfxContext);
444 gfxContext.TransitionResource(g_SceneDepthBuffer, D3D12_RESOURCE_STATE_DEPTH_WRITE, true);
445 gfxContext.ClearDepth(g_SceneDepthBuffer);
447 #ifdef _WAVE_OP
448 gfxContext.SetPipelineState(EnableWaveOps ? m_DepthWaveOpsPSO : m_DepthPSO );
449 #else
450 gfxContext.SetPipelineState(m_DepthPSO);
451 #endif
452 gfxContext.SetDepthStencilTarget(g_SceneDepthBuffer.GetDSV());
453 gfxContext.SetViewportAndScissor(m_MainViewport, m_MainScissor);
454 RenderObjects(gfxContext, m_ViewProjMatrix, kOpaque );
458 ScopedTimer _prof(L"Cutout", gfxContext);
459 gfxContext.SetPipelineState(m_CutoutDepthPSO);
460 RenderObjects(gfxContext, m_ViewProjMatrix, kCutout );
464 SSAO::Render(gfxContext, m_Camera);
466 Lighting::FillLightGrid(gfxContext, m_Camera);
468 if (!SSAO::DebugDraw)
470 ScopedTimer _prof(L"Main Render", gfxContext);
472 gfxContext.TransitionResource(g_SceneColorBuffer, D3D12_RESOURCE_STATE_RENDER_TARGET, true);
473 gfxContext.ClearColor(g_SceneColorBuffer);
475 pfnSetupGraphicsState();
478 ScopedTimer _prof(L"Render Shadow Map", gfxContext);
480 m_SunShadow.UpdateMatrix(-m_SunDirection, Vector3(0, -500.0f, 0), Vector3(ShadowDimX, ShadowDimY, ShadowDimZ),
481 (uint32_t)g_ShadowBuffer.GetWidth(), (uint32_t)g_ShadowBuffer.GetHeight(), 16);
483 g_ShadowBuffer.BeginRendering(gfxContext);
484 gfxContext.SetPipelineState(m_ShadowPSO);
485 RenderObjects(gfxContext, m_SunShadow.GetViewProjMatrix(), kOpaque);
486 gfxContext.SetPipelineState(m_CutoutShadowPSO);
487 RenderObjects(gfxContext, m_SunShadow.GetViewProjMatrix(), kCutout);
488 g_ShadowBuffer.EndRendering(gfxContext);
491 if (SSAO::AsyncCompute)
493 gfxContext.Flush();
494 pfnSetupGraphicsState();
496 // Make the 3D queue wait for the Compute queue to finish SSAO
497 g_CommandManager.GetGraphicsQueue().StallForProducer(g_CommandManager.GetComputeQueue());
501 ScopedTimer _prof(L"Render Color", gfxContext);
503 gfxContext.TransitionResource(g_SSAOFullScreen, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
505 gfxContext.SetDynamicDescriptors(3, 0, _countof(m_ExtraTextures), m_ExtraTextures);
506 gfxContext.SetDynamicConstantBufferView(1, sizeof(psConstants), &psConstants);
507 #ifdef _WAVE_OP
508 gfxContext.SetPipelineState(EnableWaveOps ? m_ModelWaveOpsPSO : m_ModelPSO );
509 #else
510 gfxContext.SetPipelineState(ShowWaveTileCounts ? m_WaveTileCountPSO : m_ModelPSO);
511 #endif
512 gfxContext.TransitionResource(g_SceneDepthBuffer, D3D12_RESOURCE_STATE_DEPTH_READ);
513 gfxContext.SetRenderTarget(g_SceneColorBuffer.GetRTV(), g_SceneDepthBuffer.GetDSV_DepthReadOnly());
514 gfxContext.SetViewportAndScissor(m_MainViewport, m_MainScissor);
516 RenderObjects( gfxContext, m_ViewProjMatrix, kOpaque );
518 if (!ShowWaveTileCounts)
520 gfxContext.SetPipelineState(m_CutoutModelPSO);
521 RenderObjects( gfxContext, m_ViewProjMatrix, kCutout );
527 // Some systems generate a per-pixel velocity buffer to better track dynamic and skinned meshes. Everything
528 // is static in our scene, so we generate velocity from camera motion and the depth buffer. A velocity buffer
529 // is necessary for all temporal effects (and motion blur).
530 MotionBlur::GenerateCameraVelocityBuffer(gfxContext, m_Camera, true);
532 TemporalEffects::ResolveImage(gfxContext);
534 ParticleEffects::Render(gfxContext, m_Camera, g_SceneColorBuffer, g_SceneDepthBuffer, g_LinearDepth[FrameIndex]);
536 // Until I work out how to couple these two, it's "either-or".
537 if (DepthOfField::Enable)
538 DepthOfField::Render(gfxContext, m_Camera.GetNearClip(), m_Camera.GetFarClip());
539 else
540 MotionBlur::RenderObjectBlur(gfxContext, g_VelocityBuffer);
542 gfxContext.Finish();
545 void ModelViewer::CreateParticleEffects()
547 ParticleEffectProperties Effect = ParticleEffectProperties();
548 Effect.MinStartColor = Effect.MaxStartColor = Effect.MinEndColor = Effect.MaxEndColor = Color(1.0f, 1.0f, 1.0f, 0.0f);
549 Effect.TexturePath = "spark_tex.dds";
551 Effect.TotalActiveLifetime = FLT_MAX;
552 Effect.Size = Vector4(4.0f, 8.0f, 4.0f, 8.0f);
553 Effect.Velocity = Vector4(20.0f, 200.0f, 50.0f, 180.0f);
554 Effect.LifeMinMax = XMFLOAT2(1.0f, 3.0f);
555 Effect.MassMinMax = XMFLOAT2(4.5f, 15.0f);
556 Effect.EmitProperties.Gravity = XMFLOAT3(0.0f, -100.0f, 0.0f);
557 Effect.EmitProperties.FloorHeight = -0.5f;
558 Effect.EmitProperties.EmitPosW = Effect.EmitProperties.LastEmitPosW = XMFLOAT3(-1200.0f, 185.0f, -445.0f);
559 Effect.EmitProperties.MaxParticles = 800;
560 Effect.EmitRate = 64.0f;
561 Effect.Spread.x = 20.0f;
562 Effect.Spread.y = 50.0f;
563 ParticleEffects::InstantiateEffect( Effect );
565 ParticleEffectProperties Smoke = ParticleEffectProperties();
566 Smoke.TexturePath = "smoke.dds";
568 Smoke.TotalActiveLifetime = FLT_MAX;
569 Smoke.EmitProperties.MaxParticles = 25;
570 Smoke.EmitProperties.EmitPosW = Smoke.EmitProperties.LastEmitPosW = XMFLOAT3(1120.0f, 185.0f, -445.0f);
571 Smoke.EmitRate = 64.0f;
572 Smoke.LifeMinMax = XMFLOAT2(2.5f, 4.0f);
573 Smoke.Size = Vector4(60.0f, 108.0f, 30.0f, 208.0f);
574 Smoke.Velocity = Vector4(30.0f, 30.0f, 10.0f, 40.0f);
575 Smoke.MassMinMax = XMFLOAT2(1.0, 3.5);
576 Smoke.Spread.x = 60.0f;
577 Smoke.Spread.y = 70.0f;
578 Smoke.Spread.z = 20.0f;
579 ParticleEffects::InstantiateEffect( Smoke );
581 ParticleEffectProperties Fire = ParticleEffectProperties();
582 Fire.MinStartColor = Fire.MaxStartColor = Fire.MinEndColor = Fire.MaxEndColor = Color(8.0f, 8.0f, 8.0f, 0.0f);
583 Fire.TexturePath = "fire.dds";
585 Fire.TotalActiveLifetime = FLT_MAX;
586 Fire.Size = Vector4(54.0f, 68.0f, 0.1f, 0.3f);
587 Fire.Velocity = Vector4 (10.0f, 30.0f, 50.0f, 50.0f);
588 Fire.LifeMinMax = XMFLOAT2(1.0f, 3.0f);
589 Fire.MassMinMax = XMFLOAT2(10.5f, 14.0f);
590 Fire.EmitProperties.Gravity = XMFLOAT3(0.0f, 1.0f, 0.0f);
591 Fire.EmitProperties.EmitPosW = Fire.EmitProperties.LastEmitPosW = XMFLOAT3(1120.0f, 125.0f, 405.0f);
592 Fire.EmitProperties.MaxParticles = 25;
593 Fire.EmitRate = 64.0f;
594 Fire.Spread.x = 1.0f;
595 Fire.Spread.y = 60.0f;
596 ParticleEffects::InstantiateEffect( Fire );