You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Three.js中纹理特定三角区域跨纹理映射实现咨询及代码需求

在Three.js中实现纹理三角形区域到异形变体三角形的映射

完全可以实现,核心是用自定义着色器(ShaderMaterial)手动处理纹理坐标的变换——Three.js默认的UV映射是基于四边形的,要做三角形到三角形的映射,得靠仿射变换(如果是透视关系就用透视变换)来计算对应坐标。

核心思路

给定源纹理里的一个三角形(三个顶点的UV坐标:uvA, uvB, uvC),以及目标几何体上的变形三角形(三个顶点位置:posA, posB, posC),我们可以在着色器里这么做:

  1. 给每个顶点分配重心坐标权重,顶点着色器里把这个值传给片元着色器
  2. 片元着色器里用重心坐标插值出对应的源纹理UV,完成映射

示例代码

下面是一个最小可运行的示例,用一个三角形几何体作为目标载体,把源纹理里的某块三角形区域映射到变形后的三角形上:

import * as THREE from 'three';

// 初始化基础场景
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// 加载你的源纹理(替换成自己的图片路径)
const textureLoader = new THREE.TextureLoader();
const sourceTexture = textureLoader.load('your-source-texture.jpg');
sourceTexture.wrapS = THREE.ClampToEdgeWrapping;
sourceTexture.wrapT = THREE.ClampToEdgeWrapping;

// 定义源纹理里的三角形UV(这里取纹理左上角、右上角、左下角区域,可自行调整)
const sourceUVs = {
  A: new THREE.Vector2(0, 1),
  B: new THREE.Vector2(1, 1),
  C: new THREE.Vector2(0, 0),
};

// 定义目标变形三角形的顶点位置
const targetVertices = [
  -1, 1, 0,   // 顶点A
  2, 0.5, 0,  // 顶点B
  -0.5, -1, 0 // 顶点C
];

// 创建三角形几何体
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.Float32BufferAttribute(targetVertices, 3));
// 给每个顶点设置重心坐标权重(分别对应三个顶点的权重)
geometry.setAttribute('barycentric', new THREE.Float32BufferAttribute([
  1, 0, 0,
  0, 1, 0,
  0, 0, 1
], 3));

// 自定义着色器代码
const vertexShader = `
  attribute vec3 barycentric;
  varying vec3 vBarycentric;

  void main() {
    vBarycentric = barycentric;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
  }
`;

const fragmentShader = `
  uniform sampler2D sourceTexture;
  uniform vec2 uvA;
  uniform vec2 uvB;
  uniform vec2 uvC;
  varying vec3 vBarycentric;

  void main() {
    // 用重心坐标插值计算当前像素对应的源纹理UV
    vec2 sourceUV = vBarycentric.x * uvA + vBarycentric.y * uvB + vBarycentric.z * uvC;
    // 采样源纹理
    gl_FragColor = texture2D(sourceTexture, sourceUV);
  }
`;

// 创建着色器材质
const material = new THREE.ShaderMaterial({
  uniforms: {
    sourceTexture: { value: sourceTexture },
    uvA: { value: sourceUVs.A },
    uvB: { value: sourceUVs.B },
    uvC: { value: sourceUVs.C },
  },
  vertexShader,
  fragmentShader,
  side: THREE.DoubleSide, // 开启双面渲染,避免看不到背面
});

// 创建网格并加入场景
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

camera.position.z = 3;

// 渲染循环
function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}
animate();

// 窗口大小适配
window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
});

几点说明

  • 重心坐标:每个顶点的barycentric属性是该顶点在三角形中的权重,片元着色器通过插值得到当前像素在目标三角形中的位置,再用这个位置去匹配源纹理的三角形区域。
  • 如果你需要处理透视关系(比如源和目标三角形不在同一平面),可以把仿射变换换成透视变换矩阵,计算逻辑会复杂一些,但核心思路还是用重心坐标或矩阵变换来映射UV。
  • 替换your-source-texture.jpg为你的实际纹理路径,调整sourceUVs和targetVertices的值就能改变源三角形区域和目标三角形的形状位置。

内容的提问来源于stack exchange,提问作者fresh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 02:43:35