Kev*_*eid 14 3d projection webgl opengl-es-2.0
我有一个3D场景和一个使用gluPerspective定义的相机.我有一个固定的FOV,我知道任何几何体与相机的最小距离(它是第一人称视角,因此这是从视点到角色碰撞体积的最小距离).
无论玩家如何移动和观看,我怎样才能选择最近的剪裁平面(最佳深度缓冲分辨率),不会造成任何剪裁?
这些距离不是简单相等,因为近平面的角离原点比中心更远.
Kev*_*eid 14
式:
nearPlane = nearestApproachToPlayer/sqrt(1 + tan (fov/2)2 ·(aspectRatio 2 + 1)))
JavaScript代码:
var nearPlane = nearestApproachToPlayer
/ Math.sqrt(1 + Math.pow(Math.tan(fov/180*Math.PI/2), 2)
* (Math.pow(aspectRatio, 2) + 1));
Run Code Online (Sandbox Code Playgroud)
推导:
在几何上,考虑金字塔,其基部是近剪裁平面,尖端是原点.让nearPlane成为金字塔的高度,w和h是金字塔底座的宽度和高度.
w = aspectRatio·h
FOV确定金字塔的高轴方向的斜率:
斜率 = TAN(FOV/2)
⇓
H/nearPlane = 2黄褐色(FOV/2)
⇓
ħ/2 = nearPlane黄褐色(FOV/2)
近剪裁平面的任何角点都从剪辑平面的中心偏移(w/2,h/2),因此距离是sqrt((w/2)2 +(h/2)2).距离角点原点的距离是由nearPlane和前一距离形成的直角三角形的斜边,因此是sqrt((w/2)2 +(h/2)2 + nearPlane 2).
我们希望到角点的距离等于任何几何的最近距离.
nearestApproachToPlayer = sqrt((w/2)2 +(h/2)2 + nearPlane 2)
应用直接代数产生上面给出的公式.
我还没有检查过我的代数,但是我已经通过实验测试了公式:如果我将nearPlane乘以1.1,那么它产生的剪裁平面对于各种宽高比来说有点太过分了.我没有尝试过比60°不同的FOV.
选择近距离和远距离剪辑距离的最佳做法是使它们紧密地包围场景,即尽可能地使近剪裁平面和远剪辑平面尽可能接近.
大多数3D应用用于透视变换的标准平截头体投影是平行平面投影.这意味着从视点确定平面距离.这实际上很简单:
您将在3D渲染程序中携带的参数之一是视图矢量,即摄像机指向的方向.假设您将此向量标准化(即单位长度),然后将标量(=点)乘积与对象位置一起给出与原点的平面距离.这是一种更直接的方法,因为它直接为您提供所需的值,而不需要正方形,平方根和除法.它只是乘法和,即MAD指令,它们由SIMD指令集直接支持.