可編程管道下的剪裁平面
剪裁平面 (Clip Plane) 在圖形學領域有著重要的作用,比如水面模擬中,渲染折射紋理時,我們就必須將水面以上的頂點通過剪裁平面剪裁掉。
在過去的固定渲染管道時代,剪裁平面的實現較為簡單,比如在 DirectX 9 中,可以先設定剪裁平面在世界坐標系下的方程 (ax+by+cz+d=0) ,再調用 SetClipPlane(DWORD Index,CONST float * pPlane) 這個 API 函數就可以了。
?
附上例子程序:
vPosition=D3DXVECTOR3(0,0,0);
//
平面上一個點
vNormal=D3DXVECTOR3(0,1,0);
//
法向量
D3DXPlaneFromPointNormal(?&clipplane,?&vPosition,?&vNormal?);
//
生成剪裁平面
m_pDevice()->SetClipPlane(?0,?(
float
*)clipplane);?
?
然而,在現在的可編程管道 (programmable pipeline) 下,設置的剪裁平面會被在剪裁坐標系下處理,而不是在世界坐標系下。
解決這個問題的方法有:1)? 給要剪裁的頂點做標記,在Pixel Shader中把它剪裁掉。
2)? 使用近斜平面裁剪(Oblique Near-Plane Clipping),即修改投影矩陣,將要剪裁的頂點放在視截體之外,從而避免了該頂點的繪制。
3)? 修改平面方程,使之從世界坐標系轉換到剪裁坐標系。
上述方法中,第一種和第二種效率并不高:在Pixel Shader中剪裁沒有減少任何不必要的頂點處理,而計算近斜平面裁剪矩陣較為繁瑣。所以,方法三是最佳選擇。
?要將一個平面從世界坐標系轉換到剪裁坐標系,必須求出這個變換矩陣。
設平面方程ax+by+cz+d=0,用一個4維向量來n表示(a,b,c,d),設平面上有個點p:(x,y,z,1)。根據平面方程的定義,有:
nTp = ax + by + cz + d = 0
設矩陣R可以讓點P從世界坐標系轉換到剪裁坐標系,矩陣Q可以讓平面n實現同樣的變換。那么,有:
其中p'、n'分別是轉換后的點與平面。
nTQTRp = 0
如果:QTR = I
那么:
nTQTRp = nTIp = nTp = 0
于是:
Q = (R-1)T
在DirectX 3D中,將一個點從世界坐標系轉換到剪裁坐標系,所用的矩陣為觀察矩陣與投影矩陣的乘積,即:
D3DXMATRIX??TranMatrix?=?matView*matProj;
(TranMatrix為所求的變換矩陣,matView和matProj分別為觀察矩陣與投影矩陣)
?
附上在D3D中變換的完整代碼:
D3DXPLANE?tempPlane?=?clipplane;
D3DXPlaneNormalize(&tempPlane,?&tempPlane);
D3DXMATRIX??TranMatrix?=?matView*matProj;
D3DXMatrixInverse(&TranMatrix,?NULL,?&TranMatrix);
D3DXMatrixTranspose(&TranMatrix,?&TranMatrix);
D3DXPlaneTransform(&tempPlane,?&tempPlane,?&TranMatrix);
參考資料:
1.Back Face Culling Notes ,Jordan Smith (University of California, Berkeley)
http://www.cs.berkeley.edu/~ug/slide/pipeline/assignments/backfacecull.shtml?
2.GameDev Forum
http://www.gamedev.net/community/forums/topic.asp?topic_id=402381
3.Oblique Near-Plane Clipping with Orthographic Camera ,Aras
http://aras-p.info/texts/obliqueortho.html
posted on 2010-01-20 22:00 Bill Hsu 閱讀(2019) 評論(2) 編輯 收藏 引用 所屬分類: C/C++ 、Game Dev 、Algorithm