THREE.patchShader is not a function

My goal is to add an image on top of an object material – as a sticker for a logo. This will be for things like coffee cup, T-shirt. I have the image as SVG so I have a canvas to draw onto and get the texture.

I’ve read a lot of things about multiple materials, copytexture and others and I’m going crazy. I got decals working fairly well, but then I realised I don’t want the projection method because of the wrap around edges makes the logo bend incorrectly. I could maybe pursue learning this more, but the projection stuff I found difficult indeed.

So after reading more, I opted for onBeforeCompile from this post [Images on top of textures] but it says patchShader is not a function so I must be missing something. I hope someone can help please.

In index.html I have thes
script type=“text/javascript” src=“https://threejs.org/build/three.js
script src=“https://mevedia.com/share/ShaderMaterialExtend.js?v4

and in a further down js, I traverse the object like so:

                    child.material.onBeforeCompile = function ( shader ) {
                            // 	// 		//	Use string.replace or this helper https://github.com/Fyrestar/ShaderMaterialExtend
                                                
                                            THREE.patchShader(shader, {
                                                
                                                  header: 'uniform sampler2D tDecal[3]; uniform vec4 uDecal[3];',
                                      
                                                  fragment: {
                                                    '#include <fog_fragment>': `
                                            
                                                    vec4 sc = vec4(0.0);
                                            
                                                    vec2 offset = uDecal[0].xy + vUv / uDecal[0].zw;
                                                    vec4 c = texture2D(tDecal[0], offset);
                                            
                                                    offset = uDecal[1].xy + vUv / uDecal[1].zw;
                                                    sc = texture2D(tDecal[1], offset);
                                                    c = mix(c, sc, sc.a);
                                            
                                                    offset = uDecal[2].xy + vUv / uDecal[2].zw;
                                                    sc = texture2D(tDecal[2], offset);
                                                    c = mix(c, sc, sc.a);
                                            
                                                    gl_FragColor = mix(gl_FragColor, c, c.a);
                                            
                                              `  
                                                  },
                                                  
                                                  uniforms: {
                                                    uDecal: [
                                                    new THREE.Vector4(-0.4, -0.6, .3, .3),
                                                    new THREE.Vector4(-0.45, -0.5, .3, .3),
                                                    new THREE.Vector4(-0.8, -0.2, .5, .5)
                                                    ],
                                                    tDecal: [
                                                    xxloader.load('https://threejs.org/examples/textures/sprite0.png'),
                                                    xxloader.load('https://threejs.org/examples/textures/sprite1.png'),
                                                    xxloader.load('https://threejs.org/examples/textures/sprite.png')
                                                    ]
                                            }	
                                                  
                               });
                                              
                    }		 
             
                    child.material.needsUpdate = true; 

As noted in the comment it’s a helper plugin for easier patching of materials not part of THREE core. For decals there are various ways, such as using layers like in the example or using geometry decals which technically are more independent from the original UVs of the geometry.

https://threejs.org/examples/?q=decal#webgl_decals

oh, i see. Thanks for the info. I’ll go back to decals again instead.

I’ve spent again more time working on decals. I still have the original problem, decals bend on edges which distort the projected image. Is there a way to project it so it doesn’t bend the edges. I think decal geometry might not be what I want.

Here’s an image, see the bottom splatter, it’s stretched. If I edit this code and change the decal for a logo image, it will look incorrect I think. Is it that I will need to use GLSL shader for this instead as I can’t use the patchshader.