WebGL blendMode 詳解

一、簡單介紹

          blendMode 翻譯過來也就是大家常說的顏色混合模式,或者大家在 PS 裏見過得圖層之間的混合模式。具體概念就不在這裏詳談了,不太明白的可以先搜索一下,只要有普通的概念就好了,接下來看看 WebGL 是如何處理一個個的圖像,並正確顯示它們混合之後的顏色的。


二、webgl 中的 blendMode 函數

     (這一章看完可能會不懂,結合第三章再反過來查閱這一章,就會明白。所以這一章只是API參考,跟很多講 webgl 、 opengl 的書籍一樣,需要結合栗子甚至實際操作結合才能理解、明白這些概念)

       在 webgl 裏有如下幾個函數控制 blendMode :

       1. gl.blendEquation(enum mode)

       2. gl.blendEquationSeprate(enum modeRGB,enum modeAlpha)

       3. gl.blendFunc(enum src, enum dst)

       4. gl.blendFuncSeprate(enum srcRGB, enum dstRGB, enum srcAlpha, enum dstAlpha)

       5. gl.blendColor(r,g,b,a)


2.1 blendEquation

       其中 函數 1 和 2 是做同一件事情。

       gl.blendEquation(gl.FUNC_ADD) 等同於 gl.blendEquation(gl.FUNC_ADD,gl.FUNC_ADD)。

       gl.blendEquation 的可選參數如圖



2.2 blendFunc

       函數3 和 4 是做同一件事。

       gl.blendFunc(gl.ONE,gl.ZERO) 就相當於 gl.blendFuncSeprate(gl.ONE,gl.ZERO,gl.ONE,gl.ZERO)。

       gl.blendFunc 的可選參數如圖


R、G、B、A 分別都有下標,這些下標是指:

       首先明確一個概念,假設 webgl 裏面有一塊顏色畫板 (dst),這個時候我們要畫一個對象 M (src) 上去,這樣可以得到更新的畫板,下次再畫對象 N (src)時,取最新的畫板顏色 (dst) 進行混合就可以得到下一次的混合底色 (dst) 或者 最終顏色 。

s 即 src,也就是要要疊加的對象的顏色。

d 即 dst,也就是畫板上得顏色。

c 即 const,也就是 gl.blendColor 指定的顏色,默認情況下 gl.blendColor 的顏色爲 (1,1,1,1)

畫板初始的顏色全部爲 (0,0,0,0),如果調用過 gl.clearColor(r,g,b,a) 就是 gl.clear 刷新過的 (r,g,b,a)。


三、栗子

       接下來看個實際的栗子,看看這些函數到底是怎麼控制顏色混合的。

       例如文字 FPS,放大後我們可以看到它的邊緣有一些半透明的顏色(抗鋸齒效果,不至於全是實線,實線轉彎的地方鋸齒很嚴重): 

       接下來看看幾種情況下繪製的結果和我們的推算。

 

情況一:

              gl.clearColor(0,0,0,0);

              繪製文字("FPS");

        這裏並沒有調用任何 blendMode 相關的函數,也就是各個情況都是默認的。也就是相當於:

        gl.blendColor(1,1,1,1)

        gl.blendEquationSeprate(gl.FUNC_ADD, gl.FUNC_ADD)

        gl.blendFuncSeprate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA)

取文字FPS邊緣的一個半透明像素考慮 (F上面那一橫,用QQ截圖就能看到顏色,截圖會看到那一行的像素顏色爲(113,113,113)),像素顏色爲 (0,0,0,143/255)。

        1. 在調用 gl.clearColor(0,0,0,0) 後,所有的顏色清除爲 (0,0,0,0)

        2. 繪製文字 FPS,那麼 src 的顏色爲 (0,0,0,0.5),dst 的顏色爲 (0,0,0,0)

        3. 採用混合參數可以知道  (參考第二章的混合參數設置,中間的 + 來自 gl.blendEquationSeprate 的第一個參數)

            r = srcR * srcAlpha + dstR * (1 - srcAlpha) = 0 * 143/255 + 0 * (1 -143/255) = 0 

            g = srcG * srcAlpha + dstG * (1 - srcAlpha) = 0 *143/255 + 0 * (1 -143/255) = 0 

            b = srcB * srcAlpha + dstB * (1 - srcAlpha) = 0 *143/255 + 0 * (1 -143/255) = 0 

            a = srcA * 1 + dstA * (1 - srcAlpha) =143/255 * 1 + 0 * (1 -143/255) =143/255

        4. 混合之後的顏色爲 (0,0,0,143/255)

        5. 由於網頁背景色是 (1,1,1,1),所以網頁背景色再跟 (0,0,0,143/255) 做混合就可以得到 

            r = srcR * srcAlpha + dstR * (1 - srcAlpha) = 0 *143/255 + 1 * (1 -143/255) = 113/255

            g = srcG * srcAlpha + dstG * (1 - srcAlpha) = 0 *143/255 + 1 * (1 -143/255) =113/255

            b = srcB * srcAlpha + dstB * (1 - srcAlpha) = 0 *143/255 + 1 * (1 -143/255) =113/255

            a = srcA * 1 + dstA * (1 - 143/255) = 143/255 * 1 + 1 * (1 - 143/255) = 1

        可能有人會說這樣推出的結果其實不靠譜,因爲我又不知道 F 上面那橫如果沒有任何顏色疊加真正的顏色是什麼,其實可以在 PS 裏看到,這個 F 的字體是 Heletica ,24 號字體,放大了4倍。

        當然我們可以繼續用別的顏色混合看看結果是否正確(情況二)。

        不過我可以明確的說明,這裏我沒有在 PS 裏取色,而是用了混合公式反推出的原始顏色。


情況二:

             gl.clearColor(1,0,0,0);

             繪製文字("FPS");

          先看看結果:

          結果表明,在文字有顏色的地方會顯示黑色和紅色(半透明的邊緣像素),沒有顏色的地方是白色。

          先取文字FPS邊緣的一個半透明像素 (0,0,0,143/255) 做混合後顯示的顏色爲:

          1. 經過 gl.clearColor(1,0,0,0) 之後像素顏色爲 (1,0,0,0)

          2. 疊加顏色 (0,0,0,143/255) 之後

            r = srcR * srcAlpha + dstR * (1 - srcAlpha) = 0 *143/255 + 1 * (1 -143/255) =113/255

            g = srcG * srcAlpha + dstG * (1 - srcAlpha) = 0 *143/255 + 0 * (1 -143/255) = 0 

            b = srcB * srcAlpha + dstB * (1 - srcAlpha) = 0 *143/255 + 0 * (1 -143/255) = 0 

            a = srcA * 1 + dstA * (1 - srcAlpha) =143/255 * 1 + 0 * (1 -143/255) =143/255

          3. 混合的顏色爲 (113/255,0,0,143/255)

          4. 混合網頁底色 (1,1,1,1) 和 (113/256,0,0,143/255) 之後

            r = srcR * srcAlpha + dstR * (1 - srcAlpha) = (113/255) * (143/255) + 1 * (1 - 143/255) = 206/255

            g = srcG * srcAlpha + dstG * (1 - srcAlpha) = 0 *143/255 + 1 * (1 -143/255) = 113/255

            b = srcB * srcAlpha + dstB * (1 - srcAlpha) = 0 *143/255+ 1 * (1 -143/255) = 113/255

            a = srcA * 1 + dstA * (1 - srcAlpha) = 143/255 * 1 + 1 * (1 - 143/255) = 1

          5. 混合之後的顏色爲 (206/255,113/255,113/255,1),QQ 截圖之後發現顏色爲 (233,112,115),之後又測試了純色塊的 (0,0,0,143/255) 發現顏色爲 (226,113,113)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章