檢視區與裁剪 (Direct3D 9)
在概念上,檢視區是投影 3D 場景的二維 (2D) 矩形。 在 Direct3D 中,矩形是一個定位在 Direct3D 表面上、供系統使用的渲染目標的座標。 投影轉換會將頂點轉換成用於視口的座標系統。 檢視區也用來指定轉譯目標表面的深度值範圍,場景通常在此範圍內(0.0 到 1.0)進行呈現。
檢視 Frustum
視錐體是場景中的三維空間,位置相對於視口的相機。 音量的形狀會影響模型從相機空間投射到螢幕的方式。 最常見的投影類型是透視投影,負責讓相機附近的對象顯示大於距離中的物件。 對於透視視椎,視景椎體可以可視為金字塔,並將相機放置在金字塔頂端,如下圖所示。 這個金字塔與正面和背面裁剪平面交集。 前後裁剪平面之間截錐體的體積就是檢視範圍。 只有在對象位於此磁碟區時才會顯示。
如果您想像自己站在一個黑暗的房間裡,透過正方形窗戶向外看,您便是在想像一個視椎體。 在這個比喻中,近裁剪平面是窗戶,遠裁剪平面的作用是任何最終擋住視線的東西——例如街對面的摩天大樓、遠處的山或其他任何東西。 您可以看到從視窗開始到視野被阻擋為止的截頭四棱錐內所有的東西,而看不到其他任何東西。
視景體由視野(fov)和前後裁剪平面的距離所定義,使用 z 座標來指定,如下圖所示。
在此圖示中,變數 D 表示從相機到幾何運算管道最後一步驟所定義的空間原點的距離,即檢視轉換。 這是您排列檢視範圍限制的空間。 如需如何使用這個 D 變數來建置投影矩陣的詳細資訊,請參閱 投影轉換 (Direct3D 9)
視窗矩形
您可以使用 D3DVIEWPORT9 結構,在C++中定義檢視區矩形。 D3DVIEWPORT9 結構會與 IDirect3DDevice9 介面所公開的下列檢視區作方法搭配使用。
D3DVIEWPORT9 結構包含四個成員 -- X、Y、Width、Height - 定義呈現目標表面的區域。 這些值會對應至目的地矩形或檢視區矩形,如下圖所示。
您為 X、Y、Width、Height 成員指定的值是相對於渲染目標表面左上角的螢幕座標。 結構會定義兩個額外的成員(MinZ 和 MaxZ),以指出場景將呈現的深度範圍。
Direct3D 假設檢視區裁剪範圍為 X 軸從 -1.0 到 1.0,以及 Y 軸從 1.0 到 -1.0。這些是應用程式過去最常使用的設定。 在使用 投影轉換進行裁剪之前,您可以先調整檢視區的縱橫比。
注意
MinZ 和 MaxZ 表示將呈現場景的深度範圍,且不會用於裁剪。 大部分的應用程式會將這些成員設定為 0.0 和 1.0,讓系統能夠轉譯至深度緩衝區中的整個深度值範圍。 在某些情況下,您可以使用其他深度範圍來達到特殊效果。 例如,若要在遊戲中渲染抬頭顯示器,您可以將這兩個值設定為0.0,以強制系統將物件渲染於前景,或者您可以將兩者都設定為1.0來將一律需要在背景渲染的物件。
檢視區之 D3DVIEWPORT9 結構的 X、Y、Width、Height 成員會定義轉譯目標介面上檢視區的位置和維度。 這些值位於螢幕座標中,相對於表面左上角。
Direct3D 會使用檢視區位置和維度來調整頂點,以將轉譯的場景放入目標表面的適當位置。 在內部,Direct3D 會將這些值插入下列套用至每個頂點的矩陣中。
套用至每個頂點的矩陣方程式
此矩陣會根據檢視區維度和所需的深度範圍調整頂點,並將其轉譯為轉譯目標表面的適當位置。 矩陣也會翻轉 Y 座標,以反映左上角的螢幕原點,並向下增加 y。 套用此矩陣之後,頂點仍為同質,也就是說,頂點仍以 [x,y,z,w] 頂點的形式存在,而且在傳送至點陣化器之前,它們必須轉換成非同質座標。
注意
檢視區縮放矩陣包含 D3DVIEWPORT9 結構的 MinZ 和 MaxZ 成員,以調整頂點以符合深度範圍 [MinZ, MaxZ]。 這表示與先前版本的 DirectX 有不同的語意,以前這些成員用於裁剪。
注意
應用程式通常會將MinZ和 MaxZ分別設定為0.0和1.0,讓系統轉譯到整個深度範圍。 不過,您可以使用其他值來達到特定影響。 例如,您可以將這兩個值設定為 0.0 以強制所有對象進入前景,或將這兩個值都設定為 1.0,將所有物件轉譯成背景。
清除檢視區
清除檢視區會重設渲染目標表面上檢視區矩形的內容。 它也可以清除深度和樣板緩衝區表面的矩形。
使用 IDirect3DDevice9::Clear 清除檢視區。 方法會接受一或多個矩形,以定義要清除表面的區域。 將 Count 參數設定為 1,並將 pRects 參數設定為涵蓋整個檢視區區域的單一矩形位址,將會清除整個檢視區。 清除整個檢視區的另一種方法是將 pRects 參數設定為 NULL,並將 Count 參數設定為 0。
IDirect3DDevice9::Clear 可用於清除深度緩衝區內的樣板位。 只要設定 Flags 參數,即可判斷 IDirect3DDevice9::Clear 如何與轉譯目標及任何相關聯的深度或樣板緩衝區搭配運作。 D3DCLEAR_TARGET旗標會使用您在 Color 自變數中提供的任意 RGBA 色彩來清除檢視區(這不是材質色彩)。 D3DCLEAR_ZBUFFER旗標會將深度緩衝區清除至您在 Z: 0.0 中指定的任意深度,而 1.0 則是最遠的距離。 D3DCLEAR_STENCIL旗標會將模板位元重設為您在模板自變數中提供的值。 您可以使用範圍從 0 到 2n-1 的整數,其中 n 是樣板緩衝區位深度。
在某些情況下,您可能只會對渲染目標和深度緩衝區表面的小部分進行繪製。 清除方法也可讓您在單一呼叫中清除表面的多個區域。 若要這樣做,請將 Count 參數設定為您想要清除的矩形數目,並在 pRects 參數的矩形陣列中指定第一個矩形的位址。
設定剪貼的檢視區
投影矩陣的結果決定了投影空間中的裁剪區域為:
-wc<= xc<= wc
-wc<= yc<= wc
0 <= zc<= wc
其中:套用投影轉換之後,x、y、z 和 w 代表頂點座標。 如果啟用裁剪功能(預設行為),任何頂點的 x、y 或 z 元件超出這些範圍都會被裁剪。
除了頂點緩衝區之外,應用程式會透過 D3DRS_CLIPPING 轉譯狀態來啟用或停用裁剪。 在處理期間會產生頂點緩衝區的裁剪資訊。 如需詳細資訊,請參閱 固定函式頂點處理 (Direct3D 9) 和 可程式化頂點處理 (Direct3D 9)。
Direct3D 不會裁剪來自頂點緩衝區的基本類型的轉換後頂點,除非它是由 IDirect3DDevice9::ProcessVertices生成。 如果您要執行自己的轉換,而且需要 Direct3D 來執行裁剪,則不應該使用頂點緩衝區。 在此情況下,應用程式會遍歷數據以轉換數據。 Direct3D 會第二次遍歷數據以裁剪數據,然後驅動程式渲染數據,效率不佳。 因此,如果應用程式轉換數據,也應該裁剪數據。
當裝置收到需要裁剪的預先轉換和點亮頂點(T&L 頂點)時,為了執行裁剪作業,會根據頂點的倒數同質座標 w(RHW)以及檢視區資訊,將頂點返回到裁剪空間。 接著會執行裁剪。 並非所有裝置都能夠執行此反向轉換,以裁剪 T&L 頂點。
D3DPMISCCAPS_CLIPTLVERTS裝置功能指出裝置是否能夠裁剪 T&L 頂點。 如果未設定此功能,應用程式會負責裁剪要傳送至要轉譯之裝置的 T&L 頂點。 裝置一律能夠裁剪軟體頂點處理模式中的 T&L 頂點(不論裝置是在軟體頂點處理模式中建立,還是切換至軟體頂點處理模式)。
設定渲染裝置檢視區參數的唯一要求,就是設定檢視區的裁剪體積。 若要這樣做,您可以初始化和設定裁剪區域與渲染目標表面的裁剪值。 檢視區通常會設定為渲染至渲染目標表面的完整區域,但這並非必要條件。
您可以針對 D3DVIEWPORT9 結構的成員使用下列設定,以在C++中達成此目的。
D3DVIEWPORT9 viewData = { 0, 0, width, height, 0.0f, 1.0f };
在 D3DVIEWPORT9 結構中設定值之後,請呼叫其 IDirect3DDevice9::SetViewport 方法,將檢視區參數套用至裝置。 下列程式代碼範例顯示此呼叫看起來可能的樣子。
HRESULT hr;
hr = pd3dDevice->SetViewport(&viewData);
if(FAILED(hr))
return hr;
如果呼叫成功,則會設定檢視區參數,並在下次呼叫轉譯方法時生效。 若要變更檢視區參數,只要更新 D3DVIEWPORT9 結構中的值,然後再次呼叫 IDirect3DDevice9::SetViewport。
注意
D3DVIEWPORT9 結構成員 MinZ 和 MaxZ 表示場景將被渲染至的深度範圍,不會用於裁剪。 大部分的應用程式會將這些成員設定為 0.0 和 1.0,讓系統能夠轉譯至深度緩衝區中的整個深度值範圍。 在某些情況下,您可以使用其他深度範圍來達到特殊效果。 例如,若要在遊戲中呈現抬頭顯示器,您可以將這兩個值設定為0.0,以強制系統在前景中呈現物件,或者您可以將兩者都設定為1.0來呈現始終在背景中的物件。
相關主題