@@ -59,13 +59,38 @@ void GameApp::Startup(void)
59
59
60
60
// 默认PSO
61
61
m_mapPSO[E_EPT_DEFAULT] = defaultPSO;
62
+
63
+ // 模板PSO 禁止深度写入。如果通过了深度+模板测试,则在对应的模板中写入预设值
64
+ GraphicsPSO stencilTestPSO = defaultPSO;
65
+ stencilTestPSO.SetDepthStencilState (Graphics::StencilStateTest);
66
+ stencilTestPSO.Finalize ();
67
+ m_mapPSO[E_EPT_STENCILTEST] = stencilTestPSO;
68
+
69
+ // 模板绘制PSO 通过上一步写入了值,这一步进行判断,如果当前像素的模板值等于预设值,则通过测试
70
+ // 因为要绘制镜子中的物体,所以需要顶点反向
71
+ GraphicsPSO stencilDrawPSO = defaultPSO;
72
+ stencilDrawPSO.SetRasterizerState (Graphics::RasterizerDefault);
73
+ stencilDrawPSO.SetDepthStencilState (Graphics::StencilStateTestEqual);
74
+ stencilDrawPSO.Finalize ();
75
+ m_mapPSO[E_EPT_STENCILDRAW] = stencilDrawPSO;
76
+
77
+ // 透明PSO 绘制半透明的镜子
78
+ GraphicsPSO transparencyPSO = defaultPSO;
79
+ auto blend = Graphics::BlendTraditional;
80
+ // 目标的alpha用0,这样透过去的目标就不再变淡了
81
+ blend.RenderTarget [0 ].DestBlendAlpha = D3D12_BLEND_ZERO;
82
+ transparencyPSO.SetBlendState (blend);
83
+ transparencyPSO.Finalize ();
84
+ m_mapPSO[E_EPT_TRANSPARENT] = transparencyPSO;
62
85
}
63
86
64
87
void GameApp::Cleanup (void )
65
88
{
66
89
m_mapGeometries.clear ();
67
90
m_mapMaterial.clear ();
68
91
m_mapPSO.clear ();
92
+
93
+ m_vecAll.clear ();
69
94
}
70
95
71
96
void GameApp::Update (float deltaT)
@@ -171,7 +196,14 @@ void GameApp::updateSkull(float deltaT)
171
196
auto rotationMatrix = Math::AffineTransform::MakeYRotation (Math::XM_PIDIV2);
172
197
auto scallMatrix = Math::AffineTransform::MakeScale ({ 0 .45f , 0 .45f , 0 .45f });
173
198
auto translateMatrix = Math::AffineTransform::MakeTranslation (mSkullTranslation );
174
- mSkullRitem ->modeToWorld = Math::Transpose (Math::Matrix4 (translateMatrix * scallMatrix * rotationMatrix));
199
+ auto world = Math::Matrix4 (translateMatrix * scallMatrix * rotationMatrix);
200
+ mSkullRitem ->modeToWorld = Math::Transpose (world);
201
+
202
+ // xy平面
203
+ XMVECTOR mirrorPlane = XMVectorSet (0 .0f , 0 .0f , 1 .0f , 0 .0f );
204
+ XMMATRIX R = XMMatrixReflect (mirrorPlane);
205
+ mReflectedSkullRitem ->modeToWorld = Math::Transpose (Math::Matrix4 (R) * world);
206
+ mReflectedFloorlRItem ->modeToWorld = Math::Transpose (Math::Matrix4 (R));
175
207
}
176
208
177
209
void GameApp::RenderScene (void )
@@ -185,40 +217,49 @@ void GameApp::RenderScene(void)
185
217
gfxContext.ClearColor (Graphics::g_SceneColorBuffer);
186
218
187
219
gfxContext.TransitionResource (Graphics::g_SceneDepthBuffer, D3D12_RESOURCE_STATE_DEPTH_WRITE, true );
188
- gfxContext.ClearDepth (Graphics::g_SceneDepthBuffer);
220
+ gfxContext.ClearDepthAndStencil (Graphics::g_SceneDepthBuffer);
189
221
190
222
gfxContext.SetRenderTarget (Graphics::g_SceneColorBuffer.GetRTV (), Graphics::g_SceneDepthBuffer.GetDSV ());
191
223
192
- // 设置渲染流水线
193
- gfxContext.SetPipelineState (m_mapPSO[E_EPT_DEFAULT]);
194
-
195
224
// 设置根签名
196
225
gfxContext.SetRootSignature (m_RootSignature);
197
226
// 设置顶点拓扑结构
198
227
gfxContext.SetPrimitiveTopology (D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
199
228
200
- // 设置通用的常量缓冲区
201
- PassConstants psc;
202
- psc.viewProj = Transpose (m_ViewProjMatrix);
203
- psc.eyePosW = m_Camera.GetPosition ();
204
- psc.ambientLight = { 0 .25f , 0 .25f , 0 .35f , 1 .0f };
205
- psc.Lights [0 ].Direction = { 0 .57735f , -0 .57735f , 0 .57735f };
206
- psc.Lights [0 ].Strength = { 0 .6f , 0 .6f , 0 .6f };
207
- psc.Lights [1 ].Direction = { -0 .57735f , -0 .57735f , 0 .57735f };
208
- psc.Lights [1 ].Strength = { 0 .3f , 0 .3f , 0 .3f };
209
- psc.Lights [2 ].Direction = { 0 .0f , -0 .707f , -0 .707f };
210
- psc.Lights [2 ].Strength = { 0 .15f , 0 .15f , 0 .15f };
211
- gfxContext.SetDynamicConstantBufferView (1 , sizeof (psc), &psc);
229
+ // 设置显示物体的常量缓冲区
230
+ setLightContantsBuff (gfxContext);
212
231
213
232
// 开始绘制
233
+ // 渲染普通目标
234
+ gfxContext.SetPipelineState (m_mapPSO[E_EPT_DEFAULT]);
214
235
drawRenderItems (gfxContext, m_vecRenderItems[(int )RenderLayer::Opaque]);
215
236
237
+ // 设置模板写入PSO,对于镜子区域,进行模板+深度测试,通过的话,在模板缓冲区写入1
238
+ gfxContext.SetStencilRef (1 );
239
+ gfxContext.SetPipelineState (m_mapPSO[E_EPT_STENCILTEST]);
240
+ drawRenderItems (gfxContext, m_vecRenderItems[(int )RenderLayer::Mirrors]);
241
+
242
+ // 设置镜中物体的常量缓冲区
243
+ setLightContantsBuff (gfxContext, true );
244
+
245
+ // 绘制镜中物体,只有通过了模板测试,也就是会处于镜中才会绘制
246
+ gfxContext.SetPipelineState (m_mapPSO[E_EPT_STENCILDRAW]);
247
+ drawRenderItems (gfxContext, m_vecRenderItems[(int )RenderLayer::Reflected]);
248
+ gfxContext.SetStencilRef (0 );
249
+
250
+ // 设置显示物体的常量缓冲区
251
+ setLightContantsBuff (gfxContext);
252
+
253
+ // 绘制镜子
254
+ gfxContext.SetPipelineState (m_mapPSO[E_EPT_TRANSPARENT]);
255
+ drawRenderItems (gfxContext, m_vecRenderItems[(int )RenderLayer::Transparent]);
256
+
216
257
gfxContext.TransitionResource (Graphics::g_SceneColorBuffer, D3D12_RESOURCE_STATE_PRESENT);
217
258
218
259
gfxContext.Finish (true );
219
260
}
220
261
221
- void GameApp::drawRenderItems (GraphicsContext& gfxContext, std::vector<std::unique_ptr< RenderItem> >& ritems)
262
+ void GameApp::drawRenderItems (GraphicsContext& gfxContext, std::vector<RenderItem* >& ritems)
222
263
{
223
264
for (auto & item : ritems)
224
265
{
@@ -248,6 +289,40 @@ void GameApp::drawRenderItems(GraphicsContext& gfxContext, std::vector<std::uniq
248
289
}
249
290
}
250
291
292
+ void GameApp::setLightContantsBuff (GraphicsContext& gfxContext, bool inMirror /* = false */ )
293
+ {
294
+ if (!inMirror)
295
+ {
296
+ // 设置通用的常量缓冲区
297
+ PassConstants psc;
298
+ psc.viewProj = Transpose (m_ViewProjMatrix);
299
+ psc.eyePosW = m_Camera.GetPosition ();
300
+ psc.ambientLight = { 0 .25f , 0 .25f , 0 .35f , 1 .0f };
301
+ psc.Lights [0 ].Direction = { 0 .57735f , -0 .57735f , 0 .57735f };
302
+ psc.Lights [0 ].Strength = { 0 .6f , 0 .6f , 0 .6f };
303
+ psc.Lights [1 ].Direction = { -0 .57735f , -0 .57735f , 0 .57735f };
304
+ psc.Lights [1 ].Strength = { 0 .3f , 0 .3f , 0 .3f };
305
+ psc.Lights [2 ].Direction = { 0 .0f , -0 .707f , -0 .707f };
306
+ psc.Lights [2 ].Strength = { 0 .15f , 0 .15f , 0 .15f };
307
+ gfxContext.SetDynamicConstantBufferView (1 , sizeof (psc), &psc);
308
+ }
309
+ else
310
+ {
311
+ // 设置镜子中的光照,偷个懒,直接设置了
312
+ PassConstants psc;
313
+ psc.viewProj = Transpose (m_ViewProjMatrix);
314
+ psc.eyePosW = m_Camera.GetPosition ();
315
+ psc.ambientLight = { 0 .25f , 0 .25f , 0 .35f , 1 .0f };
316
+ psc.Lights [0 ].Direction = { 0 .57735f , -0 .57735f , -0 .57735f };
317
+ psc.Lights [0 ].Strength = { 0 .6f , 0 .6f , 0 .6f };
318
+ psc.Lights [1 ].Direction = { -0 .57735f , -0 .57735f , -0 .57735f };
319
+ psc.Lights [1 ].Strength = { 0 .3f , 0 .3f , 0 .3f };
320
+ psc.Lights [2 ].Direction = { 0 .0f , -0 .707f , 0 .707f };
321
+ psc.Lights [2 ].Strength = { 0 .15f , 0 .15f , 0 .15f };
322
+ gfxContext.SetDynamicConstantBufferView (1 , sizeof (psc), &psc);
323
+ }
324
+ }
325
+
251
326
void GameApp::buildRoomGeo ()
252
327
{
253
328
// Create and specify geometry. For this sample we draw a floor
@@ -448,7 +523,7 @@ void GameApp::buildRenderItem()
448
523
floorRItem->BaseVertexLocation = m_mapGeometries[" roomGeo" ]->geoMap [" floor" ].BaseVertexLocation ;
449
524
floorRItem->geo = m_mapGeometries[" roomGeo" ].get ();
450
525
floorRItem->mat = m_mapMaterial[" checkertile" ].get ();
451
- m_vecRenderItems[(int )RenderLayer::Opaque].push_back (std::move ( floorRItem));
526
+ m_vecRenderItems[(int )RenderLayer::Opaque].push_back (floorRItem. get ( ));
452
527
453
528
// 墙壁
454
529
auto wallRItem = std::make_unique<RenderItem>();
@@ -457,16 +532,7 @@ void GameApp::buildRenderItem()
457
532
wallRItem->BaseVertexLocation = m_mapGeometries[" roomGeo" ]->geoMap [" wall" ].BaseVertexLocation ;
458
533
wallRItem->geo = m_mapGeometries[" roomGeo" ].get ();
459
534
wallRItem->mat = m_mapMaterial[" bricks" ].get ();
460
- m_vecRenderItems[(int )RenderLayer::Opaque].push_back (std::move (wallRItem));
461
-
462
- // 镜子
463
- auto mirrorRItem = std::make_unique<RenderItem>();
464
- mirrorRItem->IndexCount = m_mapGeometries[" roomGeo" ]->geoMap [" mirror" ].IndexCount ;
465
- mirrorRItem->StartIndexLocation = m_mapGeometries[" roomGeo" ]->geoMap [" mirror" ].StartIndexLocation ;
466
- mirrorRItem->BaseVertexLocation = m_mapGeometries[" roomGeo" ]->geoMap [" mirror" ].BaseVertexLocation ;
467
- mirrorRItem->geo = m_mapGeometries[" roomGeo" ].get ();
468
- mirrorRItem->mat = m_mapMaterial[" icemirror" ].get ();
469
- m_vecRenderItems[(int )RenderLayer::Opaque].push_back (std::move (mirrorRItem));
535
+ m_vecRenderItems[(int )RenderLayer::Opaque].push_back (wallRItem.get ());
470
536
471
537
// skull
472
538
auto skullRItem = std::make_unique<RenderItem>();
@@ -476,5 +542,42 @@ void GameApp::buildRenderItem()
476
542
skullRItem->geo = m_mapGeometries[" skullGeo" ].get ();
477
543
skullRItem->mat = m_mapMaterial[" skullMat" ].get ();
478
544
mSkullRitem = skullRItem.get ();
479
- m_vecRenderItems[(int )RenderLayer::Opaque].push_back (std::move (skullRItem));
545
+ m_vecRenderItems[(int )RenderLayer::Opaque].push_back (skullRItem.get ());
546
+
547
+ // 镜子
548
+ auto mirrorRItem = std::make_unique<RenderItem>();
549
+ mirrorRItem->IndexCount = m_mapGeometries[" roomGeo" ]->geoMap [" mirror" ].IndexCount ;
550
+ mirrorRItem->StartIndexLocation = m_mapGeometries[" roomGeo" ]->geoMap [" mirror" ].StartIndexLocation ;
551
+ mirrorRItem->BaseVertexLocation = m_mapGeometries[" roomGeo" ]->geoMap [" mirror" ].BaseVertexLocation ;
552
+ mirrorRItem->geo = m_mapGeometries[" roomGeo" ].get ();
553
+ mirrorRItem->mat = m_mapMaterial[" icemirror" ].get ();
554
+ m_vecRenderItems[(int )RenderLayer::Mirrors].push_back (mirrorRItem.get ());
555
+ m_vecRenderItems[(int )RenderLayer::Transparent].push_back (mirrorRItem.get ());
556
+
557
+ // 镜子中的skull
558
+ auto reflectedSkullRItem = std::make_unique<RenderItem>();
559
+ reflectedSkullRItem->IndexCount = m_mapGeometries[" skullGeo" ]->geoMap [" skull" ].IndexCount ;
560
+ reflectedSkullRItem->StartIndexLocation = m_mapGeometries[" skullGeo" ]->geoMap [" skull" ].StartIndexLocation ;
561
+ reflectedSkullRItem->BaseVertexLocation = m_mapGeometries[" skullGeo" ]->geoMap [" skull" ].BaseVertexLocation ;
562
+ reflectedSkullRItem->geo = m_mapGeometries[" skullGeo" ].get ();
563
+ reflectedSkullRItem->mat = m_mapMaterial[" skullMat" ].get ();
564
+ mReflectedSkullRitem = reflectedSkullRItem.get ();
565
+ m_vecRenderItems[(int )RenderLayer::Reflected].push_back (reflectedSkullRItem.get ());
566
+
567
+ // 镜子中的floor
568
+ auto reflectedFloorlRItem = std::make_unique<RenderItem>();
569
+ reflectedFloorlRItem->IndexCount = m_mapGeometries[" roomGeo" ]->geoMap [" floor" ].IndexCount ;
570
+ reflectedFloorlRItem->StartIndexLocation = m_mapGeometries[" roomGeo" ]->geoMap [" floor" ].StartIndexLocation ;
571
+ reflectedFloorlRItem->BaseVertexLocation = m_mapGeometries[" roomGeo" ]->geoMap [" floor" ].BaseVertexLocation ;
572
+ reflectedFloorlRItem->geo = m_mapGeometries[" roomGeo" ].get ();
573
+ reflectedFloorlRItem->mat = m_mapMaterial[" checkertile" ].get ();
574
+ mReflectedFloorlRItem = reflectedFloorlRItem.get ();
575
+ m_vecRenderItems[(int )RenderLayer::Reflected].push_back (reflectedFloorlRItem.get ());
576
+
577
+ m_vecAll.push_back (std::move (floorRItem));
578
+ m_vecAll.push_back (std::move (wallRItem));
579
+ m_vecAll.push_back (std::move (skullRItem));
580
+ m_vecAll.push_back (std::move (mirrorRItem));
581
+ m_vecAll.push_back (std::move (reflectedSkullRItem));
582
+ m_vecAll.push_back (std::move (reflectedFloorlRItem));
480
583
}
0 commit comments