我正在使用OpenTK,我希望能够在Z是一定数量的情况下渲染多边形和纹理像素,投影中的任何其他位置无关紧要(这适用于UI)。有没有办法设置一个这样做的投影矩阵?
答案 0 :(得分:6)
首先,忘记那个“特殊”的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
为了非奇异性,我们在[0,1]范围内为顶点眼睛空间Z选择Z行为(0,0,1,0)。因此,这是用于从眼睛空间到glViewport(ox, oy, px, py)