d3d12龙书学习之MiniEngine的最小化实现(十六) 龙书第20章 阴影贴图 Shadow Map

文章目录

  • shadow map技术简介
  • MiniEngine中的shadowBuffer
  • MiniEngine中的shadowCamera
  • 调试以及知其然而不知所以然的魔改过程
  • 柱子上没有影子?
  • 总结

shadow map技术简介

Shadow Map网上有大把的技术文档。

简单说就是设置一个camera到需要产生阴影的光源位置,根据光源类型有不同的camera类型。
使用这个camera观察世界,生成深度图。
回到真正的camera那里,在绘制世界的时候,判断当前顶点的深度与深度图上对应位置的值。

如果顶点深度小于(根据设置,也可以大于)深度图的值,代表没有被遮挡,否则代表在阴影中。

MiniEngine中的shadowBuffer

本身就是一个深度缓冲区。稍微封装了下,方便绘制阴影深度图到buffer中

MiniEngine中的shadowCamera

这个camera啊,一直没看懂,根据官方的例子,始终无法实现正常的阴影。
考虑到camera本身已经被修改过,所以这个shadwoCamera也要修改

调试以及知其然而不知所以然的魔改过程

做好后,发现没有阴影。

两个怀疑点

  1. 阴影pso参数错误
  2. shadowCamera错误

对于1,修改了很多参数,发现也没有什么用。
于是开始调试2

  1. 场景中仅保留一个渲染目标,方便进行图形调试
  2. 设置阴影绘制的shadowCamera为正常的camera,发现可以绘制出阴影图。确定是shadowCamera的问题
  3. 研究shadowCamera的代码。发现看不明白
  4. 最后决定直接把shadowCamera魔改下。当然并没有按照d3d12book一样采用正交摄像机。暂时还是用的透视
void GameCore::ShadowCamera::UpdateMatrix(
    Vector3 LightDirection, Vector3 ShadowCenter, Vector3 ShadowBounds,
    uint32_t BufferWidth, uint32_t BufferHeight, uint32_t BufferPrecision )
{
    SetLookDirection(LightDirection, Vector3(kYUnitVector) );

    // Converts world units to texel units so we can quantize the camera position to whole texel units
    Vector3 RcpDimensions = Recip(ShadowBounds);
    Vector3 QuantizeScale = Vector3((float)BufferWidth, (float)BufferHeight, (float)((1 << BufferPrecision) - 1)) * RcpDimensions;

    SetPosition(-LightDirection * ShadowBounds.GetX() / 2.0f);

    // 看不懂原先的代码什么意思, 所以暂时直接改成这样吧
//     // Transform to view space
//     ShadowCenter = ~GetRotation() * ShadowCenter;
//     // Scale to texel units, truncate fractional part, and scale back to world units
//     ShadowCenter = Floor(ShadowCenter * QuantizeScale) / QuantizeScale;
//     // Transform back into world space
//     ShadowCenter = GetRotation() * ShadowCenter;
// 
//     SetPosition(ShadowCenter);

    SetProjMatrix( Matrix4::MakeScale(Vector3(2.0f, 2.0f, 1.0f) * RcpDimensions) );

    Update();

    // Transform from clip space to texture space
    m_ShadowMatrix =  Matrix4( AffineTransform( Matrix3::MakeScale( 0.5f, -0.5f, 1.0f ), Vector3(0.5f, 0.5f, 0.0f) ) ) * m_ViewProjMatrix;
}

原先阴影摄像机这个中心点很诡异,考虑到原本为右手坐标系,而且本身我修改过baseCamera代码。这里暂时也就不纠结了。改成我喜欢的一种简单的方式来实现就可以了。

简单跑一下,发现阴影正常了。不错。

柱子上没有影子?

结果发现柱子上没有影子。对于pso的参数,文档也极少。
尝试修改下,发现成功了

RasterizerShadow.SlopeScaledDepthBias = 1.5f;
RasterizerShadow.DepthBias = 100;

总结

以前看过一篇文章,讲这个程序员有一类是这样的,靠瞎蒙编程。蒙对了就不管了。
我现在学dx12就是这么个过程。
对于dx12很多的参数做不到理解,也找不到说明什么的。

不管怎么样,还是要一步一步慢慢地走。我觉得坑踩多了,自然而然就会有一些理解了,期间也要继续学习dx12相关的一些知识。

效果图:

你可能感兴趣的:(DirectX12,龙书学习)