13 | 如何给简单的图案添加纹理和复杂滤镜?
月影
该思维导图由 AI 生成,仅供参考
你好,我是月影。
上一课我们讲了两类处理像素的滤镜,分别是颜色滤镜和高斯滤镜。其中,颜色滤镜是基本的简单滤镜。因为简单滤镜里的每个像素都是独立的,所以它的处理结果不依赖于其他像素点的信息,因此应用起来也比较简单。而高斯滤镜也就是平滑效果滤镜,它是最基本的复杂滤镜。复杂滤镜的处理结果不仅与当前像素有关,还与其周围的像素点有关,所以应用起来很复杂。
当然了,颜色滤镜和高斯滤镜能够实现的视觉效果有限。如果想要实现更复杂的视觉效果,我们还需要使用更多其他的滤镜。所以这一节课,我们就来说说,怎么结合不同滤镜实现更复杂的视觉效果。
其他简单滤镜在 Canvas 中的应用
我们知道,简单滤镜的处理效果和像素点的颜色有关。其实,还有一些简单滤镜的处理效果和像素点的坐标、外部环境(比如鼠标位置、时间)有关。这些滤镜虽然也是简单滤镜,但能实现的效果可不简单。让我们来看几个有趣的例子。
第一个例子,实现图片边缘模糊的效果。
如上面代码所示,我们可以在遍历像素点的时候计算当前像素点到图片中心点的距离,然后根据距离设置透明度,这样我们就可以实现下面这样的边缘模糊效果了。
边缘模糊效果示意图
第二个,我们可以利用像素处理实现图片融合。比如说,我们可以给一张照片加上阳光照耀的效果。具体操作就是,把下面这张透明的 PNG 图片叠加到一张照片上。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
本文介绍了如何在WebGL中利用纹理和滤镜实现复杂的视觉效果。作者详细讲解了创建纹理对象的步骤,包括设置纹理参数和在Shader中使用纹理对象的方法。文章还介绍了如何实现图片灰度化滤镜,通过引入颜色矩阵并在片元着色器中对颜色向量进行仿射变换来实现。此外,作者提到了使用gl-renderer库可以简化纹理加载和设置的步骤,使得操作更加便捷。另外,文章还讨论了边缘模糊和纹理叠加这两种滤镜,并且重点学习了用Shader加载纹理和实现滤镜的方法。通过具体的代码示例和技术原理,读者可以了解WebGL中纹理和滤镜的应用,以及如何利用Shader实现复杂的视觉效果。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《跟月影学可视化》,新⼈⾸单¥68
《跟月影学可视化》,新⼈⾸单¥68
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(7)
- 最新
- 精选
- 木瓜777shader中有很多数字,为什么是这些数字?
作者回复: 如果你说的是随机数函数里的数字,那个数字就是随便写的一个大数,因为伪随机用正弦函数小数点后几位来模拟随机
2020-07-2221 - Zackwebgl实现灰度化,为什么要先把颜色矩阵转置?
作者回复: 因为行主序和列主序问题,与矩阵乘法具体实现有关
2020-12-093 - MG.Fre马赛克效果:对纹理坐标做放大缩小处理,st = floor(vUv * 50.0) / 50.0;精度丢失;局部马赛克的话,加坐标范围的判断就可以了。2021-07-221
- 有一种踏实局部“马赛克”主要实现: // 片元着色器 const fragment = ` #ifdef GL_ES precision highp float; #endif uniform sampler2D tMap; uniform int start; uniform vec2 mousepos; uniform float radiusX; uniform float radiusY; varying vec2 vUv; float random (vec2 st) { return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123); } void main() { vec4 color = texture2D(tMap, vUv); if (start > 0 && pow(abs(mousepos.x - vUv.x), 2.0) / pow(radiusX, 2.0) + pow(abs(mousepos.y - vUv.y), 2.0) / pow(radiusY, 2.0) <= 1.0) { vec2 st = vUv * vec2(100, 55.4); vec2 uv = vUv + 1.0 - 2.0 * random(floor(st)); color = texture2D(tMap, uv); } gl_FragColor = color; } `; // uniform 更新 const { canvas } = renderer; const { width, height } = canvas; const rect = canvas.getBoundingClientRect(); let start = false; renderer.uniforms.start = 0; renderer.uniforms.mousepos = [0, 0]; const radiusPX = 100; renderer.uniforms.radiusX = radiusPX / width; renderer.uniforms.radiusY = radiusPX / height; canvas.addEventListener('mousemove', e => { if (start) { const x = (e.clientX - rect.left) / width; const y = (height - (e.clientY - rect.top)) / height; renderer.uniforms.mousepos = [x, y]; } else { start = true; renderer.uniforms.start = 1; } });2023-11-29归属地:上海
- Geek_00734e因为原始图像的图片像素宽高是 1000px 和 554px,所以我们用 vec2 st = vUv * vec2(100, 55.4) 就可以得到 10px X 10px 大小的网格。 这一段不理解,为啥100, 55.4 就是10X10的网格? 就因为1000/100 = 10 ?想不通2023-02-16归属地:浙江
- Geek3340if(cat.r < 0.5 && cat.g > 0.6) { 请问 这里的 阀值是如何得到的呢2021-06-27
- 番薯尝试了用webgl写高斯模糊和马赛克,发现个问题:片元着色器里,循环和数组都不能带uniform变量,只能直接hardcode代表半径的数字进去,写片元就是这样吗?还是有更合适的方法? https://codepen.io/sfyan-the-styleful/pen/OJbpXzx https://codepen.io/sfyan-the-styleful/pen/KKNWEgQ2021-02-16
收起评论