顶点着色器中的透视除法?

5

当在顶点着色器中使用透视矩阵时,我是否应该编写代码来除以w,还是在后续阶段自动完成?

我提出这个问题的原因是我看到很多顶点着色器使用:

gl_Position = matrix * pos;

如果有一个后续阶段将向量与其w分量相除,这就是有意义的。

然而,在我的顶点着色器中使用以下代码之前,我从未使它起作用:

gl_Position = matrix * pos;
gl_Position = gl_Position / gl_Position.w;

第二个示例是正确的吗?还是可能缺少其他设置?

换句话说:在OpenGL顶点变换(第一张图片)中显示的步骤中,我必须在顶点着色器中编写哪些步骤?

我确定ModelView和Projection矩阵属于其中之一(或两者合并)。视口变换不是顶点着色器的一部分,但除以w呢?

我的设置是一些简单的三角形,其坐标在[-1 1]范围内的x/y/z。

透视矩阵应该将z=-1到-10的坐标投影到z=-1,x=[-1,1],y=[-1,1]。

-1.0   0.0   0.0   0.0
 0.0  -1.0   0.0   0.0
 0.0   0.0  -1.2  -2.2
 0.0   0.0   1.0   0.0

它是由以下生成的:

x = 2.0f * zNear / (xMax - xMin);
y = 2.0f * zNear / (yMax - yMin);
a = -(xMax + xMin) / (xMax - xMin);
b = -(yMax + yMin) / (yMax - yMin);
c = (zFar + zNear) / (zNear - zFar);
d = -(2.0f * zFar * zNear) / (zNear - zFar);

制作矩阵P:
x, 0, a, 0
0, y, b, 0
0, 0, c, d
0, 0, 1, 0;

最终,我通过矩阵 = P * T 生成了最终矩阵,其中T是一个平移(0,0,-2)。
我已经尝试在CPU上进行数学计算,并且似乎可以生成期望的结果,但是我也手动进行了除以w的操作。
更新:问题已解决,但需要理解。
我否定了矩阵中的所有组件(乘以-1),现在它可以正常工作。上面的示例还有一个问题,即将正和负z坐标投影到投影平面上,这个问题也因此更改而得到解决。
欢迎提供任何参考或解释为什么可以通过此更改解决该问题。

我仍然不确定你从哪里得到那些方程式,但是如果我看一下gluPerspective,你的“d”值恰好与他们使用的相反。 - Tim
这些公式是从零开始推导出来的,使用上面展示的矩阵作为起点,其中包含未知数。 - hultqvist
1个回答

5

在顶点着色器中不要自己进行透视除法,因为它会在后面的管线中自动完成。

如果这样做无效,你可以提供一些代码或者更详细地描述问题吗?我很惊讶为什么这对你有影响。


好知道,那我就知道不该在哪里“解决”我的问题了,我添加了更多关于我的配置的示例。 - hultqvist
1
@phq - 我对这个语句感到困惑:“从z=-1到-10进入z=-1”。你的znear/zfar参数是什么?你是用gluPerspective或等效函数生成的吗?剪裁是在透视除法之前完成的,所以唯一的解释可能是你的多边形在非除法示例中被剪裁了,而手动除法时则没有。 - Tim
我正在尝试使用上面的代码自己生成矩阵。z范围[-1,-10]应该映射到[1,-1],投影位置垂直于z轴,在z = -1处。 - hultqvist
你不会上传转置矩阵吧?在你的例子中,'d' 应该是第14个元素。否则我不知道你从哪里得到这些方程式,但我建议尝试模仿 gluPerspective 手册上给出的方程式,除非这是某种学术练习。 - Tim
是的,目标是理解,我正在使用M*v乘法,因此列向量应该在矩阵中反映出来,如果正确的话。请查看问题更新,进行了小改动后它可以工作了。仍然不确定原因。 - hultqvist

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