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

这应该使您更好地了解如何在片断着色器中执行操做。

尝试实现其余一些过滤器,例如饱和度或活力度过滤器。

明天见👋

相关文章
相关标签/搜索