本文 我们来说说uv
那么 它是什么呢?
首先 比如 我们几何体 贴一个图 那么 为什么我们图的四个边就能正好贴到几何体的边
为什么不可以图就在几何体中间呢?
中心为什么能对齐 它就不能偏一点吗?
这是第一个问题
还有我们 gltf 这种文件 其实也是很多个三角形组件的
那么 我们怎么确定它每个部位的颜色?
其实 实现 就是这样一个贴图
而每个部位的颜色 就是通过uv 来告诉它具体贴图的哪个位置去实现的
import './style.css'
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
//创建相机
const camera = new THREE.PerspectiveCamera(
45, //视角 视角越大 能看到的范围就越大
window.innerWidth / window.innerHeight,//相机的宽高比 一般和画布一样大最好
0.1, //近平面 相机能看到最近的距离
1000 //远平面 相机能看到最远的距离
);
const scene = new THREE.Scene();
const planeGeometry = new THREE .PlaneGeometry(1, 1);
console.log(planeGeometry);
//c创建一个canvas容器 并追加到 body上
const renderer = new THREE.WebGLRenderer(0);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//设置相机位置 这里 我们设置Z轴 大家可以试试 S Y 和 Z 都是可以的
camera.position.z = 5;
//设置相机默认看向哪里 三个 0 代表 默认看向原点
camera.lookAt(0, 0, 0);
//将内容渲染到元素上
renderer.render(scene, camera);
const controls = new OrbitControls(camera, renderer.domElement);
function animate() {
controls.update();
requestAnimationFrame(animate);
/*cube.rotation.x += 0.01;
cube.rotation.y += 0.01;*/
renderer.render(scene, camera);
}
animate();
然后 我们运行代码 打开控制台
这里 我们几何体对象 attributes 下是有一个uv属性的
这里 我们可以拿这个图片做
坐标理解 大体是这样的
然后 我们加上如下代码
let uvTexture = new THREE.TextureLoader().load("/textUv.jpg");
const planeGeometry = new THREE .PlaneGeometry(1, 1);
const planeMaterial = new THREE.MeshBasicMaterial({
map: uvTexture
})
const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
scene.add(planeMesh);
我们通过TextureLoader导入图片
然后 创建一个几何体
材质map贴图 选择我们需要导入的图片
然后将图片 add到场景中
然后 我们可以在下面加上这样的代码
const geometry = new THREE.BufferGeometry();
// 创建顶点数据
const vertices = new Float32Array([
-1.0 ,-1.0 ,0.0,
1.0 ,-1.0, 0.0,
1.0 ,1.0 ,0.0,
-1.0 ,1.0, 0.0
])
geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
const indices = new Uint16Array([0 ,1 ,2, 0, 3, 2]);
const material = new THREE.MeshBasicMaterial({
map: uvTexture,
side: THREE.DoubleSide
})
geometry.setIndex(new THREE.BufferAttribute(indices, 1));
const cube = new THREE.Mesh(geometry, material);
cube.position.x = - 3
console.log(cube);
scene.add(cube)
这里 我们用顶点的方式 创建了一个几何体
然后 也将它的贴图设置为 uvTexture
运行之后 你会发现 图没有上去
我们打开控制台查看
我们自己创建的顶点几何体 你在它的对象里 是找不到uv的
那么 它就不知道这个图怎么贴了
我们要告诉它 四个点分别对应贴图的什么位置
我们可以改写代码如下
const geometry = new THREE.BufferGeometry();
// 创建顶点数据
const vertices = new Float32Array([
-1.0 ,-1.0 ,0.0,
1.0 ,-1.0, 0.0,
1.0 ,1.0 ,0.0,
-1.0 ,1.0, 0.0
])
geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
const indices = new Uint16Array([0 ,1 ,2, 0, 3, 2]);
const material = new THREE.MeshBasicMaterial({
map: uvTexture,
side: THREE.DoubleSide
})
const uv = new Float32Array([
0, 0, 1, 0, 1, 1, 0, 1
])
geometry.setAttribute("uv", new THREE.BufferAttribute(uv, 2));
geometry.setIndex(new THREE.BufferAttribute(indices, 1));
const cube = new THREE.Mesh(geometry, material);
cube.position.x = - 3
console.log(cube);
scene.add(cube)
这里 我们定义了一个Float32Array对象 声明了
第一个参数代表 几何体左上角 承载图片的 x 轴 0 就是最左边 y轴 0 就是顶部
然后第二个代表 几何体 右上角 承载 x 轴 1 就是最右侧 y轴 0 就是顶部
第三个 几何体 右下角 承载图片 x轴 1 就是最右侧 y轴 1就是底部
最后一个 几何体 左下角 x 0就是最左侧 y轴 1 就是底部
setAttribute声明uv属性 BufferAttribute第二个参数告诉它 我们是 xy 2个为一组的
我们 可以将 Float32Array 改成这样
const uv = new Float32Array([
0, 0, 1, 0, 1, 1, 0, 0
])
这样 我们左下角 去取样 图片 x 0 最上面 y轴0 也是图片最上面的样式
这样 左边上下就都是这个角的红色了
相对顶点 这样 我们把uv弄好了 一些很复杂的图形 也都是可以做出来的