WebGL顏色合成
這是一個(gè)五彩繽紛的世界,彩色的玻璃讓窗外的風(fēng)景絢麗奪目。

我們可以把世界想象成一張畫布,這個(gè)世界里存在著兩種風(fēng)景:
source:即將落筆的風(fēng)景,比如彩色的玻璃。
destination:已經(jīng)落筆的風(fēng)景,比如窗外的城市。
當(dāng)這兩種風(fēng)景合到一起后,便會(huì)形成新的destination,進(jìn)入我們的眼睛。
在webgl 中有兩種合成顏色的方法:
blendFunc(sfactor, dfactor) 基于sfactor, dfactor對(duì)source和destination的rgba顏色做合成。
blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha) 基于srcRGB, dstRGB對(duì)source和destination的rgb顏色做合成;基于srcAlpha, dstAlpha對(duì)source和destination的alpha透明度做合成。
blendFunc(sfactor, dfactor) 適合對(duì)沒有透明度的顏色做合成;
blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha) 適合對(duì)有透明度的顏色做合成。
其中的參數(shù)需要按照下面的Constant來寫。

我們?cè)敿?xì)說一下上面的兩個(gè)合成方法。
blendFunc(sfactor, dfactor) 的計(jì)算原理如下:
舉個(gè)例子。
已知:
source是(0,0,1,1)
destination是(1,1,0,1)
sfactor是gl.ONE
dfactor是gl.ZERO
求:BlendColor
解:
上面的算法就是常見的顏色覆蓋,就像畫水粉一樣,頂上的source壓住下面的dfactor。
我們可以寫個(gè)webgl測(cè)試一下。
那如果黃色是半透明的會(huì)怎么樣呢?
改下代碼:
效果如下:

相信你可以看出,黃色變淡了。
這是為什么呢?用之前的公式印證一番即可:
由上可知,合成顏色的透明度變了。
但為什么合成顏色的透明度變了會(huì)導(dǎo)致顏色變淡呢?
這跟webgl顏色與canvas畫布背景色的合成方式有關(guān),其具體算法我先不細(xì)說,大家先知道顏色的透明度會(huì)影響顏色的最終渲染效果即可。
接下來,我們還要解決一個(gè)問題。
既然黃色半透明了,那黃色與藍(lán)色相交的部分就應(yīng)該有所變化。
這樣我們就得換一套合成因子了:
效果如下:

其算法如下:
通過上面的算法可以看到合成顏色變灰了。
但同時(shí)也出現(xiàn)了一個(gè)問題:合成區(qū)域的透明度變低了。
一個(gè)半透明的圖像合上一個(gè)不透明的圖像后,其透明度是不可能降低的。
因此,這個(gè)透明度需要與rgb分開計(jì)算。
webgl就提供了一個(gè)這樣的方法-blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha)。
改一下代碼,把之前的blendFunc()方法改成blendFuncSeparate()方法。
效果如下:

現(xiàn)在的合成顏色就明顯比之前顏色暗了。
看一下其算法:
因?yàn)橥该鞫鹊臉O大值就是1,所以1.5 的透明度依舊是1。
現(xiàn)在關(guān)于blendFunc()和blendFuncSeparate()的常規(guī)用法,我們就說完了。
我們還可以在其中寫入其它的constant,讓圖像出現(xiàn)不同的合成效果,其作用,大家可以聯(lián)想一下photoshop里的合成方式:

具體我就不給大家寫了,接下來再聊點(diǎn)其它的相關(guān)方法。
我們之前在合成source和destination的時(shí)候,用的是加法。
其實(shí),我們也可以用減法。
blendEquation(mode):blendFunc()方法中source和destination的合成方式。
gl.FUNC_ADD: source + destination (default value)
gl.FUNC_SUBTRACT: source - destination
gl.FUNC_REVERSE_SUBTRACT: destination - source
gl.MIN: Minimum of source and destination
gl.MAX: Maximum of source and destination
上面的mode我是從MDN里復(fù)制粘貼的,英語很好理解,不翻譯了。
既然blendFunc()有了一個(gè)blendEquation(),那blendFuncSeparate()也自然有一個(gè)blendEquationSeparate()。
blendEquationSeparate(modeRGB, modeAlpha):對(duì)應(yīng)blendFuncSeparate()中rgb和a的兩種合成方式,其中的參數(shù)類型與blendEquation()一樣。
在代碼里測(cè)試一下。
為了方便看減法效果,把藍(lán)色的點(diǎn)改成紫色。
效果如下:

相關(guān)算法就不寫了,理解這個(gè)功能就好,免得在three.js的合成里的遇到一堆沒見過的單詞。
參考鏈接:
https://wgld.org/d/webgl/w029.html
https://wgld.org/d/webgl/w030.html