1. 程式人生 > >Chaptor 9 Blending (Introduction to 3D Game Programing with DirextX 11)自讀

Chaptor 9 Blending (Introduction to 3D Game Programing with DirextX 11)自讀

9.1 THE BLENDING EQUATION

image1

Csrc是這幀PS計算結果輸出,Cdest是當前back buffer計算結果(比如已經計算好的透明體背後的solid的color),Fsrc (source blend factor) and Fdst (destination blend factor)

⊗表示componentwise multiplation ,⊞ 表示binary operation,這兩個下面兩節會說。

alpha和rgb 類似,之所以分開,是為了要分開控制。而且alpha的blend的需求頻率比rgb要小很多,因為一般用不到back buffer的alpha。

image2

9.2 BLEND OPERATIONS

解釋⊞,binary operation

image3

alpha類似

9.3 BLEND FACTORS

解釋⊗,factor

具體在D3D11_BLEND 的enum type裡

image4

9.4 BLEND STATE

在DX中,以上資訊由ID3D11BlendState 控制,建立它,通過ID3D11Device::CreateBlendState方法 傳入D3D11_BLEND_DESC 結構體。

HRESULT ID3D11Device::CreateBlendState( const D3D11_BLEND_DESC *pBlendStateDesc, ID3D11BlendState **ppBlendState);

注意其中的一些引數

AlphaToCoverageEnable 用於MSAA 計算覆蓋率時使用,第11章時用到

RenderTarget 8個D3D11_RENDER_TARGET_BLEND_DESC 大小的陣列,表示8個rendr target 依次怎麼blend,預設用第一個的

RenderTargetWriteMask:用於控制是否允許寫入哪些通道

image5

bind  STATE 到pipeline 呼叫

void ID3D11DeviceContext::OMSetBlendState( ID3D11BlendState *pBlendState, const FLOAT BlendFactor, UINT SampleMask);

9.5 EXAMPLES (書中有很多效果對比圖)

9.5.1 No Color Write

方法1 Fsrc=(0,0,0),Fdest=(1,1,1) C=Csrc*(0,0,0)+Cdest*(1,1,1)

方法2 D3D11_RENDER_TARGET_BLEND_DESC::RenderTargetWriteMask =0

9.5.2 Adding/Subtracting

Add會讓畫面變亮,因為更多的畫素值變大了。Subtract會讓畫面變暗,因為畫素值變小了。

C=Csrc*(1,1,1)+/- Cdest*(1,1,1)

9.5.3 Multiplying

Fsrc=(0,0,0),Fdest=D3D11_BLEND_SRC_COLOR 

 C=Csrc*(0,0,0)+Cdest*Csrc

正片疊底,通常執行正片疊底模式後的顏色比原來兩種顏色都深。任何顏色和黑色正片疊底得到的仍然是黑色,任何顏色和白色執行正片疊底則保持原來的顏色不變,而與其他顏色執行此模式會產生暗室中以此種顏色照明的效果。

9.5.4 Transparency

Fsrc=D3D11_BLEND_SRC_ALPHA,Fdest=D3D11_BLEND_INV_SRC_ALPHA

 C=Csrc*As+Cdest*(1-As)

使用這種方法,就要注意object的繪製順序

基本原則是Draw objects that do not use blending first. Next, sort the objects that use blending by their distance from the camera. Finally, draw the objects that use blending in a back-to-front order. 先繪製不用blend的object,然後對需要blend的object根據和camera的距離做排序,然後根據排序從後往前繪製。

如果有半透明的才需要排序,否則如果只是 add subtract multiple,雖然還是先渲染不需要blend的,再渲染blend的objects,但這些objects就不需要排序了,因為這三種操作是可交換的,先後順序不影響。?

9.5.5 Blending and the Depth Buffer

當渲染一系列blend的object,這一系列是不互相阻擋的,因此不希望他們覆寫掉depth value,如果這樣,後面blend的同系列的就可能無法通過深度測試,從而無法blend,所以這種時候會關閉這些畫素的深度寫入,只寫入rgb值。

image6

比如一堆粒子,互相之間是addtive的,一個畫素上 addtive到的例子越多,這個地方就越亮,反之越暗,這個也和實際情況相符。

9.6 ALPHA CHANNELS

一般比如上一章節 最終ps 傳出 diffuse texture 的alpha,作為 src的alpha值。

介紹DXTex 工具可以在把一張只有rgb的和一張作為alpha的灰度圖合併,把灰度圖作為alpha channel插入進去。這種photoshop啥的都可以。

9.7 CLIPPING PIXELS

呼叫clip(x) 方法可以裁剪掉 傳入x<0 的畫素,一般傳入alpha,如果alpha小於0,表示不可見,直接丟棄

因此ps中加入引數gAlphaClip, 如果為true,會執行裁剪。

image7

雖然用blend也可以做到,但這個更高效,不用執行blend,之後的ps程式碼也可以不用執行。

這裡的例子中注意丟棄畫素之後,object的背面可能也需要畫出來,因此需要關閉背面剔除。

9.8 FOG

模擬天氣霧效有以下好處

1.遮擋遠端物件,減少繪製

2.阻止poping現象發生,這是說遠處一個物體本來在視錐體之外,由於相機移動到了視錐體之內,它會突然出現,非常突兀。

3.另外即使是晴天,也會需要在遠距離又一些霧效,比如遠處的山也需要給予深度的朦朧效果,模擬大氣散射效果。

計算方式:

首先 foggedcolor用 係數s 混合 litcolor和 fogcolor

image8

s的計算是基於 定義 fogStart和fogRange,霧的起始距離和範圍。

iamge9

saturate 方法會clamp 傳入的值到0~1.

image10

所以可以看到 fog 完全不影響 fogstart之前的object的顏色,而fogend=fogstart+fogrange之後的object會完全隱藏掉。

例子中fog計算會在ps的最後,再計算了litColor之後再最終混合霧效。

例子中一個是distToEye 和toEye 計算了兩次可以優化一下。一個是 添加了wireframe,lighting,fog三種模式,可以對比檢視。