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

阿尔贝托·达拉波尔塔

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

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

  • 因为我是通过CanvasTexture内联 svg 给T 恤着色的,所以我认为在特定坐标处将徽标绘制到 svg 中会很容易。这确实很容易,但徽标不会在纹理/网格上呈现(或以某种方式不可见),尽管它在内嵌 svg 中可见。所以CanvasTexture可能不适用于嵌入的图像(我尝试了 base64 和 URL)

  • 所以,我开始研究更多的 3d “原生”方式来做这件事,但我还没有找到一种对我来说真正有意义的方式。我知道ShaderMaterial在 Threejs 中有,我可以用它来有选择地渲染徽标的像素或布料的像素,但这意味着要进行大量复杂的计算才能确定徽标的位置,而且我无法相信绘制简单的 JPEG或具有特定坐标和大小的 PNG 可能如此复杂......我一定错过了一个明显的解决方案。

编辑

这是我如何将图像添加到内联 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 画布
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. 将 2d 画布绘制到 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...]
狮身人面像

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

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

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/

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章