从剪辑空间到屏幕坐标的转换是在什么时候发生的?

38
我正在研究渲染流水线,在剪裁阶段时解释说,从视图(眼睛或相机)空间中,我们必须传递到剪辑空间,也称为归一化设备空间(NDC),这是一个从-1到1的立方空间。
然而,现在我不明白从这个空间到屏幕坐标空间的转换是在何时进行的:
  1. 剪裁之后、光栅化之前吗?

  2. 光栅化之后、剪切和z测试之前吗?

  3. 最后在写入帧缓冲器之前?

5个回答

66
不,剪裁空间和NDC空间不是同一回事。
剪裁空间实际上距离NDC只有一个步骤,所有坐标都被除以Clip.W以产生NDC。在结果NDC空间中范围在[-1,1]之外的任何东西都对应于位于剪切体积之外的点。在NDC之前的坐标空间被称为剪裁空间有其原因 ;)
严格来说,然而,NDC空间不一定是立方体的。在OpenGL中,NDC空间确实是一个立方体,但在Direct3D中并非如此。在D3D中,NDC空间中的Z坐标范围为0.01.0,而在GL中范围从-1.01.0。X和Y在GL和D3D中的行为相同(即它们的范围从-1.01.0)。NDC是一个标准的坐标空间,但在不同的API中具有不同的表示方法。
最后,从NDC空间到屏幕空间(也称为窗口空间)发生在光栅化期间,并由您的视口和深度范围定义。在任何其他坐标空间中,片段位置确实毫无意义,这就是光栅化产生的片段

更新:

在OpenGL 4.5中引入了扩展GL_ARB_clip_control,允许您在GL中采用D3D的NDC约定。


传统的OpenGL行为是:

glClipControl (GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE);

可以通过以下方式实现Direct3D行为:

glClipControl (GL_UPPER_LEFT, GL_ZERO_TO_ONE); // Y-axis is inverted in D3D

1
剪裁空间和NDC不是同一件事,否则它们就不会有不同的名称。剪裁空间是指点经过投影矩阵的点变换之后但在w归一化之前所处的空间。NDC空间是指点在w归一化之后所处的空间。http://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/projection-matrix-GPU-rendering-pipeline-clipping - user18490
13
这个答案可能会有点误导。剪裁空间和NDC从概念上讲是相同的,只是用不同的形式表示 - 一个是齐次坐标,另一个是笛卡尔坐标。这种转换中唯一失去的是表示无穷远点的能力。因此,虽然它们在实践中是不同的事物(也就是说,你必须执行一个操作才能从一个转换到另一个),但它们有效地代表了相同的基础模型。 - Joseph Mansfield
1
我认为它比那简单多了。它与我所谓的二维投影空间无关。相反,它仅仅是代表相机视野的体积。在剪辑空间内的物体对相机可见。在剪辑空间之外的物体则不可见。这与二维透视投影无关。进一步阅读后,发现剪辑空间与NDS相同。在二维透视空间中,如果一个物体的x和y坐标在屏幕尺寸范围内,你可以轻松地判断它是否在视野内。因此,你需要两次使用二维透视空间。 - marshal craft
2
这是正确的,但关于剪裁空间的事情是,它不是标准化的 :) w 坐标定义了剪裁体在剪裁空间和 NDC 空间中的范围,但在 NDC 空间中,w1.0 并且所有内容都已经被标准化。在剪裁空间中,每个顶点可以存在自己的比例,由不同的 w 坐标定义;一旦转换到 NDC 空间中,所有顶点都达成一致并且更容易处理。 - Andon M. Coleman
2
@AndonM.Coleman - 感谢您非常有用的评论!我仍然有疑问,您能帮忙吗?基本上我在网上找到的所有来源(参考链接)都将NDC空间显示为一个立方体。那么我应该如何看待剪裁空间呢?它也是一个立方体,还是像眼睛空间一样的透视棱锥体(因为在其中我们可以表示无限远点)?并且,从剪辑空间到NDC的操作是否正确地将第一个中的射线映射到第二个中的点,还是1对1的? - Matteo
1
是的,根据定义,剪裁空间必须是一个立方体,如果你在x/y/z范围内的值为+/-w,那就是一个立方体。它通常的工作方式是(透视)投影矩阵将基于z的值定义不同的w值--这就是透视的来源,但它不是剪裁空间的自动部分。经过透视除法后,一旦所有内容都在NDC空间中,透视会导致具有不同剪裁空间w坐标的任何顶点扩散开来。正交投影在剪裁空间中同样有效,并且不会导致这种情况。 - Andon M. Coleman

11

“剪辑空间”和“标准化设备坐标”并不是同一个概念,否则它们就不会有不同的名称。

“剪辑空间”是指经过投影矩阵变换后,但在通过 w 标准化之前的点的坐标系。

“标准化设备坐标”是指经过通过 w 标准化后的点的坐标系。

http://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/projection-matrix-GPU-rendering-pipeline-clipping

Camera space --> 
x projection matrix ---> 
Clip space (before normalisation) --->
Clipping ---> 
Normalisation by w (x/w, y/w, z/w) --->
NDC space (in the range [-1, 1] in x and y)

21
不是要挑剔,但有很多坐标系有多个名称。例如,视点空间、观察空间和相机空间都不幸指的是同一件事情。窗口空间和屏幕空间也是同一个东西的两个词。_NDC和剪裁空间绝对不是指相同的事情,这是真的。_请注意,以上只是简单翻译,没有解释或添加额外内容。 - Andon M. Coleman
6
将每个组件除以“w”组件的步骤不叫做“标准化”,而被称为“透视除法”,其目的是将顶点从齐次空间转换为笛卡尔空间(即投影它们)。虽然它们最终出现在规范化设备空间中,但这并不意味着这些顶点已经被“标准化”了。实际上,对一个表示为向量的顶点进行归一化是完全不同的事情。 - code_dredd

2
显然,根据苹果公司的说法,剪辑空间与标准化设备坐标(NDC)相同。

https://developer.apple.com/documentation/metal/hello_triangle

“引用:”
“顶点函数(也称为顶点着色器)的主要任务是处理传入的顶点数据,并将每个顶点映射到视口中的位置。这样,管道中的后续阶段可以引用此视口位置,并将像素渲染到可绘制的确切位置。顶点函数通过将任意顶点坐标转换为归一化设备坐标(也称为裁剪空间坐标)来完成此任务。”
“另一个来自示例代码注释的引用:”
“每个顶点着色器的输出位置都在裁剪空间(也称为归一化设备坐标空间或NDC)中。”
“也许这是因为教程是在2D环境下?这些陈述有误导性。”

1
《OpenGL超级宝典第6版》- 第64页:“_剪裁空间_: 将顶点映射到非线性齐次坐标后的位置。_标准化设备坐标(NDC)空间_: 顶点坐标在其剪裁空间坐标除以其自身w分量后被认为处于NDC中。” - Drout
是的,对我来说剪辑空间在剪辑之前而不是之后。但在2D应用程序或正交投影中,结果是相同的。 - Siamaster
在剪裁之前和之后,您都处于剪辑空间中。剪辑坐标的背后思想是,由于尚未应用透视,所有梯度仍然是线性的;这简化了很多事情。如果剪切器的输入在剪辑空间中,则输出也在其中。您正在描述一个角落案例,其中所有顶点的w都统一为1.0。从变换矩阵和输入顶点(如果它们是3个或更少的组件,则是微不足道的)可以轻松检测到此场景。这并不影响剪辑结果仍然在剪辑坐标中的事实。好的,所以NDC与剪辑相同,很棒;您可以跳过一步。 - t0rakka

0

你可以将从剪辑空间(在图像内的每个轴上为-1到+1)到屏幕坐标系的转换,也称为视口空间(在X轴上为0到ResX,在Y轴上为0到resY,在Z轴上为0到1,即深度),看作是在顶点处理器之后、光栅化之前发生的。

当你编写顶点着色器时,输出的是顶点在剪辑空间中的投影位置,但在片段着色器中,每个片段都有自己的屏幕坐标和深度。

关于剪辑空间与NDC

剪辑空间是一个“空间”,正如其名称所示,它是一个参考框架、坐标系统,即一种特定的原点和三个轴的选择,用于指定点和向量。

它的原点位于剪辑体的中心,其三个轴按API指定的方式对齐。例如,该空间中笛卡尔坐标为(+1,0,0)的点出现在图像的右端,而坐标为(-1,0,0)的点出现在左端。

NDC(规范化设备坐标)是一组坐标,如其名称所示,它们是剪裁空间中点的三个笛卡尔坐标。例如,取一个齐次坐标为(3,0,0,3)的剪裁空间点,您也可以表示为(30,0,0,30)等多种方式,并且具有笛卡尔坐标(1,0,0),其NDC为(1,0,0)。


-1

NDC空间是剪裁空间,在NDC空间到窗口空间的转换是由硬件实现的,在NDC和光栅化之间发生。

有API可以设置宽度和高度,默认值与窗口大小相同。

// metal
func setViewport(_ viewport: MTLViewport)
// OpenGL
void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);

OpenGL中的NDC空间,xyz范围为[-1, 1]。而在Metal中,Z轴范围是0到1。

NDC空间通常采用左手坐标系。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接