任何人都可以解释一下为了从对象空间坐标生成NDC所执行的步骤是什么,下面的示例。
float vertices[] = {
-2.0f, -12.0f,
2.0f, -12.0f,
-2.0f, 12.0f,
2.0f, 12.0f
};
这是我的mvp矩阵:
float MVP[16] = {
0.993, 0.054, -0.102, -0.102,
0.007, 0.852, 0.524, 0.524,
-0.115, 0.521, -0.846, -0.846,
0.575, -2.604, 4.061, 4.260 };
根据我的计算,我得到:
X,Y,Z,W:
0.824918 7.111959 1.110172 1.000000
-1.111003 5.714332 1.090060 1.000000
-0.123152 0.698949 0.981588 1.000000
0.256286 0.747339 0.980855 1.000000
但那些都是错的。错误的意思是,如果我这样做:
vec4 vert = mvp * vec4(inPos.x,inPos.y,0,1);
vert.xyzw/=vert.w;
gl_Position = vert;
在VS中,我获得了不同的o / p:
vec4 vert = mvp * vec4(inPos.x,inPos.y,0,1);
gl_Position = vert;
答案 0 :(得分:1)
首先,我不能完全重现你得到的数字。也许你在问题中舍入了矩阵元素。我得到的值是:
V0: [0.819627 7.09211 1.1091 1]
V1: [-1.10977 5.69893 1.08916 1]
V2: [-0.123419 0.698661 0.981492 1]
V3: [0.255704 0.7471 0.980762 1]
然而,问题还有别处。当您查看这些点的剪辑空间坐标时,您会得到:
V0: [-1.495 -12.936 -2.023 -1.824]
V1: [2.477 -12.72 -2.431 -2.232]
V2: [-1.327 7.512 10.553 10.752]
V3: [2.645 7.728 10.145 10.344]
注意几件事: 观察体积受到剪辑空间中的不等式-w <= x,y,z <= w的限制。 V0和V1的坐标不满足该不等式。所以这些点位于观看视锥体之外。通常,GL将剪切部分位于观看体积内外的图元。
剪辑本身不是问题。请注意,V0和V1的w
组件实际上是否定。这意味着那些点位于投影中心(=虚拟摄像机)后面。通过将它们除以w
,您可以将这些点镜像回相机前面的 。相机后面的点的NDC坐标在x
,y
和z
中进行镜像,跳过剪切步骤将导致完全错误的基元情况。
GL将永远不会出现此问题,因为剪辑将在剪辑空间中完成,然后才能完成分割。如果你想要有意义的NDC坐标,你还必须实现自己的剪辑。但是,在顶点着色器中几乎无法完成此操作(除非您绘制的所有内容都是单独的点)。对于线性或三角形原始,您需要所有顶点的数据来计算基本边缘和剪切平面之间的交集,并且您可能必须动态创建新的基元。
这也意味着对于位于投影中心后面的点,根本没有有意义的NDC坐标。例如,考虑一个三角形,其中两个顶点位于摄像机前面,内部很好视图体积,第三个顶点位于相机后面。剪切将在从第三个点到其他边缘的每个边缘上创建一个新点(并将生成两个三角形替换原始三角形)。这两个新点确实具有有意义的NDC坐标,但第三个原点从未有过 - 并且第三个输入点与新创建的点之间也没有1:1映射。