我想渲染一个平面,使它看起来好像在各个方向都无限远。我希望远处的平面边界是地平线。
使用简单的网格是行不通的——计算机无法渲染无限多的三角形。即使这是可能的,相机平截头体也会切掉远处的多边形,并在平面边界和地平线之间产生间隙。
一种解决方法是用数学方法计算地平线:在平面上找到点,这些点也位于无穷远处的平面上。连接这些点和视口的两个角会创建一个梯形,代表所寻找的平面。然而,这种方式不能正确地照亮飞机,或者应用纹理,或者任何其他需要精细三角测量的东西......
我想渲染一个平面,使它看起来好像在各个方向都无限远。我希望远处的平面边界是地平线。
使用简单的网格是行不通的——计算机无法渲染无限多的三角形。即使这是可能的,相机平截头体也会切掉远处的多边形,并在平面边界和地平线之间产生间隙。
一种解决方法是用数学方法计算地平线:在平面上找到点,这些点也位于无穷远处的平面上。连接这些点和视口的两个角会创建一个梯形,代表所寻找的平面。然而,这种方式不能正确地照亮飞机,或者应用纹理,或者任何其他需要精细三角测量的东西......
您可以使用标准光栅化管道绘制无限平面。它使用的齐次坐标可以像常规欧几里得点一样愉快地表示“理想”点(也称为消失点或无穷远点),同样,建立一个将远平面置于无穷远的投影矩阵也是非常实用的。
一种简单的方法是每个象限使用一个三角形,如下所示:
vertices [x,y,z,w], for drawing an (x,y) coordinate plane, at (z==0):
0: [ 0, 0, 0, 1 ]
1: [ 1, 0, 0, 0 ]
2: [ 0, 1, 0, 0 ]
3: [-1, 0, 0, 0 ]
4: [ 0,-1, 0, 0 ]
draw 4 triangles using indices:
(0,1,2); (0,2,3); (0,3,4); (0,4,1)
如果您想要一个测试图案(如无限棋盘),您将不得不处理将三角形拉伸到无限会扭曲任何标准纹理的事实。但是,您可以编写一个像素着色器,它根据实际的 3D 点(即使用x
和y
来自世界空间(x,y,z)
坐标)确定颜色,完全忽略(扭曲的)纹理坐标。
您可以根据奇偶性(对于棋盘格)在两种恒定颜色之间进行选择,或者通过根据所选坐标的小数部分对其进行采样来平铺纹理。
请注意,对于 x、y 和 z 中的每一个,OpenGL 的剪辑空间都是 [-1..1]。您可以通过在远剪辑距离无限制地增加时评估限制来计算适当的投影矩阵f
:
clip coords: [x] = [ n/r ] * view coords [x]
[y] [ n/t ] [y]
[z] [ -1 -2n ] [z]
[w] [ -1 0 ] [w]
其中(如链接中所示): n
是近剪裁平面,r
是近剪裁平面的截锥体宽度的一半,是近剪裁平面t
的截锥体高度的一半。
我没有测试过上面的矩阵,所以你付出的代价是值得的。另请注意,当您接近无穷大时,深度值将失去其精度......
虽然,更近的距离的精度可能会很好——例如,在任何给定的距离,(近:无限)情况下的深度分辨率应该比(近:远)比率为的情况低约 10% (1:10)。
您的视锥体是一个有盖的金字塔,由侧面和顶部/底部的 4 个剪辑平面构成,在近平面和远平面上是“无限的”(它不是无限的,但是因为您看不到任何东西之外的东西截锥体,它是无限的)。
因此,绘制带顶金字塔(一个四边形或两个三角形)的底边是一个“无限”的平面,指向地平线。或者,就此而言,其角点位于近平面和远平面上的任何四边形。