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.
9 // Developed by Minigraph
11 // Author(s): Alex Nankervis
16 #include "GraphicsCore.h"
17 #include "CameraController.h"
18 #include "BufferManager.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"
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.
41 #include "compiled_shaders/DepthViewerVS.h"
42 #include "compiled_shaders/DepthViewerPS.h"
43 #include "compiled_shaders/ModelViewerVS.h"
44 #include "compiled_shaders/ModelViewerPS.h"
46 #include "compiled_shaders/DepthViewerVS_SM6.h"
47 #include "compiled_shaders/ModelViewerVS_SM6.h"
48 #include "compiled_shaders/ModelViewerPS_SM6.h"
50 #include "compiled_shaders/WaveTileCountPS.h"
52 using namespace GameCore
;
54 using namespace Graphics
;
56 class ModelViewer
: public GameCore::IGameApp
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
;
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();
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
;
86 GraphicsPSO m_DepthWaveOpsPSO
;
87 GraphicsPSO m_ModelWaveOpsPSO
;
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];
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);
118 BoolVar
EnableWaveOps("Application/Forward+/Enable Wave Ops", true);
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();
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();
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();
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;
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;
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 )
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
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
)
309 Matrix4 modelToProjection
;
310 Matrix4 modelToShadow
;
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
) )
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
)
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
);
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;
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
;
404 Vector3 ambientLight
;
405 float ShadowTexelSize
[4];
408 uint32_t TileCount
[4];
409 uint32_t FirstLightIndex
[4];
410 uint32_t FrameIndexMod2
;
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
);
449 gfxContext
.SetPipelineState(EnableWaveOps
? m_DepthWaveOpsPSO
: m_DepthPSO
);
451 gfxContext
.SetPipelineState(m_DepthPSO
);
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
)
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
);
509 gfxContext
.SetPipelineState(EnableWaveOps
? m_ModelWaveOpsPSO
: m_ModelPSO
);
511 gfxContext
.SetPipelineState(ShowWaveTileCounts
? m_WaveTileCountPSO
: m_ModelPSO
);
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());
541 MotionBlur::RenderObjectBlur(gfxContext
, g_VelocityBuffer
);
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
);