簡體   English   中英

opengl es2預乘與直接alpha +混合

[英]opengl es2 premultiplied vs straight alpha + blending

在iphone上的Opengl es2。 一些對象由多層精靈與alphas組成。

然后我也有UI元素,它們也是由各種精靈組合在一起的,我淡入/淡出其他一切。 我通過調整着色器中的alpha來淡化。

我的紋理是PNG與alphahop中制作的alpha。 我沒有故意為他們做好准備。 我希望它們是直的alpha,但在我的應用程序中,它們表現得好像它們被預先乘以我可以看到在白色背景上繪制的白色精靈周圍的黑色邊緣。

如果我將混合模式設置為:

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

這些元素很好地融合在一起,沒有奇怪的邊緣。 但是當元素逐漸消失時,它們最終會成為POP。 它們將開始消退但不會一直下​​降到alpha零。 所以在淡出動畫結束時,當我刪除元素時,它們“彈出”會導致它們沒有完全消失。

如果我將混合模式切換為:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

元素很好地淡化和淡化。 但是白色元素上的任何白色都有一個看起來像alpha預乘的暗邊緣。 查看白框頂部繪制的白色圓圈:

在此輸入圖像描述

但是場景中的其他混合物對我來說很好看。 其他透明物體很好地融合在一起。

另一個重要的注意事項是我的着色器處理元素和顏色元素的不透明度。 對於繪制的每個東西,我乘以元素顏色,最后的alpha乘以不透明度值:

void main(void)
{
    gl_FragColor = texture2D(u_textureSampler,v_fragmentTexCoord0);
    gl_FragColor = vec4(gl_FragColor.r*u_baseColor.r,gl_FragColor.g*u_baseColor.g,gl_FragColor.b*u_baseColor.b,gl_FragColor.a*u_baseColor.a * u_opacity);
}

這允許我在我的精靈表中拍攝一個白色物體,並使其成為我想要的任何顏色。 或者使用灰色的baseColor使對象變暗。

每當我想到我理解這些混合模式時,我就會開始懷疑自己。

是否有其他混合模式組合在我的精靈上有光滑的邊緣,並且還支持着色器中的alpha淡化/混合?

我假設需要GL_SRC_ALPHA在着色器中使用alpha進行混合。

或者我的問題是我需要使用除PSD以外的東西來保存我的精靈表嗎? 因此在這一點上幾乎是不可能的。

更新:

我認為答案可能只是否定,沒有辦法做我想要的。 第二種混合模式應該是正確的。 但它有可能是將RGB與某個地方的alpha相乘,或者它在源文件中被預乘。 我甚至嘗試通過添加以下內容在上面的着色器中預先復制alpha:

gl_FragColor.rgb *= glFragColor.a;

但這只會使衰落看起來很糟糕,因為當它們逐漸淡出時,它們會變成灰色。 如果我自己預先設定alpha並使用上面的其他混合模式,那么事情就像我原來的一樣。 它們在沒有彈出的情況下逐漸消失,但你仍然可以看到光環。

這是一篇關於如何避免帶有直紋alpha紋理的黑條紋的精彩文章http://www.realtimerendering.com/blog/gpus-prefer-premultiplication/

如果你正在使用mip-maps,這可能就是你的直線alpha紋理有黑條紋的原因 - 過濾直線alpha圖像會導致這種情況發生,最好的解決方案是在mip-maps之前預先乘以圖像。創建。 有一個常見的黑客修復,如該文章中所述,但認真考慮預乘。

使用直線α來創建紋理通常是必要且首選的,但是在構建步驟的一部分或紋理加載期間將它們預先乘以比將它們保持為內存中的直線更好更好。 我不確定OpenGL ES,但我知道WebGL允許你在加載期間通過gl.pixelPorei和gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL參數在運行中預加倍紋理。

另一種可能性是,如果你要合成許多元素,你的直接alpha混合函數是不正確的。 為了使用直接alpha圖像做一個正確的“over operator”,你需要使用這個混合函數,也許這就是你要找的東西:

gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);

您引用的常見直接alpha混合函數(gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA))無法正確處理目標Alpha通道,在混合直接alpha圖像源時,必須使用單獨的顏色和alpha混合函數,如果您打算使用“over運算符”合成多個圖層。 (考慮一下你可能不想插入alpha通道,它應該總是比source和dest更不透明。)並且在混合時要特別小心,因為直alpha混合的結果是預乘圖像! 因此,如果您稍后使用結果,您仍然必須准備好進行預乘混合。 對於更長的解釋,我在這里寫了這篇文章: https//limnu.com/webgl-blending-youre-probably-wrong/

使用預乘圖像和混合的好處是你不必為顏色和alpha使用單獨的混合函數,並且你自動避免了很多這些問題。 你可以&應該創建直的alpha紋理,但是在加載之前或加載期間預加倍,並在整個代碼中使用復合混合(glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA))。

AFAIK, glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 是預乘的alpha,如果按原樣使用顏色,它應該可以正常工作。 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 是直的阿爾法。

許多紋理加載框架隱式地將圖像轉換為預乘的alpha格式。 這是因為他們中的許多人正在將圖像重新繪制成新圖像,而CGBitmapContext不支持直接(非倍增)圖像。 因此,它們通常會生成預乘的α圖像。 因此,請查看紋理加載代碼,並檢查它是否已轉換為預乘格式。

此外,Photoshop(當然是Adobe的)在導出到PNG時隱式擦除完全透明(alpha = 0)像素上的顏色信息。 如果使用線性或其他紋理過濾,則GPU將對相鄰像素進行采樣,透明像素中的顏色將影響邊緣處的像素。 但Photoshop已經刪除了顏色信息,因此它們會有一些隨機顏色值。

從理論上講,可以通過在透明像素上保持正確的顏色值來修復這種顏色滲色。 無論如何,使用Photoshop,我們沒有實用的方法來導出PNG文件並保持正確的顏色值,因為Photoshop不尊重隱形的東西。 (需要編寫一個專用的PNG導出器Photoshop插件來正確導出它們,我不能很好地支持這個)

預乘alpha只是為了顯示圖像,但如果使用任何着色器顏色魔法它將無法正常工作,因為顏色以整數形式存儲,因此它通常沒有足夠的精度來恢復原始顏色值。 如果您需要精確的顏色魔法物品,請使用直接alpha - 避免使用Photoshop。


更新

這是我在iPhone模擬器上的@ SlippD.Thompson測試代碼的測試結果(64位/ 7.x)

 <Error>: CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 24 bits/pixel; 3-component color space; kCGImageAlphaNone; 2048 bytes/row.
    cgContext with CGImageAlphaInfo 0: (null)
    cgContext with CGImageAlphaInfo 1: <CGContext 0x1092301f0>
    cgContext with CGImageAlphaInfo 2: <CGContext 0x1092301f0>
 <Error>: CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 32 bits/pixel; 3-component color space; kCGImageAlphaLast; 2048 bytes/row.
    cgContext with CGImageAlphaInfo 3: (null)
 <Error>: CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 32 bits/pixel; 3-component color space; kCGImageAlphaFirst; 2048 bytes/row.
    cgContext with CGImageAlphaInfo 4: (null)
    cgContext with CGImageAlphaInfo 5: <CGContext 0x1092301f0>
    cgContext with CGImageAlphaInfo 6: <CGContext 0x1092301f0>
 <Error>: CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 24 bits/pixel; 0-component color space; kCGImageAlphaOnly; 2048 bytes/row.
    cgContext with CGImageAlphaInfo 7: (null)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM