【发布时间】:2013-05-13 21:53:52
【问题描述】:
我正在使用 OpenTK,我希望能够在其 Z 为某个数字时完美渲染多边形和纹理像素,投影中的其他任何地方都无关紧要(这是用于 UI)。有没有办法设置一个投影矩阵来做到这一点?
【问题讨论】:
-
@NicolBolas 我已经尝试过该链接,但它没有回答我的问题。我在寻求一种方法来做到这一点,而不是为什么它不起作用。
标签: vb.net opengl projection-matrix
我正在使用 OpenTK,我希望能够在其 Z 为某个数字时完美渲染多边形和纹理像素,投影中的其他任何地方都无关紧要(这是用于 UI)。有没有办法设置一个投影矩阵来做到这一点?
【问题讨论】:
标签: vb.net opengl projection-matrix
首先,忘记那个“特殊”的 Z 值。当您想要绘制 UI 时,您可以切换到正交投影,这样您就可以使用 Z 对图形元素进行分层。
因此,基本问题归结为找到一个将视图空间映射到视口空间的正投影。那么让我们看看 OpenGL 对此有何规定:
如果剪辑坐标中的顶点由下式给出
xc yc zc wc 那么顶点的归一化设备坐标是
xd xc/wc yd = yc/wc zd zc/wc 13.6.1 控制视口
视口变换由所选视口的宽度决定 和以像素为单位的高度,分别为 px 和 py,以及它的中心 (ox,oy) (也以像素为单位)。
顶点的窗口坐标由下式给出
xw px·xd/2 + ox yw = py·yd/2 + oy zw (f−n)zd/2 + (n+f)/2 (…) 分别为每个基元。应用于的因子和偏移量 每个由 n 和 f 编码的视口的 zd 使用 glDepthRange… 设置 (…)
所以你有它:要成为完美像素,你必须找到一个投影,它与顶点剪辑坐标到顶点归一化坐标到顶点窗口坐标的组合正好相反。
让 w = 1 然后你可以用归一化代替剪辑顶点坐标,因此
xw px·xc/2 + ox
yw = py·yc/2 + oy
zw (f−n)zc/2 + (n+f)/2
由于我们对z坐标不感兴趣,我们可以稍微重写一下
xw px·xc/2 + ox px/2 0 ox xc
yw = py·yc/2 + oy = 0 py/2 oy yc
…… … … … … ……
1 1 0 0 1 1
即我们已将其更改为齐次矩阵变换
v_w = V · v_c
其中 v_c 是从眼睛空间投影到剪辑空间后的顶点位置,其中 V 是视口变换矩阵
px/2 0 ox
V = 0 py/2 oy
… … …
0 0 1
所以我们可以重新改写为
v_w = V · P · v_e
我们越来越近了。我们想要那个
v_w = v_e
所以V·P 必须是身份
I = V · P = V · V^-1
因此我们知道投影矩阵 P 必须是视口矩阵的逆矩阵
px/2 0 ox
P = inv V = inv 0 py/2 oy
… … …
0 0 1
2/px 0 -ox
= 0 2/py -oy
… … …
0 0 1
为了非奇异性,我们选择 Z 行作为 (0,0,1,0) 用于范围 [0, 1] 中的顶点眼空间 Z。所以这是用于从眼睛空间到glViewport(ox, oy, px, py)的像素完美映射的投影矩阵
【讨论】: