講講不怎麼有用卻很有意義的包圍體測試

2022-05-22 09:24:14 字數 2453 閱讀 5075

大多遊戲程式設計師和圖形程式都知道渲染流水線這個概念,它的本質是將3d的場景對映到顯示屏上的一系列操作。它主要分3個階段:應用程式階段,幾何階段,光柵化階段。將攝像機位置,光照,模型的圖元輸入到幾何階段便是應用程式階段。進行多邊形和頂點操作把3d資料對映到2d的階段便是幾何階段。給定進過變換和投影之後的頂點,顏色,紋理座標,給每個畫素正確配色,這個階段叫光柵化階段。具體的流水線概念,這篇文章不做詳細介紹,這篇文章主要講解幾何階段中的包圍體測試。

幾何階段簡介

幾何階段分幾個階段,流水線上按順序為頂點資料等執行以下操作

模型檢視變換:模型空間變換到觀察空間

頂點著色:光照處理

投影:將模型變換到乙個單位立方體內

裁剪:裁剪不顯示的部分

螢幕對映:對映到螢幕座標系

而物體剔除和背面消隱是處於模型檢視變換的可選操作。

在模型檢視變換階段時需要將物體座標系的點先轉換到世界座標系,然後再由世界座標系轉換到檢視座標系(相機座標系)

然而執行世界座標到相機座標前,需要進行幾個測試。來判斷物體對相機是否可見,避免場景過大時造成大量多餘的計算,然後準確無誤地渲染物體。而這些測試被稱為隱藏面消除。

執行的測試有2種,一種是背面消隱,一種是包圍體測試。

背面消隱的原理可以看這篇部落格,我這篇就主要講很少被提及的包圍體測試的原理

原理很簡單:就是用乙個球體把物體包起來,然後判斷球體是否在視景體外,是則丟棄這個物體。『

現在我們假設有乙個物體,包含一組頂點,要找到離中心遠最遠的頂點,最遠頂點到中心點的距離便是球體的半徑,**實現如下

class gameobject

/// /// 計算半徑

///

private void calculatemaxradius()

max_radius = (float)system.math.sqrt(max_radius);}}

為了便於理解,我用畫圖工具畫了個視景體的圖。視景體就是塗畫的淺藍色部門區域。

不過為了計算,程式裡的視景體是個由遠裁剪面,*裁剪面,y = ymax(視景體內點y座標的最大值),y = ymin,x = xmax,x = xmin六個面構成的長方體,我們只需要判斷球體是否在長方體內即可。也就是判斷球體的6個臨界頂點是否在視景體內即可。

遠*裁剪面

首先我們判斷球體是否在遠*裁剪面間

只需要判斷球體z座標最大的點的z座標值是否在比*裁面的z值小,球體z座標最小的點的z座標值是否比遠裁面的z值大即可。**實現如下

//遠*裁剪面裁剪

if (spherecenterpos.z - go.max_radius> camera.zf||

spherecenterpos.z + go.max_radius < camera.zn)

左右裁剪面和上下裁剪面

接下來是對左右裁剪面和上下裁剪面的判斷,不過由於需要計算xmin,ymin,xmax,ymax,我們需要先獲得攝像頭的焦距

焦距就是位於視景體內的黃線長度,也就是視景體的z深度

焦距的計算和攝像頭資料結構定義**如下

class camera

} }

通過**我們可以看到,焦距的計算,只是簡單的三角函式的變換,不做詳細介紹,不理解可以結合下圖來理解

完整**

/// /// 物體剔除-包圍球測試

///

private bool cullobject(gameobject go,vector3 spherecenterpos)

float focallength = camera.focallength;//獲得焦距

//左右裁剪面剔除

float z_test = 0.5f * camera.aspect * camera.screenheight *

spherecenterpos.z / focallength;

if (spherecenterpos.x - go.max_radius > z_test ||

spherecenterpos.x + go.max_radius < -z_test)

//上下裁剪面剔除

z_test = 0.5f * camera.screenheight *

spherecenterpos.z / focallength;

if (spherecenterpos.y - go.max_radius > z_test ||

spherecenterpos.y + go.max_radius < -z_test)

return go.mesh.cullflag = false;

}

程式中的視景體實際上並沒有成功代表整個視景體,包圍球也不一定很好地代表整個物體。而且存在物體部分位於視景體的情況,包圍體測試不一定管用。但這不代表包圍體測試沒有意義,至少在遊戲中,能有效避免對不可見的大型區域進行處理。

正則不怎麼會用

一 基本正則 1.乙個點 匹配除換行符之外的任意乙個字元,例如r.t能匹配rat ret,但是不能匹配root 2.符號 用於匹配前乙個字元0次或任意多次,比如ab 可以a ab abb等。比如 代表任意長度的不包含換行的字元 grep r t etc passwd 沒有rt rrt rrrt,只能...

例項3 邏輯操作,很少用卻很有用

所謂邏輯,即與 或關係,含有與 或關係運算子的表示式稱為邏輯表示式,在pascal語言中,與用and代替,或用or代替。編寫程式時,基本是處理這樣幾類問題 表示式 判斷 分支選擇。判斷有簡單判斷與複雜判斷,在複雜判斷中,少不了用到各種邏輯關係。比如有這樣乙個判斷 篩選出年裡在18 20歲 長頭髮 身...

BOM一些不怎麼重要的方法

console.log window.innerwidth 獲取可視視窗的寬度 console.log window.innerheight 獲取可視視窗的高度 location.href location.reload 重新整理頁面 window.history.forward 頁面前進一次 wi...