我正在使用 Direct3D 11 和 HLSL。我使用四种不同的着色器(顶点、外壳、域和像素)。
我总是在我的着色器中使用正确的坐标空间时遇到麻烦。有人可以为顶点、外壳、域和像素着色器阶段确定适当的空间吗?
我正在使用 Direct3D 11 和 HLSL。我使用四种不同的着色器(顶点、外壳、域和像素)。
我总是在我的着色器中使用正确的坐标空间时遇到麻烦。有人可以为顶点、外壳、域和像素着色器阶段确定适当的空间吗?
在任何着色器中使用什么样的空间都没有限制——你可以自由使用任何适合你的目的。事实上,在同一个舞台内使用多个空间是很常见的——例如,使用光源的世界空间坐标来计算像素着色器中的光照。唯一的要求是将 SV_Position 发送到剪辑空间中的光栅化器中,所以无论你最后一个阶段是在光栅化之前做什么,都需要这样做。
通常,顶点在补丁空间中流入顶点着色器,这是一种局部坐标系,描述要细分的区域(补丁),但可能不描述模型本身(多边形)。外壳和域着色器在这些补丁上工作。外壳着色器在补丁空间中运行,而域着色器在补丁空间中运行一半,从外壳着色器控制点函数(控制点是“补丁级别顶点”)传递,一半在补丁的切线空间中(即在补丁的平面上)。这使您可以了解新顶点相对于面片控制点的位置。曲面细分完成后,如果您没有几何着色器,模型可以在投影空间中,如果有,则可以在模型空间中。然后几何着色器可以从模型中添加或减去顶点,将结果转换到投影空间,然后将它们传递给像素着色器。最后一个阶段,像素着色器,通常在屏幕空间中运行(即,如果您查询 SV_Position,它将在屏幕空间中)。
虽然这些很常见,但您也可以直接指定投影空间中的坐标(如果它对算法更方便的话)、世界空间、局部空间、变换的局部空间、切线空间、法线空间、光照空间......真的是你想要的任何东西喜欢。我列出的典型管道空间只是一个例子。这真的取决于你。
这是我从 Josh Petrie 那里得到的关于 Gamedev 的答案:
顶点着色器从顶点缓冲区(通常在模型空间中)获取输入数据,转换该输入,并在剪辑空间中生成输出数据。在顶点着色器阶段之后,发生透视划分(通过输出 w 坐标)。
像素着色器处理片段,而不是顶点,但是当您使用坐标时(例如通过 SV_Position),这些坐标位于屏幕空间中(偏移 0.5)。这意味着它们的范围从零到一。
外壳和域着色器对输入数据进行操作并在同一空间内生成输出数据。因为输入数据通常在模型空间中,所以输出数据也在模型空间中。
也就是说,这些只是规范的默认值。由于您正在控制输入数据和对该输入数据的解释,因此您可以将该数据放置在对您有用的任何坐标系中。例如,当在 3D API 中伪造 2D 图形时,将像素坐标输入数据简单地放入顶点缓冲区并拥有一个非常简单、几乎无操作的顶点着色器会很有用。
不过,流水线的某些方面超出了您的可编程控制范围。例如,SV_Position 将始终是偏移屏幕空间。最需要担心的实际上是顶点着色器阶段的输出。管道的其余部分将假设输出在剪辑空间中,执行剪辑,并执行 w 的透视除法。因此,如果您想“避免”这种划分,您可能需要相应地设置 w(通常为 1.0)。