OpenGL透视投影像素完美绘图

时间:2017-09-18 13:17:00

标签: opengl 3d projection perspectivecamera orthographic

目标是绘制一个形状,比方说三角形,像素完美(顶点应以像素指定)并能够在第三维中进行变换。

我已经尝试使用正交投影矩阵并且一切正常,但形状没有任何深度 - 如果我围绕Y旋转它轴看起来我只是围绕X轴进行缩放。 (因为正交投影显然表现得像这样)。现在我想用 perspective 投影来尝试它。但是通过这个投影,坐标系完全改变,因此我无法用像素指定我的三角形顶点。此外,如果我的窗口大小发生变化,形状的大小也会发生变化(因为坐标系已经改变)。

有没有办法改变透视投影的坐标系,这样我就可以指定我的顶点,就好像我会使用正交投影一样?或者有人知道如何实现第一句中描述的目标吗?

1 个答案:

答案 0 :(得分:1)

投影矩阵描述了从场景的3D点到视口的2D点的映射。它从眼睛空间转换到剪辑空间,并且通过用剪辑坐标的w分量进行划分,将剪辑空间中的坐标转换为规范化设备坐标(NDC)。 NDC的范围是(-1,-1,-1)到(1,1,1)。

在Perspective Projection中,投影矩阵描述了从针孔相机到视口的2D点看世界中3D点的映射。
相机平截头体(截头金字塔)中的眼睛空间坐标被映射到立方体(标准化设备坐标)。

enter image description here

透视投影矩阵:

r = right, l = left, b = bottom, t = top, n = near, f = far

2*n/(r-l)      0              0               0
0              2*n/(t-b)      0               0
(r+l)/(r-l)    (t+b)/(t-b)    -(f+n)/(f-n)    -1    
0              0              -2*f*n/(f-n)    0

其中:

aspect = w / h
tanFov = tan( fov_y * 0.5 );

prjMat[0][0] = 2*n/(r-l) = 1.0 / (tanFov * aspect)
prjMat[1][1] = 2*n/(t-b) = 1.0 / tanFov


我假设视图矩阵是单位矩阵,因此视图空间坐标等于世界坐标 如果要绘制多边形,其中顶点坐标以1:1的比例转换为像素,则必须在平行平面中将多边形绘制到视口。这意味着必须以相同的深度绘制所有点。
深度必须选择那种方式,通过逆投影矩阵对归一化设备坐标中的点的变换给出像素中的顶点坐标。注意,由逆投影矩阵变换给出的齐次坐标必须除以齐次坐标的w分量,才能得到笛卡尔坐标。
这意味着,平面的深度取决于投影的视场角度:

假设您设置了这样的透视投影:

float vp_w  = ....  // width of the viewport in pixel
float vp_h  = ....  // height of the viewport in pixel
float fov_y = ..... // field of view angle (y axis) of the view port in degrees < 180°

gluPerspective( fov_y, vp_w / vp_h, 1.0, vp_h*2.0f );

然后,顶点坐标和像素关系为1:1的平面的depthZ将按如下方式计算:

float angRad = fov_y * PI / 180.0;
float depthZ = -vp_h / (2.0 * tan( angRad / 2.0 ));

注意,投影到视口的中心点是(0,0),因此平面的左下角点是(-vp_w/2-vp_h/2depthZ )和右上角点是(vp_w/2vp_h/2depthZ)。确保透视投影的近平面小于-depthZ且远平面大于-depthZ

进一步了解: