• 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

  • 相关阅读:
    上传图片,将图片保存在腾讯云(2种方式)
    由ping所引发的思考~
    php面试上机题(2018-3-3)
    【八】jqeury之click事件[添加及删除数据]
    【七】jquery之属性attr、 removeAttr、prop[全选全不选及反选]
    【六】jquery之HTML代码/文本/值[下拉列表框、多选框、单选框的选中]
    【五】jquery之事件(focus事件与blur事件)[提示语的出现及消失时机]
    小白懂算法之基数排序
    mysql_sql199语法介绍
    Python基本编程快速入门
  • 原文地址:https://www.cnblogs.com/rickerliang/p/2792564.html
Copyright © 2020-2023  润新知