- 原文地址: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); }
结果:
这应该使您更好地了解如何在片断着色器中执行操做。
尝试实现其余一些过滤器,例如饱和度或活力度过滤器。
明天见👋