Computefrustumfromprojection is a function used to calculate the frustum in the view space through the projection matrix. frustum is described in the xNa structure.
Struct frustum
{
Xmfloat3 origin;
Xmfloat4 orientation;
Float rightslope;
Float leftslope;
Float topslope;
Float bottomslope;
Float near, far;
}
In view space, the origin of frustum is the origin and orientation is the identity transform. Therefore, the function mainly uses projection matrix to calculate rightslope, leftslope, topslope, bottomslope, near, and far.
First describe the rightslope and leftslope calculation methods. This method is the same as the calculation of topslope and bottomslope. The intuitive method for calculating rightslope and leftslope is through the intersection of X, 0, zplane, far plane, right plane and left plane in projection space and the inverse matrix in projection matrix, get the coordinates of these two points in view space, and then calculate x/y to get the rightslope (leftslope ).
But the problem is, under projection space, the coordinates of the intersection points of these planes are unknown. However, in the next frame -- normalized device space (coordinate NDC) of projection space, the coordinates of these two points are known, respectively (1.0, 0.0, 1.0, 1.0) and (-1.0, 0.0, 1.0, 1.0), because all points in NDC are in [-] × [-] ×. Again, the projection space to NDC is just a scalar * vector operation (divided by W, that is, multiplied by 1/W). Under the premise of linear transformation, T (scaler * vector) = scaler * t (vector ). Therefore, with the support of the above conditions, the following derivation is obtained:
P_ndc = p_proj/p_proj.w = p_proj/p_view.z;
=> P_proj = p_ndc * p_view.z;
P_view = t_proj_inv (p_proj) = t_proj_inv (p_ndc * p_view.z) = t_proj_inv (p_ndc) * p_view.z;
Let p_temp = t_proj_inv (p_ndc );
Then
P_view.x = p_temp.x * p_view.z;
P_view.y = p_temp.y * p_view.z;
P_view.z = p_temp.z * p_view.z;
P_view.w = p_temp.w * p_view.z;
Then
Rightslope = p_view.x/p_view.z = (p_temp.x * p_view.z)/(p_temp.z * p_view.z) = p_temp.x/p_temp.z;
So
Rightslope = t_proj_inv (p_ndc). X/t_proj_inv (p_ndc). Z;
Corresponding xNa: computefrustumfromprojectionCodeYes
Points [I] = xmvector4transform (homogenouspoints [I], matinverse); // t_proj_inv (p_ndc)
...
Points [0] = points [0] * xmvectorreciprocal (xmvectorsplatz (point [0]); // p_temp.xyzw multiplied by 1/p_temp.z
...
Pout-> rightslope = xmvectorgetx (points [0]); // obtain x
right, left, top, and bottom slope are obtained through the above calculation. Next, calculate the distance between near plane and far plane from the origin point near and far. In view space, near and far are the Z values at the intersection of near plane and far plane and Z axis, which are similar to the slope calculation method, we calculate the Z value of view space through the coordinate value under NDC. In NDC, the intersection points of near and far are (0.0, 0.0, 0.0, 1.0) and (0.0, 0.0, 1.0, 1.0) respectively. Observe the calculation slope method and we can see that NDC. W and view. Z relationship:
p_view = t_proj_inv (p_ndc * p_view.z) = t_proj_inv (p_ndc) * p_view.z;
let p_temp = t_proj_inv (p_ndc );
then
...
p_view.z = p_temp.z * p_view.z;
p_view.w = p_temp.w * p_view.z;
visible, p_temp.z is equal to 1, when p_view is a vertex, p_view.w equals 1 (w equals 1 indicates a vertex, and 0 indicates a vector), so p_temp.w = 1/p_view.z, p_view.z is 1/p_temp.w
the corresponding xNa code is
points [4] = points [4] * xmvectorreciprocal (xmvectorsplatw (points [4]); // p_temp.xyzw multiplied by 1/p_temp.w, that is, p_view.z
...
pout-> near = xmvectorgetz (points [4]); // after multiplying by 1/p_temp.w because p_temp.z is equal to 1, p_view.z