Canvas 2D 中用 globalCompositeOperation 实现纹理叠加需先绘主体、再设合成模式(如 "overlay")、最后 drawImage 纹理图;SVG 滤镜受限于兼容性与平铺能力;WebGL 方案最灵活但需处理 sRGB、GPU 兼容及纹理上传等细节。

Canvas 2D 上用 globalCompositeOperation 实现纹理叠加
HTML5 本身没有叫“纹理叠加滤镜”的内置 API,真正能快速叠加纹理的是 CanvasRenderingContext2D 的合成模式。核心是把一张纹理图(比如噪点、纸纹、划痕 PNG)画在已有内容之上,并控制混合方式。
常见错误是直接用 drawImage 覆盖导致丢失原图细节——必须改写 globalCompositeOperation 才生效。
-
globalCompositeOperation = "overlay"或"soft-light"效果最接近 Photoshop 的叠加模式,但注意:这些值在部分旧版 Safari 中不支持,需降级为"multiply"或"screen" - 纹理图建议用带 Alpha 通道的 PNG,透明区域不会干扰底层内容
- 绘制顺序很重要:先画主体内容,再设
globalCompositeOperation,最后drawImage纹理图
用 CSS filter: url(#texture) 做 SVG 滤镜叠加的限制
如果想对任意 HTML 元素(比如一个 典型问题:纹理图路径必须同源或 CORS 开启; 立即学习“前端免费学习笔记(深入)”; 真正灵活的纹理叠加(如调整强度、混合系数、UV 偏移)得靠 WebGL。这时“滤镜”其实是写在 这里 如果项目已用 Three.js,别自己写 shader。用 例如把纸纹图塞进 真正难的不是叠加动作本身,而是让纹理在不同缩放、光照、色彩空间下看起来一致——这需要实机多设备反复调参,不是套个公式就能搞定的。 + ,但实际兼容性和可控性较差。 不支持缩放/平铺,纹理容易拉伸失真;Firefox 对 feImage 的 preserveAspectRatio 支持不稳定。
包裹 才能平铺纹理,否则只显示一次feBlend mode="overlay" 是关键,但 Safari 目前只支持 "normal"、"multiply"、"screen" 这三种 modeWebGL 方案里纹理叠加本质是 fragment shader 计算
fragmentShader 里的几行 GLSL:uniform sampler2D u_texture;
uniform sampler2D u_noise;
varying vec2 v_uv;
void main() {
vec4 base = texture2D(u_texture, v_uv);
vec4 noise = texture2D(u_noise, v_uv * 5.0); // 放大纹理频率
gl_FragColor = mix(base, overlay(base.rgb, noise.rgb), noise.a * 0.3);
}overlay() 需手写函数(不是内置),且 mix() 的第三个参数控制纹理强度。容易踩的坑:
texture2D 多采样容易崩,建议预乘 Alpha 并用 NEAREST 滤波texImage2D 上传,且图片需已加载完成Three.js 中用
MeshStandardMaterial 叠加纹理更省事roughnessMap 或 aoMap 当占位纹理通道,配合自定义 onBeforeCompile 注入混合逻辑更稳妥。aoMap,然后在 shader 中重映射它的作用:
material.aoMap = noiseTexture,并启用 material.aoMapIntensity = 0.4
onBeforeCompile 找到 vec3 outgoingLight 计算位置,插入 outgoingLight = overlay(outgoingLight, texture2D(aoMap, vUv).rgb)
vUv 可能被 UV 动画修改,若纹理要固定不动,得额外传入 vUvNoTransform










