aL3*_*891 6 directx optimization directx-11 depth-buffer depth-testing
作为一个DirectX noob,我试图将我的头部包裹在深度缓冲区周围,特别是如何为遮挡像素调用像素着色器.
根据我的理解,光栅化器为覆盖绘制的原始图像的每个像素调用像素着色器,然后在输出合并阶段,输出合并器检查深度缓冲区并丢弃,写入或混合后面缓冲区中的像素.
这看起来很浪费,但是如果我在一个非常复杂的对象前面渲染一个简单的不透明对象,那么让光栅化器检查深度图是有用的甚至在调用复杂对象的像素着色器之前.
做研究我发现早期Z测试/保守Z测试等等,但似乎也没有关于它的文档.我找了一种在rasterizer状态desc对象上配置它的方法,但我只在OM状态desc上找到了类似的东西.
似乎可以在DX9中使用SetRenderState进行设置(尽管我没有使用DX9的经验)
根据我的研究,如果我从前到后渲染对象,这似乎是某些硬件才会这样做,这是正确的吗?我怎么能说出来?所有的Control DirectX都让你看起来很奇怪,因为它似乎是一个很好的优化:)
关于此的任何信息或参考都是适用的
Ada*_*les 22
就深度测试而言,DirectX声称在像素着色器之后必须出现深度测试,它并没有说实际上必须这样做.实际上,早期z已经在许多制造商的硬件上存在多年.通常有一种早于早期的Z测试形式称为Hierarchical Z,它不是在单个像素上运行,而是在一次运行许多像素的"瓦片"上,以避免早期Z的成本.
早期Z不是您可以通过在设备上设置的任何特定状态打开或关闭的东西.硬件将尽可能早地执行z测试,并且您不知道它在像素着色器之后的任何地方.
有些事情你可以做,虽然这可能会限制硬件能够尽早进行z测试.Alpha测试,使用'discard'(杀死像素)和alpha覆盖都将禁用早期z写入,因为在硬件可以确定是否写入深度值之前需要运行像素着色器.如果你正在使用alpha测试/丢弃并且不需要z-writes,那么关闭它们就可以获得早期z可用的最佳机会.
如果你想要早期Z,在像素着色器中修改/写入"深度"肯定是禁止的.在这种情况下,硬件甚至不能执行早期测试,因为它还没有意识到像素的深度是什么,直到你已经在像素着色器中决定它,它既不能执行早期的z测试,也不能执行早期的z写操作.
如果您需要从像素着色器写入深度,但可以保证您只会写入一个大于或等于光栅化器生成的深度值,您可以使用相当未记录的SV_DepthGreater输出语义.由于您承诺不写入小于内插深度的深度值,硬件仍然可以尝试执行早期z测试,但是然后将z写入推迟到像素着色器结束.(SV_DepthLessEqual如果碰巧使用倒置的z-test/z-buffer,则有一个等价物).
由于必须看到z测试发生在管道的末端,因此在像素着色器中使用UAV也会禁用early-z.由于渲染目标现在不是唯一的输出,并且由于DirectX规范表明必须在最后发生z测试,因此即使对于最终未通过z测试的像素,也应该发生UAV写入.出于这个原因,在Shader Model 5中添加了一个名为[earlydepthstencil]的属性,该属性告诉DirectX你很高兴早期z发生(如果可能的话)而不是运行像素着色器,即使你已经发生无人机写入.
总而言之,如果你没有做上面提到的任何略微古怪的事情(使用SV_DEPTH修改深度,使用剪辑/丢弃等修改alpha),那么你很可能已经获得了早期Z的好处.如果您不想要它们,请务必关闭z-writes,并且不要写入SV_DEPTH,因为绝对没有办法在早期启用z-z.