- 原文地址:Day 9. Image filters
- 原文作者:Andrei Lesnitsky
这是 WebGL 系列的第 9 天教程,每天都有新文章公布。
订阅或者退出邮件列表以便及时获取更新内容。
源代码在这里
第 8 天咱们学习了如何在 webgl 中应用纹理,接下来让咱们利用这些常识来构建乏味的货色。
明天,咱们将探讨如何实现简略的图像过滤器。
反转色彩
咱们要做的第一个最简略的图像过滤器,就是对图像的所有色彩反转的滤镜。
咱们如何反转色彩?
原始值是在 [0..1]
范畴内。
如果咱们从每个重量中减去 1,咱们将失去负值,glsl
中就有一个 abs
函数。
您还能够像在 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);
}
后果:
这应该使您更好地理解如何在片段着色器中执行操作。
尝试实现其余一些过滤器,例如饱和度或活力度过滤器。
今天见????