- 原文地址:Day 9. Image filters
- 原文做者:Andrei Lesnitsky
這是 WebGL 系列的第 9 天教程,天天都有新文章發佈。git
源代碼在這裏web
第 8 天咱們學習瞭如何在 webgl 中使用紋理,接下來讓咱們利用這些知識來構建有趣的東西。函數
今天,咱們將探討如何實現簡單的圖像過濾器。學習
反轉顏色webgl
咱們要作的第一個最簡單的圖像過濾器,就是對圖像的全部顏色反轉的濾鏡。url
咱們如何反轉顏色?spa
原始值是在 [0..1]
範圍內。3d
若是咱們從每一個份量中減去 1,咱們將獲得負值,glsl
中就有一個 abs
函數。code
您還能夠像在 C/C++
中同樣,在 glsl
中定義除 void main
外的其它函數,所以讓咱們建立 inverse
函數。
📄 src/shaders/texture.f.glsl
uniform sampler2D texture; uniform vec2 resolution; + vec4 inverse(vec4 color) { + return abs(vec4(color.rgb - 1.0, color.a)); + } + void main() { vec2 texCoord = gl_FragCoord.xy / resolution; gl_FragColor = texture2D(texture, texCoord);
讓咱們中真正地使用它:
📄 src/shaders/texture.f.glsl
void main() { vec2 texCoord = gl_FragCoord.xy / resolution; gl_FragColor = texture2D(texture, texCoord); + + gl_FragColor = inverse(gl_FragColor); }
瞧,咱們有一個只有 4 行代碼的逆濾波器。
黑白濾鏡
讓咱們考慮一下如何實現黑白濾鏡。
白色是 vec4(1, 1, 1, 1)
黑色是 vec4(0, 0, 0, 1)
什麼是灰色陰影?顯然,咱們須要爲每一個顏色份量添加相同的值。
所以,基本上咱們須要計算每一個組件的「亮度」值。在很粗糙的實現方法中,咱們能夠將全部顏色份量相加併除以 3(算術平均值)。
注意:這不是最好的方法,由於不一樣的顏色會給出相同的結果(例如vec3(0.5, 0, 0)
和vec3(0, 0.5, 0)
,但實際上這些顏色具備不一樣的「亮度」,我只是想讓這些例子通俗易懂)。
好吧,讓咱們嘗試實現這個:
📄 src/shaders/texture.f.glsl
return abs(vec4(color.rgb - 1.0, color.a)); } + vec4 blackAndWhite(vec4 color) { + return vec4(vec3(1.0, 1.0, 1.0) * (color.r + color.g + color.b) / 3.0, color.a); + } + void main() { vec2 texCoord = gl_FragCoord.xy / resolution; gl_FragColor = texture2D(texture, texCoord); - gl_FragColor = inverse(gl_FragColor); + gl_FragColor = blackAndWhite(gl_FragColor); }
哇!看起來不錯。
棕褐色濾鏡
好的,接下來是能作出帶有奇特效果「老式」照片的棕褐色濾鏡。
棕褐色爲紅褐色,RGB值是 112, 66, 20
。
讓咱們定義 sepia
函數和和顏色:
📄 src/shaders/texture.f.glsl
return vec4(vec3(1.0, 1.0, 1.0) * (color.r + color.g + color.b) / 3.0, color.a); } + vec4 sepia(vec4 color) { + vec3 sepiaColor = vec3(112, 66, 20) / 255.0; + } + void main() { vec2 texCoord = gl_FragCoord.xy / resolution; gl_FragColor = texture2D(texture, texCoord);
有個粗糙的實現方法,是將必定比例的棕褐色混入原始顏色。有一個 mix
函數:
📄 src/shaders/texture.f.glsl
vec4 sepia(vec4 color) { vec3 sepiaColor = vec3(112, 66, 20) / 255.0; + return vec4( + mix(color.rgb, sepiaColor, 0.4), + color.a + ); } void main() { vec2 texCoord = gl_FragCoord.xy / resolution; gl_FragColor = texture2D(texture, texCoord); - gl_FragColor = blackAndWhite(gl_FragColor); + gl_FragColor = sepia(gl_FragColor); }
結果:
這應該使您更好地瞭解如何在片斷着色器中執行操做。
嘗試實現其餘一些過濾器,例如飽和度或活力度過濾器。
明天見👋