Threejs - 仅在网格的一部分中渲染图像纹理的最佳方式

Threejs - Best way to render image texture only in a portion of the mesh

我有一件 T 恤的 .obj,它包含一些网格和材料,我正在使用由内联 svg 提供的 CanvasTexture 为其着色。

现在我应该在特定位置(或多或少在心脏上方)添加徽标,但我很难理解哪种 best/proper 方法(我对3D 图形和 Three.js)。这是我到目前为止尝试过的:

编辑

这是我将图像添加到内联 svg 的方式(上面的选项 1)。

  1. 将图像添加到内联 svg
const groups = Array.from(svg.querySelectorAll('g'));
// this is the "g" tag where I want to add the logo into
const targetGroup = groups.find((group: SVGGElement) => group.getAttribute('id') === "logo_placeholder");

const image = document.createElement('image');
image.setAttribute('width', '64');
image.setAttribute('height', '64');
image.setAttribute('x', '240');
image.setAttribute('y', '512');
image.setAttribute('xlink:href', `data:image/png;base64,${base64}`);

targetGroup.appendChild(image);
  1. 将内联 svg 绘制为 2d canvas
static drawSvgToCanvas = async (canvas: HTMLCanvasElement, canvasSize: TSize, svgString: string) => {
  return new Promise((resolve, reject) => 
    canvas.width = canvasSize.width;
    canvas.height = canvasSize.height;

    const ctx = canvas.getContext('2d');

    const image = new Image(); // eslint-disable-line no-undef
    image.src = `data:image/svg+xml;base64,${btoa(svgString)}`;
    image.onload = () => {
      if (ctx) {
        ctx.drawImage(image, 0, 0);
          resolve();
        } else {
          reject(new Error('2D context is not set on canvas'));
        }
      };

    image.onerror = () => {
      reject(new Error('Could not load svg image'));
    }
 });
};
  1. 绘制二维canvas到threejs纹理
const texture = new Three.CanvasTexture(canvas);
texture.mapping = Three.UVMapping; // it's the default
texture.wrapS = Three.RepeatWrapping;
texture.wrapT = Three.RepeatWrapping; // it's the default
texture.magFilter = Three.LinearFilter; // it's the default
texture.minFilter = Three.LinearFilter;
texture.needsUpdate = true;

[...add texture to material...]

出于某种原因,canvases 不喜欢带有嵌入图像的 SVG,因此对于一个类似的项目,我必须分两步进行,分别渲染 SVG 和图像:

首先,在 canvas 上渲染 SVG,然后在其上渲染图像(在同一个 canvas 上)。

const ctx = canvas.getContext('2d');
ctx.drawImage(imgSVG, 0, 0);
ctx.drawImage(img2, 130, 10, 65, 90);

const texture = new THREE.CanvasTexture(canvas);

示例:https://jsfiddle.net/0f9hm7gx/