zoukankan      html  css  js  c++  java
  • XNA::ComputeFrustumFromProjection的一些注释

    ComputeFrustumFromProjection是通过投影矩阵计算出view space下frustum的函数,Frustum在XNA内用这个结构描述

    struct Frustum
    {
    XMFLOAT3 Origin;
    XMFLOAT4 Orientation;
    FLOAT RightSlope;
    FLOAT LeftSlope;
    FLOAT TopSlope;
    FLOAT BottomSlope;
    FLOAT Near, Far;
    }
          其中,view space下frustum的origin是原点,orientation是identity transform,所以,函数主要工作是通过projection matrix计算rightslope,leftslope,topslope,bottomslope,near和far。
          先描述计算rightslope和leftslope方法,这个方法跟计算topslope和bottomslope的方法是一样的。计算rightslope和leftslope的直观方法是通过projection space下的x,0,z平面、far plane、right plane和left plane相交的两个点及projection matrix的inverse matrix,得到这两点在view space下的坐标,然后计算x/y就得到rightslope(leftslope)。
          但问题是,projection space下,这些平面的相交点坐标是多少,不知道。不过,在projection space的下一个frame--normalized device space(coordinate NDC)里,这两个点的坐标是知道的,分别是(1.0,0.0,1.0,1.0)和(-1.0,0.0,1.0,1.0),因为NDC下所有点都在[-1,1]×[-1,1]×[0,1]里面。再观察,由projection space到NDC只是一个scalar*vector的运算(除以w,即乘以1/w),在线性变换的前提下,T(scaler*vector)=scaler*T(vector)。所以,在上述条件支撑下,得到下面的推导:
    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;

    对应XNA::ComputeFrustumFromProjection代码就是
    Points[i] = XMVector4Transform(HomogenousPoints[i], matInverse); // T_proj_inv(P_ndc)
    ...
    Points[0] = Points[0] * XMVectorReciprocal(XMVectorSplatZ(Point[0])); // P_temp.xyzw乘以1/P_temp.z
    ...
    pOut->RightSlope = XMVectorGetX(Points[0]); // 取x

        通过上述计算得到right、left、top和bottom slope,接下来要计算near plane和far plane离原点的距离near和far。在view space下,near和far就是near plane和far plane与z轴交点的z值,与计算slope方法类似,我们通过NDC下的坐标值计算出view space下的z值。NDC下,near和far交点分别是(0.0,0.0,0.0,1.0)、(0.0,0.0,1.0,1.0),观察计算slope方法,可以看出ndc.w和view.z的关系:
    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;
    可见,P_temp.z是等于1,又因为当P_view代表是点的时候P_view.w等于1(w等于1表明是点,等于零表明是向量),所以P_temp.w = 1/P_view.z,所以,P_view.z就是1/P_temp.w
    对应XNA的代码是
    Points[4] = Points[4] * XMVectorReciprocal(XMVectorSplatW(Points[4]));// P_temp.xyzw 乘以 1/P_temp.w即P_view.z
    ...
    pOut->Near = XMVectorGetZ(Points[4]); // 因为P_temp.z等于1,所以乘以1/P_temp.w之后,P_temp.z就是P_view.z

  • 相关阅读:
    BZOJ4223 : Tourists
    BZOJ3565 : [SHOI2014]超能粒子炮
    BZOJ3499 : PA2009 Quasi-template
    BZOJ3490 : Pa2011 Laser Pool
    BZOJ2828 : 火柴游戏
    BZOJ3070 : [Pa2011]Prime prime power 质数的质数次方
    BZOJ2138 : stone
    BZOJ2167 : 公交车站
    BZOJ1290 : [Ctsc2009]序列变换
    Ural2110 : Remove or Maximize
  • 原文地址:https://www.cnblogs.com/rickerliang/p/2792564.html
Copyright © 2011-2022 走看看