WebGL 系列 09 圖像過濾器

這是 WebGL 系列的第 9 天教程,天天都有新文章發佈。git

訂閱或者加入郵件列表以便及時獲取更新內容。github

源代碼在這裏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 行代碼的逆濾波器。

Inverse

黑白濾鏡

讓咱們考慮一下如何實現黑白濾鏡。

白色是 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);
  }

哇!看起來不錯。

Black and white

棕褐色濾鏡

好的,接下來是能作出帶有奇特效果「老式」照片的棕褐色濾鏡。

棕褐色爲紅褐色,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);
  }

結果:

Sepia

這應該使您更好地瞭解如何在片斷着色器中執行操做。

嘗試實現其餘一些過濾器,例如飽和度或活力度過濾器。

明天見👋

相關文章
相關標籤/搜索