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三種模式,可以對比檢視。