webgl濾鏡--會呼吸的痛

psychewang發表於2018-10-29

我們一起來完成一個webgl的濾鏡效果,可能有的人會問?為什麼要叫會呼吸的痛呢?沒有為什麼,因為剛睡醒
閒言少敘讓我們直接看一下效果。

webgl濾鏡--會呼吸的痛

是的,上面就是我們要實現的效果,不是整張圖片全部做一個濾鏡效果,而是在圖片的左上角做一個呼吸的紅色漸變效果。
我們分三步完成這個效果,第一步把圖片顯示出來,也就是沒有濾鏡效果的圖片顯示出來。
第二步為整張圖片做一個紅色的濾鏡效果。
第三步為區域性做一個呼吸的紅色濾鏡,也就是最終的效果了。

一 顯示整張圖片

顯示整張圖片這裡呢,你可以參考《webgl程式設計指南》這本書去做,當然我也會在最後附上我的程式碼,那裡面也有,我不想在此贅述過多的程式碼問題。
直接上最後的效果吧!

webgl濾鏡--會呼吸的痛

上面效果的實現,包括初始化快取區,向快取區寫入資料,為頂點賦值等等,因為此篇重點不在這,所以就不多說了。
通過上面呢,我們就將整張的圖片顯示了出來,接下來就是為整張圖片新增一個紅色的濾鏡效果了。

二 整體新增紅色濾鏡

我們知道一般顏色的體現是基於三原色光模式的,也就是r(紅色),g(綠色),b(藍色),三原色的色光以不同的比例相加,從而產生多種多樣的色光。
我們最後要實現的效果是在圖片的上面新增一個紅色的濾鏡,那麼我們需要改變的就是R值了。

webgl濾鏡--會呼吸的痛

上面的圖片中看到的是顯示整張圖片時候的片源著色器程式碼,我們只需要在29行和30行之間加上一句程式碼,就可以實現整張圖片的濾鏡效果。

webgl濾鏡--會呼吸的痛

第30行程式碼的含義就是為texture的三原色中的R值新增0.2
因為三原色的值在片源著色器中的範圍是0.0~1.0,因此我們新增的值需要控制在這個範圍之內,其餘的值你可以自己試一下看看是什麼效果。 讓我們看一下新增了全域性的濾鏡的效果。

webgl濾鏡--會呼吸的痛

OK,到此呢我們實現了主體的效果,接下來就是為右上角區域性新增呼吸濾鏡的效果了。重點來啦!

三 為區域性新增濾鏡效果

讓我們先看一下webgl中座標系的情況。

webgl濾鏡--會呼吸的痛

在webgl中,或者說在我這次新增的座標系中是這個樣子的,有的人會問:不對啊,明顯這個y軸的長度大於x軸的長度,但是還都是1.0。
事實就是我畫的這個樣子的,你別慌。
OK那麼我們接下來的思路就是獲取右上角的部分,然後為其新增顏色,問題來了,你要怎麼獲取右上角呢?按照區域劃分嗎?
不不不,我們這次不需要區域劃分,讓我們換一種思路思考一下。
如果我們還是為全域性新增濾鏡,但是按照不同的區域新增不同的效果,但是不需要區域劃分,我們先將每一個點的橫豎座標相乘。

webgl濾鏡--會呼吸的痛

圖中列舉了5個點,我們發現從左下角到右上角,橫豎座標相乘以後會變得越來越大,最大的是1.0。 那麼我們為不同點的R值新增上其橫豎座標相乘以後的值會是什麼效果呢?

webgl濾鏡--會呼吸的痛

最後的效果是不是就像單獨為右上角新增了紅色的濾鏡。
其實呢我們還是為整張圖片新增了濾鏡只是左下角新增的色值比較小,因此在效果上面看著不是那麼明顯。
現在效果是新增上了,但是怎麼讓濾鏡出現再消失呢?
我們在傳入片源著色器中的引數一般會包含一個變數,這個變數一般是為了做動畫的。這次我們就利用一下這個值。
我傳入的是一個從0.01一直在變大的time變數,然後在片源著色器中使用sin(time)函式來得到一個會在一定範圍內變化的變數值。

webgl濾鏡--會呼吸的痛

在上面的程式碼中,首先使用每一個點的x座標乘y座標(v_TexCoord.x*v_TexCoord.y)然後再乘sin(time)這樣就會得到一個類似於sin函式曲線的波動效果,為了調節效果呢,我在最後除了2.0,這個2.0你們可以試著換一下。
經過這些操作我們就得到了一個波動的color值,然後我們將這個color值賦值給texture的R,最後賦值給gl_FragColor,讓我們一起看一下效果。

webgl濾鏡--會呼吸的痛

前面的效果沒有問題了,已經為右上角新增上了濾鏡的效果,但是發現後半段會變成一個綠色的濾鏡,這個是為什麼呢?
原因在於sin()函式。

webgl濾鏡--會呼吸的痛

因為sin函式的波動是有正負值的(預設情況下),當color的值走到紅框內的時候濾鏡就會顯示紅色,當走到藍框內的時候就會顯示藍色了,但是藍色並不是我們想要的效果,如何修改程式碼來實現呢?
有人說做一個判斷就OK了,當color的值小於0.0的時候我們就不做什麼。
這樣判斷是可以,但是我們直接使用webgl的內建abs函式會更便捷一些。
最終的程式碼是:

webgl濾鏡--會呼吸的痛

以上呢我們就得到了我們想要的最終效果,一個呼吸的濾鏡,但是我在新增濾鏡的時候呢,使用的是加法,這樣會用問題。
假如說背景圖片是純黑色或者純白色的時候,那麼顯示的效果就會出現問題(也是一位大佬指點我才發現這個問題的),這個問題的解決方案呢,本次不會去贅述( juejin.im/post/5bcdad… )這個連結就是指點我的大佬出的解決方案你可以移步去他那裡看一下。

本文的最後我附上我的程式碼地址,你可以下載看一下,結構很簡單,只有一個html檔案,然後和引用的js,img檔案,並且在html的94行那裡我註釋了引用純黑除白的圖片程式碼,你可以試著研究一下。
程式碼地址:gitee.com/wangtao_it_…

相關文章