在3D图形学中,一种优化的手法,叫做物体剔除(Object Culling)。这种技术的提出是基于这样的策略:我们不希望将不存在View Frustum里面的物体送往流水线中进行处理。虽然,你可能会说,现在的图形卡都已近支持了三角形剔除的技术。但是,不要忘了流水线的步骤。我们是先进行Vertex Processing,然后才进行Geometry Processing。而图形卡对三角形的剔除是在Geometry Processing这个阶段进行的。也就是说,即使能够剔除它们,我们依然要在Vertex Processing中对这些将来需要丢弃的顶点进行Vertex Processing处理。而我们知道,Vertex Processing这个阶段往往会进行坐标变换,光照计算等等费时的操作。所以,如果能够在Vertex Processing之前,也就是在Application阶段,在我们的CPU中将这些根本不需要处理的物体剔除的话,会大大的提高程序的效率。而想要将物体剔除,我们就需要知道这个物体是否在View Frustum中。而为了判断这个条件,我们就需要确定构成View Frustum的6个平面的方程。所以,本篇文章,就向大家讲述,如何获取View Frustum的6个平面方程。
void Frustum::createPlane(const Camera* camera)
{
const Mat4& mat = camera->getViewProjectionMatrix(); //获得视图投影矩阵
//extract frustum plane
// (X x a11 + Y x a12 + Z x a13 + a14) + (X x a41 + Y x a42 + Z x a43 + a44) > 0
// X(a11 + a41) + Y(a12 + a42) + Z(a13 + a43) + a14 + a44 > 0
// 负数大概是因为 p.n = d p就是(x,y,z),n就是(a11 + a41,a12 + a42,a13 + a43) d如果不变的话,n就应该取负数
_plane[0].initPlane(-Vec3(mat.m[3] + mat.m[0], mat.m[7] + mat.m[4], mat.m[11] + mat.m[8]), (mat.m[15] + mat.m[12]));//left
_plane[1].initPlane(-Vec3(mat.m[3] - mat.m[0], mat.m[7] - mat.m[4], mat.m[11] - mat.m[8]), (mat.m[15] - mat.m[12]));//right
_plane[2].initPlane(-Vec3(mat.m[3] + mat.m[1], mat.m[7] + mat.m[5], mat.m[11] + mat.m[9]), (mat.m[15] + mat.m[13]));//bottom
_plane[3].initPlane(-Vec3(mat.m[3] - mat.m[1], mat.m[7] - mat.m[5], mat.m[11] - mat.m[9]), (mat.m[15] - mat.m[13]));//top
_plane[4].initPlane(-Vec3(mat.m[3] + mat.m[2], mat.m[7] + mat.m[6], mat.m[11] + mat.m[10]), (mat.m[15] + mat.m[14]));//near
_plane[5].initPlane(-Vec3(mat.m[3] - mat.m[2], mat.m[7] - mat.m[6], mat.m[11] - mat.m[10]), (mat.m[15] - mat.m[14]));//far
}
Clip Space Approach – Extracting the Planes
In here another approach to extract the view frustum planes is presented based on the properties of clip space.
Consider a point p =(x,y,z,1) on the 3D world. Consider also a modelview matrix Mand a projection matrix P. The point p is transformed by matrices M and P as point pc =(xc,yc,zc,wc) in clip space using:
The point pc is in homogeneous coordinates, and when normalised becomes pcn:
In normalised clip space the view frustum is an axis aligned box centered in the origin, and bounded by the following planes:
- Left Plane: x’ = -1
- Right Plane: x’ = 1
- Top Plane: y’ = 1
- Bottom Plane: y’ = -1
- Near Plane: z’ = -1
- Far Plane: z’ = 1
This implies that the point pcn =(x’,y’,z’) is inside the view frustum if:
Then the point pc, in non-normalized coordinates, must obbey the following conditions in order to be inside the view frustum:
Based on this information it is possible to extract the six planes, in world coordinates, that bound the view frustum. The point pc is on the “right” side of the left plane if
Consider p and A=MP as described below
Then xc and wc can be defined as a function of p = (x,y,z,w), and A.
Therefore the following inequation must be true if p is on the right side of the left plane.
A little algebraic manipulation gives
So the left plane (Ax+By+Cz+D=0) is defined as:
where col1 and col4 are the first and forth columns of matrix A, respectively.
If the only objective is to find out if a point is inside or outside of the frustum then the plane as defined is ok. However when testing spheres, which require computing the distance from the center of the sphere to the plane, it is advisable to normalize the plane.
The right plane can be obtained in a similar manner:
The following coefficients are obtained for the right plane:
The remaining planes are obtained as follows:
- Bottom Plane
- Top Plane
- Near Plane
- Far Plane