使用ShaderMaterial实现InstancedMesh间Figma的mix-blend-mode: overlay混合效果遇到的技术问题
使用ShaderMaterial实现InstancedMesh间Figma的mix-blend-mode: overlay混合效果遇到的技术问题
最近我在做一个Three.js项目,需要让InstancedMesh的各个实例之间实现类似Figma里mix-blend-mode: overlay的混合效果。目前用Three.js自带的混合模式(比如Additive、Subtractive)虽然能正常运行,但出来的效果和设计稿完全对不上——Figma里的圆形叠加出来的层次感和颜色过渡是overlay模式特有的,原生混合模式根本做不到。
我试着把GLSL的overlay混合逻辑写到了InstancedMesh用的ShaderMaterial里,代码大概是这样的:
uniform vec3 uColors[6]; uniform float uThresholds[6]; varying vec2 vUv; float blendOverlay(float base, float blend) { return base<0.5?(2.0*base*blend):(1.0-2.0*(1.0-base)*(1.0-blend)); } vec3 blendOverlay(vec3 base, vec3 blend) { return vec3(blendOverlay(base.r,blend.r),blendOverlay(base.g,blend.g),blendOverlay(base.b,blend.b)); } vec3 blendOverlay(vec3 base, vec3 blend, float opacity) { return (blendOverlay(base, blend) * opacity + base * (1.0 - opacity)); } void main() { vec3 color = mix(uColors[0], uColors[1], smoothstep(uThresholds[0], uThresholds[1], vUv.y)); color = mix(color, uColors[2], smoothstep(uThresholds[1], uThresholds[2], vUv.y)); color = mix(color, uColors[3], smoothstep(uThresholds[2], uThresholds[3], vUv.y)); color = mix(color, uColors[4], smoothstep(uThresholds[3], uThresholds[4], vUv.y)); color = mix(color, uColors[5], smoothstep(uThresholds[4], uThresholds[5], vUv.y)); // 这里卡壳了!不知道该怎么获取已经绘制的实例颜色作为base参数 gl_FragColor = vec4(blendOverlay(color.rgb, ???), 1.0); }
我明白要实现这个混合,应该需要用sampler2D类型的uniform来传入已经绘制的内容作为纹理,但问题是这些纹理该怎么生成?如果只是和一个静态背景混合,我还能把InstancedMesh渲染到RenderTarget里当纹理用,但现在是所有InstancedMesh的实例之间要互相叠加混合,难道要把每个实例单独渲染到RenderTarget然后逐个保存纹理吗?感觉这个思路不仅麻烦,性能上也会有问题,实在有点摸不着头绪,有没有大佬能指点一下?
备注:内容来源于stack exchange,提问作者Teel
相关产品推荐
相关产品推荐

