【three.js系列六】入门教程——自定义UV坐标(贴图)

简介

在 Three.js 中,UV 坐标用于将纹理映射到模型表面。默认情况下,Three.js 会自动生成 UV 坐标,但有时我们需要根据自己的需求自定义 UV 坐标。

uv:纹理坐标系统

因为xyz已经被顶点坐标占用了,所以uvw就用来表示纹理坐标。它时候贴图影射到模型表面的依据,把表面的点与平面上的像素对应起来,一般取值在0~1;

u:图片在显示器水平的坐标

v:垂直方向

w:垂直于显示器表面

一般情况只是在表面贴图,就涉及不到w,所以常称为uv。

自定义 UV 坐标的用途

  • 控制纹理在模型表面的映射方式
  • 实现特殊效果,例如动画纹理、扭曲纹理等
  • 优化纹理资源的使用

顶点UV坐标的作用与获取

从纹理贴图上提取像素映射到网格模型Mesh的几何体表面上。

js 复制代码
const geometry = new THREE.PlaneGeometry(200, 100); //矩形平面
// const geometry = new THREE.BoxGeometry(100, 100, 100); //长方体
// const geometry = new THREE.SphereGeometry(100, 30, 30);//球体
console.log('uv',geometry.attributes.uv);   // 获取几何体默认的UV坐标数据

纹理贴图UV坐标范围

顶点UV坐标可以在0~1.0之间任意取值,纹理贴图左下角 对应的UV坐标是(0,0),右上角 对应的坐标(1,1)。

自定义顶点UVgeometry.attributes.uv

顶点UV坐标geometry.attributes.uv和顶点位置坐标geometry.attributes.position是一一对应的,

UV顶点坐标你可以根据需要在0~1之间任意设置,具体怎么设置,要看你想把图片的哪部分映射到Mesh的几何体表面上。

js 复制代码
/**纹理坐标0~1之间随意定义*/
const uvs = new Float32Array([
    0, 0, //图片左下角
    1, 0, //图片右下角
    1, 1, //图片右上角
    0, 1, //图片左上角
]);
// 设置几何体attributes属性的位置normal属性
geometry.attributes.uv = new THREE.BufferAttribute(uvs, 2); //2个为一组,表示一个顶点的纹理坐标

获取纹理贴图四分之一

获取纹理贴图左下角四分之一部分的像素值

js 复制代码
const uvs = new Float32Array([
    0, 0, 
    0.5, 0, 
    0.5, 0.5, 
    0, 0.5, 
]);

完整代码

js 复制代码
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";

// 创建场景
// 场景能够让你在什么地方、摆放什么东西来交给three.js来渲染,这是你放置物体、灯光和摄像机的地方。
const scene = new THREE.Scene();
// 添加背景颜色
scene.background = new THREE.Color(0x666666);

// 创建相机
const camera = new THREE.PerspectiveCamera();
camera.position.y = 0;
camera.position.z = 2;

// 创建矩形
const geometry = new THREE.PlaneGeometry(1, 1)

// 创建一个纹理对象
const texture = new THREE.TextureLoader().load('/aaa.jpg')

// 定义UV像素的取值范围 左上 右上 左下 右下
const uv = new Float32Array([
  0.5, 1,
  1, 1,
  0.5, 0.5,
  1, 0.5
])

// 设置uv坐标
geometry.attributes.uv = new THREE.BufferAttribute(uv, 2)

// 创建基础网格材质
const material = new THREE.MeshBasicMaterial({
  map: texture
})

console.log(geometry, 'geometry')

// 创建网格
const cube = new THREE.Mesh(geometry, material)
scene.add(cube)

// 添加坐标辅助线
const axesHelper = new THREE.AxesHelper( 5 );
scene.add( axesHelper );

  // 创建渲染器
  const renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  // 将渲染器添加到页面
  document.body.appendChild(renderer.domElement);

  // 添加轨道控制器
  const controls = new OrbitControls(camera, renderer.domElement);

  // 让立方体动起来
  function animate() {
    // 告诉浏览器------你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。
    requestAnimationFrame(animate);

    // 轨道控制器更新
    controls.update();
    renderer.render(scene, camera);
  }
  animate();

效果图

参考资料

Three.js中文网

b站

相关推荐
星栈7 小时前
pnpm 12 升级实测
前端·javascript
Ai-_Man8 小时前
您您这可以把Microsofat Copilot的多个会话比如说。左侧的多个会话一次性导出吗?不是单条会话里面的多次会对话。AI导出鸭
javascript·人工智能·ai·小程序·电脑·copilot
Bruce_Liuxiaowei11 小时前
网页版 DeepSeek “harness desktop“ WebGL 上下文创建失败排查实录
开发语言·javascript·webgl
小凯在掘金12 小时前
为什么箭头函数不能作为构造函数?
前端·javascript
可乐鸡翅yeah_12 小时前
网页端 M3U8 播放器性能监控,怎么看播放卡顿指标
javascript·ffmpeg·音视频·safari·m3u8
可乐鸡翅yeah_13 小时前
M3U8 防盗链 URL‑Token 签名,新手开发实操避坑
开发语言·javascript·ios·音视频·safari
2603_9658966213 小时前
JS原型与原型链|对象继承与实例底层原理
开发语言·javascript·原型模式
JustHappy13 小时前
「vConsole MCP🛠️」我让 AI 直接看见任何 H5 的日志和请求帮你 debug
前端·javascript·程序员
xieter14 小时前
【技术精选】Node.js 核心事件循环机制与异步 I/O 深度剖析 (2026-10-02)
前端·javascript
想吃火锅100515 小时前
【leetcode】238.除了自身以外数组的乘积js
javascript·算法·leetcode