I’m attempting to create custom blending effects for InstancedMesh objects using ShaderMaterial. Although the native THREE.JS blending modes such as Additive and Subtractive work decently, they fail to replicate the desired results based on my Figma design.
In Figma, I use a mix-blend-mode overlay for all the circular elements, and I’m aiming to achieve the same effect within Three.js utilizing my InstancedMesh objects.
I’ve come across some GLSL overlay blending functions and made an attempt to incorporate them into my fragment shader:
uniform vec3 uPalette[5];
uniform float uSteps[5];
varying vec2 vTexCoord;
float overlayBlend(float baseColor, float blendColor) {
return baseColor < 0.5 ? (2.0 * baseColor * blendColor) : (1.0 - 2.0 * (1.0 - baseColor) * (1.0 - blendColor));
}
vec3 overlayBlend(vec3 baseColor, vec3 blendColor) {
return vec3(overlayBlend(baseColor.r, blendColor.r), overlayBlend(baseColor.g, blendColor.g), overlayBlend(baseColor.b, blendColor.b));
}
vec3 overlayBlend(vec3 baseColor, vec3 blendColor, float alpha) {
return (overlayBlend(baseColor, blendColor) * alpha + baseColor * (1.0 - alpha));
}
void main() {
vec3 finalColor = mix(uPalette[0], uPalette[1], smoothstep(uSteps[0], uSteps[1], vTexCoord.y));
finalColor = mix(finalColor, uPalette[2], smoothstep(uSteps[1], uSteps[2], vTexCoord.y));
finalColor = mix(finalColor, uPalette[3], smoothstep(uSteps[2], uSteps[3], vTexCoord.y));
finalColor = mix(finalColor, uPalette[4], smoothstep(uSteps[3], uSteps[4], vTexCoord.y));
gl_FragColor = vec4(overlayBlend(finalColor.rgb, ???), 1.0);
}
My main challenge lies in needing sampler2D uniforms for the overlay function to operate correctly. What’s the best approach to render these textures? I recognize that if it were simply blending with a background, a render target could suffice. However, I require overlay blending among every individual InstancedMesh object. Should I be rendering each instance into separate render targets?