• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            投影矩陣的實現以及如何從投影矩陣中獲取各視裁體平面(教程)

            投影矩陣的實現以及如何從投影矩陣中獲取各視裁體平面(教程):

            flipcode@msn.com
            一.投影的實現:
            以D3D為例,先看一下D3D有前設置投影矩陣參數的函數:
            D3DXMATRIX *WINAPI D3DXMatrixPerspectiveFovLH(
            D3DXMATRIX *pOut,
            FLOAT fovy,
            FLOAT Aspect,
            FLOAT zn,
            FLOAT zf
            );
            第一個是輸出的結果,第二個是視角,第三個是屏幕寬高比,第四個是近平面,第五個是遠平面.
            其實如果不用作視裁剪,只作屏幕投影的話只需用到fovy和aspect,下面我們先求ys的投影,而求出
            ys后x的投影xs我們只需根據屏幕寬高比aspect來作一下調整就可以了.


            (圖1)
            o = camera's postion
            SC = screen's upper half hight (i.e. screen height/2)

            p = a point will project to our screen
            d = OS (the distance from O to S)
            下面來求ys:
            由于OSP1與OMP相似,故
            d/z = ys/y
            轉換一下,得:
            ys = d*y/z
            現在只差一個未知的d了,
            那么d怎么求呢?下面來看一個圖:


             


            o = camera's postion
            SC = screen's upper half hight (i.e. screen height/2)

            d = OA (the distance from O to A)
            @ = fov/2
            從上圖可知tag(@)=SC/d即tag(fov/2)=SC/d,其中fov是已知的(由參數傳進),
            那么SC呢?查看D3D的文檔知道D3D的project空間的
            可視范圍定義為x∈[-1,1], y∈[-1,1], z∈[0,1]的一個長方體(下面圖2和圖3)。
            (注:ogl的是z∈[[1,1])
            從project空間的z負半軸看看我們的變換目標




            從project空間的x正半軸看看我們的變換目標



            這可看作中間坐標系,從這個坐標系到屏幕坐標只需作放縮和平移操作即可
            這樣定義的好處是避免一些設備相關性的東西來分散我們的注意力,集中把算法
            弄好后而在最后再作調整就可以了.
            從上圖看出SC=1,故d=1/tag(fov/2)=cot(fov/2);
            好,經過這么一番折騰我們最終得到了ys= y*d/z=y*cot(fov/2)/z;
            而xs計算同理,但是由于屏幕寬高實際上是不等的,所以可通過參數aspect縱橫比
            進行調整,xs=x*cot(fov/2)/z/aspect;,另外為了得以使用矩陣乘法,
            我們可以利用w分量來保存z(因為w分量在投影矩陣之前都沒用到過),
            最后才讓x/w,y/w來得到正確的投影值,
            從而可以得到矩陣如下:
            d/aspect 0 0 0
            0 d 0 0
            0 0 1 1
            0 0 0 0
            (其中d=cot(fov/2))
            二.裁剪:
              由上面矩陣我們就可以將一個三維的物體坐標轉投影轉換到二維的屏幕空間了,但是為了
            去掉那些離攝象相很近或是在攝象機后面(投影會變反)或是離攝像很遠的物體從而減輕
            渲染的負擔(以及修正反向投影),我們還要處理一個要投影到(0-1)的z分量.
            而這個時候就要用到D3DXMatrixPerspectiveFovLH的最后兩個參數了(i.e.近平面及遠平面)
            下面來討論它:
            如圖:




            o = camera's postion
            @ = fov/2
            N = near plane
            F = far plane
            p = a point will project to our screen
            從上圖可以看到N就是我們要作裁剪用的近平面,而F就是我們要作裁剪用遠平面,
            近平面和遠平面可從參數得來,這時我們想作的是讓落在N和F上的點映射到0到1的
            線性坐標上,也就是說當p的z=N時投影后的zs=0,而當z=F時投影后的zs=1;
            這個很好辦:zs=(z-N)/(F-N)即可.
            好了,這一步也輕松辦到了,但是我們前面為了實際用矩陣變換來作投影而讓其在
            投影后再/w(w保存z值)才是最后的結果. 既然這樣那么我們所求的就是還未除過w的
            投影值為zw. 想一下,當z=F時我們投影后的zs=zw/z=1,也就是zs=zw/F=1;所以zw=zs*F,
            因為前面求得zs=(z-N)/(F-N),所以zw=F*(z-N)/(F-N);(簡單驗證一下:當z=N時,zw=0,這時
            zs=0/w還是0,而當z增大時0<zw<=F,也就是0<zs<=1,而直到z=F時,zw=F,這時zs=F/w=F/F=1),
            為了方便將其分解成:zw=(z*F-N*F)/(F-N)=z*F/(F-N)-N*F/(F-N)
            這樣就可以把它應用到矩陣中,如下:
            d/aspect 0 0 0
            0 d 0 0
            0 0 F/(F-N) 1
            0 0 -N*F/(F-N) 0

            以上公式可以代替D3DXMatrixPerspectiveFovLH來作測試:
            void myMatrixPerspectiveFovLH(mat4 *out, float fov, float aspect, float n, float f)
            {
            float h = tanf(0.5*fov);
            float w = h * aspect;
            out = mat4( 1.0f/w, 0, 0, 0
            0 1.0f/h 0 0
            0 0 f/(f-n) 1
            0 0 -n*f/(f-n) 0);
            }
            其中1.0f/h 就是cot(fov/2), aspect=width/height

            三.從投影矩陣獲取視裁體:
            上面已說過對一點投影后的各分量值所在范圍為:
            -1<xs<1;
            -1<ys<1;
            0<zs<1;
              其中xs/ys/zs是除過w后的值,而未除過w的值所在范圍是:
              -w<xw<w; -w<yw<w;
            0<zw<w;
            對各不等式進分解后得:
            xw+w>0;且xw-w<0;
            yw+w>0;且yw-w<0;
            zw>0;且xw-w<0;
            我們知道xw/yw/zw是一個在view space中的點v(xv,yv,zv,wv)(其中wv=1)乘上投影矩陣后的各分量值(當然還未除以w),那么
            點v(xv,yv,zv,wv)是如何乘上投影矩陣的呢?是這樣的:
            xw = xv*prj_11+yv*prj_21*prj_31+wv*prj_41;
            zw = xv*prj_12+yv*prj_22*prj_32+wv*prj_42;
            zw = xv*prj_13+yv*prj_23*prj_33+wv*prj_43;
            w = xv*prj_14+yv*prj_24*prj_34+wv*prj_44;
            即:
            xw = v dop col1;
            yw = v dop col2;
            zw = v dop col3;
            w = v dop col4;
            (說明:上述col1和col2及col3其實表達了一個投影坐標系,其中col1表示x軸,col2表示y軸,col3表示z軸,
            而點v乘上這個坐標系就相當于求出點v在此新坐標系中各分量上的投影值,此外col4只是簡單的為了讓點v點乘它時求得w=原點v的w分量值)
            故:
            xw+w>0;
            即:
            v dop col1 + v dop col4 > 0;
            即:
            v dop ( col1 + col4 ) > 0;
            也就是:
            xv*(prj_11+prj_14) + yv*(prj_21+prj_24) + zv*(prj_31+prj_34) + wv*(prj_41+prj_44) > 0;
            我們知道平面公式是: ax+by+cz+d=0,故上面其實表示的就是視裁體的左平面向內,其中它的法線是:
            (prj_11+prj_14), (prj_21+prj_24), (prj_31+prj_34).
            而由于wv=1,
            故它的距離是(prj_41+prj_44).
            同理我們可以求出視裁體的其它平面.

            四.Frustum Culling
              我們知道,視裁體的六個面是朝向內的,由上面已經得到了各平面等式,只要用P DOP N + D看是否大于0就可以知道點P是否在一個平面

            內,最后點P如果在所有平面內的才是在視裁體內.
            而當判斷一個物體是否在視裁體內時,我們只需對物體的包圍盒進行測試,例如,測試一個包圍球是否在視裁體內,只要判斷所有P DOP N + D

            >2的1/2次方*R不等式成立即可.

            參考文檔:
            fast extraction of viewing frustum planes from the world-view-projection matrix

            posted on 2008-04-16 09:49 RedLight 閱讀(2202) 評論(0)  編輯 收藏 引用 所屬分類: 3D渲染技術

            <2008年9月>
            31123456
            78910111213
            14151617181920
            21222324252627
            2829301234
            567891011

            導航

            統計

            公告


            Name: Galen
            QQ: 88104725

            常用鏈接

            留言簿(3)

            隨筆分類

            隨筆檔案

            相冊

            My Friend

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            久久久久免费精品国产| 久久久久99精品成人片三人毛片| 久久久久噜噜噜亚洲熟女综合| 91秦先生久久久久久久| 精品国产乱码久久久久软件| 久久福利青草精品资源站| 久久久这里只有精品加勒比| 亚洲狠狠久久综合一区77777| 久久精品国产精品国产精品污| 久久国产精品一区| 久久国产乱子伦免费精品| 无码任你躁久久久久久老妇App| 久久精品人人做人人爽97| 人人狠狠综合久久亚洲高清| 久久久久久久综合日本亚洲| 久久久噜噜噜www成人网| 国产精品青草久久久久福利99| 一本大道久久a久久精品综合 | 97r久久精品国产99国产精| 国产A级毛片久久久精品毛片| 亚洲日本va午夜中文字幕久久| 精品一久久香蕉国产线看播放 | 亚洲精品视频久久久| 国产情侣久久久久aⅴ免费| 久久久久亚洲av无码专区| 激情久久久久久久久久| 久久国产精品久久| 新狼窝色AV性久久久久久| 久久亚洲精精品中文字幕| 久久青草国产精品一区| 色综合久久无码五十路人妻| 久久99热这里只频精品6| 午夜精品久久久久久影视777| 国产精品一区二区久久精品无码 | 亚洲欧美成人久久综合中文网| 青青青国产精品国产精品久久久久| 久久精品亚洲精品国产色婷| 亚洲精品tv久久久久久久久| 国产成人精品综合久久久| 国产色综合久久无码有码| 亚洲国产精品无码久久一区二区|