core: Fix wchar_t handling in TextRenderer.
[vkmodelviewer.git] / ModelViewer / ModelViewer.cpp
blob1a436f95607a6a83e67ab6040256dabef19b942e
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();
138 DXGI_FORMAT ShadowFormat = g_ShadowBuffer.GetFormat();
140 D3D12_INPUT_ELEMENT_DESC vertElem[] =
142 { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
143 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
144 { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
145 { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
146 { "BITANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
149 // Depth-only (2x rate)
150 m_DepthPSO.SetRootSignature(m_RootSig);
151 m_DepthPSO.SetRasterizerState(RasterizerDefault);
152 m_DepthPSO.SetBlendState(BlendNoColorWrite);
153 m_DepthPSO.SetDepthStencilState(DepthStateReadWrite);
154 m_DepthPSO.SetInputLayout(_countof(vertElem), vertElem);
155 m_DepthPSO.SetPrimitiveTopologyType(D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE);
156 m_DepthPSO.SetRenderTargetFormats(0, nullptr, DepthFormat);
157 m_DepthPSO.SetVertexShader(g_pDepthViewerVS, sizeof(g_pDepthViewerVS));
158 m_DepthPSO.Finalize();
160 // Depth-only shading but with alpha testing
161 m_CutoutDepthPSO = m_DepthPSO;
162 m_CutoutDepthPSO.SetPixelShader(g_pDepthViewerPS, sizeof(g_pDepthViewerPS));
163 m_CutoutDepthPSO.SetRasterizerState(RasterizerTwoSided);
164 m_CutoutDepthPSO.Finalize();
166 // Depth-only but with a depth bias and/or render only backfaces
167 m_ShadowPSO = m_DepthPSO;
168 m_ShadowPSO.SetRasterizerState(RasterizerShadow);
169 m_ShadowPSO.SetRenderTargetFormats(0, nullptr, g_ShadowBuffer.GetFormat());
170 m_ShadowPSO.Finalize();
172 // Shadows with alpha testing
173 m_CutoutShadowPSO = m_ShadowPSO;
174 m_CutoutShadowPSO.SetPixelShader(g_pDepthViewerPS, sizeof(g_pDepthViewerPS));
175 m_CutoutShadowPSO.SetRasterizerState(RasterizerShadowTwoSided);
176 m_CutoutShadowPSO.Finalize();
178 // Full color pass
179 m_ModelPSO = m_DepthPSO;
180 m_ModelPSO.SetBlendState(BlendDisable);
181 m_ModelPSO.SetDepthStencilState(DepthStateTestEqual);
182 m_ModelPSO.SetRenderTargetFormats(1, &ColorFormat, DepthFormat);
183 m_ModelPSO.SetVertexShader( g_pModelViewerVS, sizeof(g_pModelViewerVS) );
184 m_ModelPSO.SetPixelShader( g_pModelViewerPS, sizeof(g_pModelViewerPS) );
185 m_ModelPSO.Finalize();
187 #ifdef _WAVE_OP
188 m_DepthWaveOpsPSO = m_DepthPSO;
189 m_DepthWaveOpsPSO.SetVertexShader( g_pDepthViewerVS_SM6, sizeof(g_pDepthViewerVS_SM6) );
190 m_DepthWaveOpsPSO.Finalize();
192 m_ModelWaveOpsPSO = m_ModelPSO;
193 m_ModelWaveOpsPSO.SetVertexShader( g_pModelViewerVS_SM6, sizeof(g_pModelViewerVS_SM6) );
194 m_ModelWaveOpsPSO.SetPixelShader( g_pModelViewerPS_SM6, sizeof(g_pModelViewerPS_SM6) );
195 m_ModelWaveOpsPSO.Finalize();
196 #endif
198 m_CutoutModelPSO = m_ModelPSO;
199 m_CutoutModelPSO.SetRasterizerState(RasterizerTwoSided);
200 m_CutoutModelPSO.Finalize();
202 // A debug shader for counting lights in a tile
203 m_WaveTileCountPSO = m_ModelPSO;
204 m_WaveTileCountPSO.SetPixelShader(g_pWaveTileCountPS, sizeof(g_pWaveTileCountPS));
205 m_WaveTileCountPSO.Finalize();
207 Lighting::InitializeResources();
209 m_ExtraTextures[0] = g_SSAOFullScreen.GetSRV();
210 m_ExtraTextures[1] = g_ShadowBuffer.GetSRV();
212 TextureManager::Initialize(MODELVIEWER_DATADIR "/textures/");
213 ASSERT(m_Model.Load(MODELVIEWER_DATADIR "/models/sponza.h3d"), "Failed to load model");
214 ASSERT(m_Model.m_Header.meshCount > 0, "Model contains no meshes");
216 // The caller of this function can override which materials are considered cutouts
217 m_pMaterialIsCutout.resize(m_Model.m_Header.materialCount);
218 for (uint32_t i = 0; i < m_Model.m_Header.materialCount; ++i)
220 const Model::Material& mat = m_Model.m_pMaterial[i];
221 if (std::string(mat.texDiffusePath).find("thorn") != std::string::npos ||
222 std::string(mat.texDiffusePath).find("plant") != std::string::npos ||
223 std::string(mat.texDiffusePath).find("chain") != std::string::npos)
225 m_pMaterialIsCutout[i] = true;
227 else
229 m_pMaterialIsCutout[i] = false;
233 CreateParticleEffects();
235 float modelRadius = Length(m_Model.m_Header.boundingBox.max - m_Model.m_Header.boundingBox.min) * .5f;
236 const Vector3 eye = (m_Model.m_Header.boundingBox.min + m_Model.m_Header.boundingBox.max) * .5f + Vector3(modelRadius * .5f, 0.0f, 0.0f);
237 m_Camera.SetEyeAtUp( eye, Vector3(kZero), Vector3(kYUnitVector) );
238 m_Camera.SetZRange( 1.0f, 10000.0f );
239 m_CameraController.reset(new CameraController(m_Camera, Vector3(kYUnitVector)));
241 MotionBlur::Enable = true;
242 TemporalEffects::EnableTAA = true;
243 FXAA::Enable = false;
244 PostEffects::EnableHDR = true;
245 PostEffects::EnableAdaptation = true;
246 SSAO::Enable = true;
248 Lighting::CreateRandomLights(m_Model.GetBoundingBox().min, m_Model.GetBoundingBox().max);
250 m_ExtraTextures[2] = Lighting::m_LightBuffer.GetSRV();
251 m_ExtraTextures[3] = Lighting::m_LightShadowArray.GetSRV();
252 m_ExtraTextures[4] = Lighting::m_LightGrid.GetSRV();
253 m_ExtraTextures[5] = Lighting::m_LightGridBitMask.GetSRV();
256 void ModelViewer::Cleanup( void )
258 m_Model.Clear();
261 namespace Graphics
263 extern EnumVar DebugZoom;
266 void ModelViewer::Update( float deltaT )
268 ScopedTimer _prof(L"Update State");
270 if (GameInput::IsFirstPressed(GameInput::kLShoulder))
271 DebugZoom.Decrement();
272 else if (GameInput::IsFirstPressed(GameInput::kRShoulder))
273 DebugZoom.Increment();
275 m_CameraController->Update(deltaT);
276 m_ViewProjMatrix = m_Camera.GetViewProjMatrix();
278 float costheta = cosf(m_SunOrientation);
279 float sintheta = sinf(m_SunOrientation);
280 float cosphi = cosf(m_SunInclination * 3.14159f * 0.5f);
281 float sinphi = sinf(m_SunInclination * 3.14159f * 0.5f);
282 m_SunDirection = Normalize(Vector3( costheta * cosphi, sinphi, sintheta * cosphi ));
284 // We use viewport offsets to jitter sample positions from frame to frame (for TAA.)
285 // D3D has a design quirk with fractional offsets such that the implicit scissor
286 // region of a viewport is floor(TopLeftXY) and floor(TopLeftXY + WidthHeight), so
287 // having a negative fractional top left, e.g. (-0.25, -0.25) would also shift the
288 // BottomRight corner up by a whole integer. One solution is to pad your viewport
289 // dimensions with an extra pixel. My solution is to only use positive fractional offsets,
290 // but that means that the average sample position is +0.5, which I use when I disable
291 // temporal AA.
292 TemporalEffects::GetJitterOffset(m_MainViewport.TopLeftX, m_MainViewport.TopLeftY);
294 m_MainViewport.Width = (float)g_SceneColorBuffer.GetWidth();
295 m_MainViewport.Height = (float)g_SceneColorBuffer.GetHeight();
296 m_MainViewport.MinDepth = 0.0f;
297 m_MainViewport.MaxDepth = 1.0f;
299 m_MainScissor.left = 0;
300 m_MainScissor.top = 0;
301 m_MainScissor.right = (LONG)g_SceneColorBuffer.GetWidth();
302 m_MainScissor.bottom = (LONG)g_SceneColorBuffer.GetHeight();
305 void ModelViewer::RenderObjects( GraphicsContext& gfxContext, const Matrix4& ViewProjMat, eObjectFilter Filter )
307 struct VSConstants
309 Matrix4 modelToProjection;
310 Matrix4 modelToShadow;
311 XMFLOAT3 viewerPos;
312 } vsConstants;
313 vsConstants.modelToProjection = ViewProjMat;
314 vsConstants.modelToShadow = m_SunShadow.GetShadowMatrix();
315 XMStoreFloat3(&vsConstants.viewerPos, m_Camera.GetPosition());
317 gfxContext.SetDynamicConstantBufferView(0, sizeof(vsConstants), &vsConstants);
319 uint32_t materialIdx = 0xFFFFFFFFul;
321 uint32_t VertexStride = m_Model.m_VertexStride;
323 for (uint32_t meshIndex = 0; meshIndex < m_Model.m_Header.meshCount; meshIndex++)
325 const Model::Mesh& mesh = m_Model.m_pMesh[meshIndex];
327 uint32_t indexCount = mesh.indexCount;
328 uint32_t startIndex = mesh.indexDataByteOffset / sizeof(uint16_t);
329 uint32_t baseVertex = mesh.vertexDataByteOffset / VertexStride;
331 if (mesh.materialIndex != materialIdx)
333 if ( m_pMaterialIsCutout[mesh.materialIndex] && !(Filter & kCutout) ||
334 !m_pMaterialIsCutout[mesh.materialIndex] && !(Filter & kOpaque) )
335 continue;
337 materialIdx = mesh.materialIndex;
338 gfxContext.SetDynamicDescriptors(2, 0, 6, m_Model.GetSRVs(materialIdx) );
341 gfxContext.SetConstants(4, baseVertex, materialIdx);
343 gfxContext.DrawIndexed(indexCount, startIndex, baseVertex);
347 void ModelViewer::RenderLightShadows(GraphicsContext& gfxContext)
349 using namespace Lighting;
351 ScopedTimer _prof(L"RenderLightShadows", gfxContext);
353 static uint32_t LightIndex = 0;
354 if (LightIndex >= MaxLights)
355 return;
357 m_LightShadowTempBuffer.BeginRendering(gfxContext);
359 gfxContext.SetPipelineState(m_ShadowPSO);
360 RenderObjects(gfxContext, m_LightShadowMatrix[LightIndex], kOpaque);
361 gfxContext.SetPipelineState(m_CutoutShadowPSO);
362 RenderObjects(gfxContext, m_LightShadowMatrix[LightIndex], kCutout);
364 m_LightShadowTempBuffer.EndRendering(gfxContext);
366 gfxContext.TransitionResource(m_LightShadowTempBuffer, D3D12_RESOURCE_STATE_GENERIC_READ);
367 gfxContext.TransitionResource(m_LightShadowArray, D3D12_RESOURCE_STATE_COPY_DEST);
369 gfxContext.CopySubresource(m_LightShadowArray, LightIndex, m_LightShadowTempBuffer, 0);
371 gfxContext.TransitionResource(m_LightShadowArray, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
373 ++LightIndex;
376 void ModelViewer::RenderScene( void )
378 static bool s_ShowLightCounts = false;
379 if (ShowWaveTileCounts != s_ShowLightCounts)
381 static bool EnableHDR;
382 if (ShowWaveTileCounts)
384 EnableHDR = PostEffects::EnableHDR;
385 PostEffects::EnableHDR = false;
387 else
389 PostEffects::EnableHDR = EnableHDR;
391 s_ShowLightCounts = ShowWaveTileCounts;
394 GraphicsContext& gfxContext = GraphicsContext::Begin(L"Scene Render");
396 ParticleEffects::Update(gfxContext.GetComputeContext(), Graphics::GetFrameTime());
398 uint32_t FrameIndex = TemporalEffects::GetFrameIndexMod2();
400 struct DECLSPEC_ALIGN(16)
402 Vector3 sunDirection;
403 Vector3 sunLight;
404 Vector3 ambientLight;
405 float ShadowTexelSize[4];
407 float InvTileDim[4];
408 uint32_t TileCount[4];
409 uint32_t FirstLightIndex[4];
410 uint32_t FrameIndexMod2;
411 } psConstants;
413 psConstants.sunDirection = m_SunDirection;
414 psConstants.sunLight = Vector3(1.0f, 1.0f, 1.0f) * m_SunLightIntensity;
415 psConstants.ambientLight = Vector3(1.0f, 1.0f, 1.0f) * m_AmbientIntensity;
416 psConstants.ShadowTexelSize[0] = 1.0f / g_ShadowBuffer.GetWidth();
417 psConstants.InvTileDim[0] = 1.0f / Lighting::LightGridDim;
418 psConstants.InvTileDim[1] = 1.0f / Lighting::LightGridDim;
419 psConstants.TileCount[0] = Math::DivideByMultiple(g_SceneColorBuffer.GetWidth(), Lighting::LightGridDim);
420 psConstants.TileCount[1] = Math::DivideByMultiple(g_SceneColorBuffer.GetHeight(), Lighting::LightGridDim);
421 psConstants.FirstLightIndex[0] = Lighting::m_FirstConeLight;
422 psConstants.FirstLightIndex[1] = Lighting::m_FirstConeShadowedLight;
423 psConstants.FrameIndexMod2 = FrameIndex;
425 // Set the default state for command lists
426 auto pfnSetupGraphicsState = [&](void)
428 gfxContext.SetRootSignature(m_RootSig);
429 gfxContext.SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
430 gfxContext.SetIndexBuffer(m_Model.m_IndexBuffer.IndexBufferView());
431 gfxContext.SetVertexBuffer(0, m_Model.m_VertexBuffer.VertexBufferView());
434 pfnSetupGraphicsState();
436 RenderLightShadows(gfxContext);
439 ScopedTimer _prof(L"Z PrePass", gfxContext);
441 gfxContext.SetDynamicConstantBufferView(1, sizeof(psConstants), &psConstants);
444 ScopedTimer _prof(L"Opaque", gfxContext);
445 gfxContext.TransitionResource(g_SceneDepthBuffer, D3D12_RESOURCE_STATE_DEPTH_WRITE, true);
446 gfxContext.ClearDepth(g_SceneDepthBuffer);
448 #ifdef _WAVE_OP
449 gfxContext.SetPipelineState(EnableWaveOps ? m_DepthWaveOpsPSO : m_DepthPSO );
450 #else
451 gfxContext.SetPipelineState(m_DepthPSO);
452 #endif
453 gfxContext.SetDepthStencilTarget(g_SceneDepthBuffer.GetDSV());
454 gfxContext.SetViewportAndScissor(m_MainViewport, m_MainScissor);
455 RenderObjects(gfxContext, m_ViewProjMatrix, kOpaque );
459 ScopedTimer _prof(L"Cutout", gfxContext);
460 gfxContext.SetPipelineState(m_CutoutDepthPSO);
461 RenderObjects(gfxContext, m_ViewProjMatrix, kCutout );
465 SSAO::Render(gfxContext, m_Camera);
467 Lighting::FillLightGrid(gfxContext, m_Camera);
469 if (!SSAO::DebugDraw)
471 ScopedTimer _prof(L"Main Render", gfxContext);
473 gfxContext.TransitionResource(g_SceneColorBuffer, D3D12_RESOURCE_STATE_RENDER_TARGET, true);
474 gfxContext.ClearColor(g_SceneColorBuffer);
476 pfnSetupGraphicsState();
479 ScopedTimer _prof(L"Render Shadow Map", gfxContext);
481 m_SunShadow.UpdateMatrix(-m_SunDirection, Vector3(0, -500.0f, 0), Vector3(ShadowDimX, ShadowDimY, ShadowDimZ),
482 (uint32_t)g_ShadowBuffer.GetWidth(), (uint32_t)g_ShadowBuffer.GetHeight(), 16);
484 g_ShadowBuffer.BeginRendering(gfxContext);
485 gfxContext.SetPipelineState(m_ShadowPSO);
486 RenderObjects(gfxContext, m_SunShadow.GetViewProjMatrix(), kOpaque);
487 gfxContext.SetPipelineState(m_CutoutShadowPSO);
488 RenderObjects(gfxContext, m_SunShadow.GetViewProjMatrix(), kCutout);
489 g_ShadowBuffer.EndRendering(gfxContext);
492 if (SSAO::AsyncCompute)
494 gfxContext.Flush();
495 pfnSetupGraphicsState();
497 // Make the 3D queue wait for the Compute queue to finish SSAO
498 g_CommandManager.GetGraphicsQueue().StallForProducer(g_CommandManager.GetComputeQueue());
502 ScopedTimer _prof(L"Render Color", gfxContext);
504 gfxContext.TransitionResource(g_SSAOFullScreen, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
506 gfxContext.SetDynamicDescriptors(3, 0, _countof(m_ExtraTextures), m_ExtraTextures);
507 gfxContext.SetDynamicConstantBufferView(1, sizeof(psConstants), &psConstants);
508 #ifdef _WAVE_OP
509 gfxContext.SetPipelineState(EnableWaveOps ? m_ModelWaveOpsPSO : m_ModelPSO );
510 #else
511 gfxContext.SetPipelineState(ShowWaveTileCounts ? m_WaveTileCountPSO : m_ModelPSO);
512 #endif
513 gfxContext.TransitionResource(g_SceneDepthBuffer, D3D12_RESOURCE_STATE_DEPTH_READ);
514 gfxContext.SetRenderTarget(g_SceneColorBuffer.GetRTV(), g_SceneDepthBuffer.GetDSV_DepthReadOnly());
515 gfxContext.SetViewportAndScissor(m_MainViewport, m_MainScissor);
517 RenderObjects( gfxContext, m_ViewProjMatrix, kOpaque );
519 if (!ShowWaveTileCounts)
521 gfxContext.SetPipelineState(m_CutoutModelPSO);
522 RenderObjects( gfxContext, m_ViewProjMatrix, kCutout );
528 // Some systems generate a per-pixel velocity buffer to better track dynamic and skinned meshes. Everything
529 // is static in our scene, so we generate velocity from camera motion and the depth buffer. A velocity buffer
530 // is necessary for all temporal effects (and motion blur).
531 MotionBlur::GenerateCameraVelocityBuffer(gfxContext, m_Camera, true);
533 TemporalEffects::ResolveImage(gfxContext);
535 ParticleEffects::Render(gfxContext, m_Camera, g_SceneColorBuffer, g_SceneDepthBuffer, g_LinearDepth[FrameIndex]);
537 // Until I work out how to couple these two, it's "either-or".
538 if (DepthOfField::Enable)
539 DepthOfField::Render(gfxContext, m_Camera.GetNearClip(), m_Camera.GetFarClip());
540 else
541 MotionBlur::RenderObjectBlur(gfxContext, g_VelocityBuffer);
543 gfxContext.Finish();
546 void ModelViewer::CreateParticleEffects()
548 ParticleEffectProperties Effect = ParticleEffectProperties();
549 Effect.MinStartColor = Effect.MaxStartColor = Effect.MinEndColor = Effect.MaxEndColor = Color(1.0f, 1.0f, 1.0f, 0.0f);
550 Effect.TexturePath = "spark_tex.dds";
552 Effect.TotalActiveLifetime = FLT_MAX;
553 Effect.Size = Vector4(4.0f, 8.0f, 4.0f, 8.0f);
554 Effect.Velocity = Vector4(20.0f, 200.0f, 50.0f, 180.0f);
555 Effect.LifeMinMax = XMFLOAT2(1.0f, 3.0f);
556 Effect.MassMinMax = XMFLOAT2(4.5f, 15.0f);
557 Effect.EmitProperties.Gravity = XMFLOAT3(0.0f, -100.0f, 0.0f);
558 Effect.EmitProperties.FloorHeight = -0.5f;
559 Effect.EmitProperties.EmitPosW = Effect.EmitProperties.LastEmitPosW = XMFLOAT3(-1200.0f, 185.0f, -445.0f);
560 Effect.EmitProperties.MaxParticles = 800;
561 Effect.EmitRate = 64.0f;
562 Effect.Spread.x = 20.0f;
563 Effect.Spread.y = 50.0f;
564 ParticleEffects::InstantiateEffect( Effect );
566 ParticleEffectProperties Smoke = ParticleEffectProperties();
567 Smoke.TexturePath = "smoke.dds";
569 Smoke.TotalActiveLifetime = FLT_MAX;
570 Smoke.EmitProperties.MaxParticles = 25;
571 Smoke.EmitProperties.EmitPosW = Smoke.EmitProperties.LastEmitPosW = XMFLOAT3(1120.0f, 185.0f, -445.0f);
572 Smoke.EmitRate = 64.0f;
573 Smoke.LifeMinMax = XMFLOAT2(2.5f, 4.0f);
574 Smoke.Size = Vector4(60.0f, 108.0f, 30.0f, 208.0f);
575 Smoke.Velocity = Vector4(30.0f, 30.0f, 10.0f, 40.0f);
576 Smoke.MassMinMax = XMFLOAT2(1.0, 3.5);
577 Smoke.Spread.x = 60.0f;
578 Smoke.Spread.y = 70.0f;
579 Smoke.Spread.z = 20.0f;
580 ParticleEffects::InstantiateEffect( Smoke );
582 ParticleEffectProperties Fire = ParticleEffectProperties();
583 Fire.MinStartColor = Fire.MaxStartColor = Fire.MinEndColor = Fire.MaxEndColor = Color(8.0f, 8.0f, 8.0f, 0.0f);
584 Fire.TexturePath = "fire.dds";
586 Fire.TotalActiveLifetime = FLT_MAX;
587 Fire.Size = Vector4(54.0f, 68.0f, 0.1f, 0.3f);
588 Fire.Velocity = Vector4 (10.0f, 30.0f, 50.0f, 50.0f);
589 Fire.LifeMinMax = XMFLOAT2(1.0f, 3.0f);
590 Fire.MassMinMax = XMFLOAT2(10.5f, 14.0f);
591 Fire.EmitProperties.Gravity = XMFLOAT3(0.0f, 1.0f, 0.0f);
592 Fire.EmitProperties.EmitPosW = Fire.EmitProperties.LastEmitPosW = XMFLOAT3(1120.0f, 125.0f, 405.0f);
593 Fire.EmitProperties.MaxParticles = 25;
594 Fire.EmitRate = 64.0f;
595 Fire.Spread.x = 1.0f;
596 Fire.Spread.y = 60.0f;
597 ParticleEffects::InstantiateEffect( Fire );