2016-01-22 88 views
0

我努力做到以下幾點:Alpha混合利用兩個渲染目標(的DirectX或OpenGL)

  • 創建一個透明的質感稱爲T

  • 渲染一個名爲Q紋理四到T

  • 渲染噸至屏幕

注意T的alpha分量將爲零,Q的alpha分量可能小於1。

我需要兩個alpha混合方程,這樣如果我將Q的多個實例渲染到T(使用第一個混合方程),然後渲染T(使用第二個混合方程),它將與直接渲染Q的多個實例相同到屏幕上。

我用這種混合等式

color = src * srcAlpha + dst * (1 - srcAlpha) 
alpha = 1 * srcAlpha + 0 * destAlpha 

的情況下,當我直接呈現補足至屏幕,但不能定義實現同樣的事情時,我第一次呈現給T這兩種混合方程。

請注意,T的像素最初是完全透明的(alpha = 0),因爲我不希望它覆蓋屏幕,如果它沒有被繪製到。 Q在每個像素中可以具有任何透明度級別。

+0

對不起,我已經糾正了我的問題零應該是一個。 – keith

回答

0

我已經想通了這一點,並賦予它不是我在其他地方看到在互聯網上,我希望這會幫助別人......

對於第一個混合式,爲四邊形Q渲染與T :

Q - >Ť

color = src * srcAlpha + dst * (1 - srcAlpha) 
alpha = 1 * srcAlpha + (1 - srcAlpha) * destAlpha 

對於第二共混物方程,T將在屏幕:

筆 - >取值

color = src * 1 + dst * (1 - srcAlpha) 
alpha = doesn't matter as screen alpha isn't used 

說明

對於化合物Q - > T,對於彩色分量的方程式是按正常阿爾法混合方程:

color = src * srcAlpha + dst * (1 - srcAlpha) 

但是我們需要確保alpha通道是爲第二部分設立的。因爲我們使用這個混合等式有效地將Q的alpha值預渲染到T上,所以我們只需要第二階段的alpha就可以確定在渲染T的時候屏幕顏色的暗淡程度,因此Alpha所述第一等式爲:

alpha = 1 * srcAlpha + (1 - srcAlpha) * destAlpha 

但我們只用它來褪色T在第二方程中的顏色後面的目標顏色(我們使用1 SRC顏色因爲這是由式(1)預相乘):

color = src * 1 + dst * (1 - srcAlpha) 

在DirectX 11中,無論使用方程式1直接渲染到屏幕還是使用兩個方程渲染t然後是屏幕。

代碼DirectX 11的(誰喜歡真正的代碼的人):

一號公式:

D3D11_BLEND_DESC blend{}; 

blend.AlphaToCoverageEnable = FALSE; 

auto& target = blend.RenderTarget[0]; 

target.BlendEnable = TRUE; 
target.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; 

target.SrcBlend = D3D11_BLEND_SRC_ALPHA; 
target.DestBlend = D3D11_BLEND_INV_SRC_ALPHA; 
target.BlendOp = D3D11_BLEND_OP_ADD; 

target.SrcBlendAlpha = D3D11_BLEND_ONE; 
target.DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; 
target.BlendOpAlpha = D3D11_BLEND_OP_ADD; 

第二個公式:

D3D11_BLEND_DESC blend{}; 

blend.AlphaToCoverageEnable = FALSE; 

auto& target = blend.RenderTarget[0]; 

target.BlendEnable = TRUE; 
target.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; 

target.SrcBlend = D3D11_BLEND_ONE; 
target.DestBlend = D3D11_BLEND_INV_SRC_ALPHA; 
target.BlendOp = D3D11_BLEND_OP_ADD; 

target.SrcBlendAlpha = D3D11_BLEND_ZERO; 
target.DestBlendAlpha = D3D11_BLEND_ONE; 
target.BlendOpAlpha = D3D11_BLEND_OP_ADD; 

T爲初始清零{0,0 ,0,0}。

+0

我不認爲這是正確的。看看你的Q->Tα方程(alpha = 1 * srcAlpha +(1-srcAlpha)* destAlpha)。如果你要渲染兩個四邊形,都是0.5 alpha,那麼將會使得T的alpha 1.0,當它應該是0.75時。 – Columbo

+0

@Columbo,我認爲你是不正確的。如果quad是一個像素並且具有'color {c,c,c,0.5}',則第一個渲染爲T的四元組的alpha將爲:'alpha = 1 * srcAlpha +(1 - srcAlpha)* destAlpha'其中' srcAlpha = 0.5'和'destAlpha = 0',因爲destAlpha是最初爲零的T的alpha。在頂部呈現的第二個Q將是:'srcAlpha = 0.5',現在在T'destAlpha = 0.5'中(從T中的先前呈現的四元組),其從'alpha = 1 * srcAlpha給出'0.75'的T的正確的字母+(1 - srcAlpha)* destAlpha'。我也試過了,看到它有效:-) – keith

+0

對不起。你是對的。 – Columbo

0

你在問什麼在數學上不可能使用線性插值。

比方說,你有兩個透明物體,AB。你有你的紋理T,和屏幕SBlend是混合方程。

你與渲染T做的是:

T = Blend(B, Blend(A, T)) 
S = Blend(T, S) 

//Therefore 
S = Blend(Blend(B, Blend(A, T)), S) 

見怎麼也有3個獨立的混合操作在這裏?你不能用兩個混合操作。如果你渲染AB,你就會得到這些。

線性插值既不是commutative也不是associative。混合操作的順序事宜。而且,通過寫入臨時中間文件並將其混合到最終緩衝區不能實現的效果可以在沒有中介的情況下實現。

有混合操作是關聯和交換。例如,添加劑。但這幾乎肯定不會達到您想要的視覺效果,因爲它會將顏色添加到一起。如果你正在做HDR照明,這可能是你可以使用的東西。但是在很多情況下這是不合適的。

添加劑共混將涉及以下形式的共混物方程:

glBlendFunc(GL_SRC_ALPHA, GL_ONE); 

與源的α確定增加了傳入顏色的百分比。

+0

我很感激你花時間回覆。我設法弄清楚了這一點。也許我提出的問題很糟糕,但我認爲混合方程只做線性插值的假設是不正確的。在解決方案中,我的第二個方程式是'color = src * 1 + dst *(1 - srcAlpha)',它不是線性插值。這只是類似於混合函數f(x)'形式爲'a *(x)+ b *(1 - x)',而不是'a + b *(1 - x)'。 – keith

0

我想這樣的作品呈現Q入T時:

color = src * srcAlpha + dst * (1 - srcAlpha) 
alpha = (1 - destAlpha) * srcAlpha + 1 * destAlpha 

編輯:關於它的思考,我的回答會不會導致屏幕的Alpha通道匹配,當你直接渲染你所描述的alpha通道進入屏幕。直接渲染到屏幕時,您的alpha混合模式非常不尋常。我不確定是否真的希望屏幕的alpha代表您渲染的最後一個紋理的alpha,或者您是否確實不在乎屏幕的alpha通道是什麼樣子。在大多數渲染情況下,人們並不關心後臺緩衝區的alpha通道的狀態,希望情況就是這樣,我的答案適用於您。