返回介绍

Three.js几何体顶点纹理坐标UV

发布于 2021-07-10 20:14:16 字数 4786 浏览 1491 评论 0 收藏 0

在课程的第二章对Threejs几何体Geometry和BufferGeometry的顶点概念做过比较多的介绍,讲解过顶点位置坐标数据、顶点颜色数据、顶点法线方向向量数据,不过顶点的UV数据没有去讲解,主要是几何体顶点的纹理坐标数据和纹理贴图的映射有关系,所以放在了本章节去讲解。

纹理UV坐标

纹理坐标含义就是一面意思,一张纹理贴图图像的坐标,选择一张图片,比如以图片左下角为坐标原点,右上角为坐标(1.0,1.0),图片上所有位置纵横坐标都介于0.0~1.0之间。

映射

纹理UV坐标和顶点位置坐标是一一对应关系,这也就是为什么一张图片可以映射到一个模型的表面,只要把图片的每个纹理坐标和模型的顶点位置建立一对一的关系,就可以实现图像到模型的映射。

矩形贴图和球面的映射图

两组UV坐标

几何体有两组UV坐标,第一组组用于.map.normalMap.specularMap等贴图的映射,第二组用于阴影贴图.lightMap的映射,这里不过过多阐述,本章节除了8.7用到的是第二组UV坐标,其它的章节内部程序用到的都是第一组UV坐标。

修改纹理坐标

你可以尝试修改上节课代码中几何体的纹理坐标,然后体会纹理坐标的作用。

几何体表面所有位置全部对应贴图(0.4,0.4)坐标位置的像素值,这样话网格模型不会显示完整的地图,而是显示采样点纹理坐标(0.4,0.4)对应的RGB值。

 //矩形平面,细分数默认1,即2个三角形拼接成一个矩形
var geometry = new THREE.PlaneGeometry(204, 102);
...
/**
 * 遍历uv坐标
 */
geometry.faceVertexUvs[0].forEach(elem => {
  elem.forEach(Vector2 => {
    // 所有的UV坐标全部设置为一个值
    Vector2.set(0.4,0.4);
  });
});

原来几何体平面默认是两个三角形构成,把细分数设置为4,三角形数量变为16个。

// 矩形平面 设置细分数4,4
var geometry = new THREE.PlaneGeometry(204, 102, 4, 4);
...
/**
 * 局部三角面显示完整纹理贴图
 */
var t0 = new THREE.Vector2(0, 1); //图片左下角
var t1 = new THREE.Vector2(0, 0); //图片右下角
var t2 = new THREE.Vector2(1, 0); //图片右上角
var t3 = new THREE.Vector2(1, 1); //图片左上角
var uv1 = [t0, t1, t3]; //选中图片一个三角区域像素——用于映射到一个三角面
var uv2 = [t1, t2, t3]; //选中图片一个三角区域像素——用于映射到一个三角面
// 设置第五、第六个三角形面对应的纹理坐标
geometry.faceVertexUvs[0][4] = uv1
geometry.faceVertexUvs[0][5] = uv2

Geometry自定义顶点UV坐标

一般Threejs的球体、圆柱等几何体创建的时候,都会通过特定算法自动生成几何体的UV坐标。

下面代码通过几何体Geometry自定义了一个由两个三角形组成的矩形几何体,并且通过几何体的.faceVertexUvs[0]属性设置了每个顶点对应的第一组UV坐标。

var geometry = new THREE.Geometry(); //创建一个空几何体对象
/**顶点坐标(纹理映射位置)*/
var p1 = new THREE.Vector3(0,0,0); //顶点1坐标
var p2 = new THREE.Vector3(160,0,0); //顶点2坐标
var p3 = new THREE.Vector3(160,80,0); //顶点3坐标
var p4 = new THREE.Vector3(0,80,0); //顶点4坐标
geometry.vertices.push(p1,p2,p3,p4); //顶点坐标添加到geometry对象
/** 三角面1、三角面2*/
var normal = new THREE.Vector3( 0, 0, 1 ); //三角面法向量
var face0 = new THREE.Face3( 0, 1, 2, normal); //三角面1
var face1 = new THREE.Face3( 0, 2, 3, normal); //三角面2
geometry.faces.push( face0,face1 ); //三角面1、2添加到几何体
/**纹理坐标*/
var t0 = new THREE.Vector2(0,0);//图片左下角
var t1 = new THREE.Vector2(1,0);//图片右下角
var t2 = new THREE.Vector2(1,1);//图片右上角
var t3 = new THREE.Vector2(0,1);//图片左上角
uv1 = [t0,t1,t2];//选中图片一个三角区域像素——映射到三角面1
uv2 = [t0,t2,t3];//选中图片一个三角区域像素——映射到三角面2
geometry.faceVertexUvs[0].push(uv1,uv2);//纹理坐标传递给纹理三角面属性

BufferGeometry自定义顶点UV坐标

下面代码通过几何体BufferGeometry自定义了一个由两个三角形组成的矩形几何体,并且通过几何体的.attributes.uv属性设置了每个顶点对应的第一组UV坐标。

var geometry = new THREE.BufferGeometry(); //声明一个空几何体对象
//类型数组创建顶点位置position数据
var vertices = new Float32Array([
  0, 0, 0, //顶点1坐标
  80, 0, 0, //顶点2坐标
  80, 80, 0, //顶点3坐标
  0, 80, 0, //顶点4坐标
]);
// 创建属性缓冲区对象
var attribue = new THREE.BufferAttribute(vertices, 3); //3个为一组
// 设置几何体attributes属性的位置position属性
geometry.attributes.position = attribue
var normals = new Float32Array([
  0, 0, 1, //顶点1法向量
  0, 0, 1, //顶点2法向量
  0, 0, 1, //顶点3法向量
  0, 0, 1, //顶点4法向量
]);
// 设置几何体attributes属性的位置normal属性
geometry.attributes.normal = new THREE.BufferAttribute(normals, 3); //3个为一组,表示一个顶点的xyz坐标
// Uint16Array类型数组创建顶点索引数据
var indexes = new Uint16Array([
  0, 1, 2, 0, 2, 3,
])
// 索引数据赋值给几何体的index属性
geometry.index = new THREE.BufferAttribute(indexes, 1); //1个为一组
 /**纹理坐标*/
 var uvs = new Float32Array([
   0,0, //图片左下角
   1,0, //图片右下角
   1,1, //图片右上角
   0,1, //图片左上角
 ]);
 // 设置几何体attributes属性的位置normal属性
 geometry.attributes.uv = new THREE.BufferAttribute(uvs, 2); //2个为一组,表示一个顶点的纹理坐标

加载一个包含UV坐标的模型文件

下面案例代码是通过Threejs加载一个包含UV坐标的外部三维模型文件,加载成功后,给模型设置一张贴图.

// 创建一个加载threejs格式JSON文件的加载器
var loader = new THREE.ObjectLoader();
// TextureLoader创建一个纹理加载器对象,可以加载图片作为几何体纹理
var textureLoader = new THREE.TextureLoader();
loader.load('model.json',function (obj) {
  console.log(obj);
  scene.add(obj);//加载返回的对象插入场景中
  // 执行load方法,加载纹理贴图成功后,返回一个纹理对象Texture
  textureLoader.load('Earth.png', function(texture) {
    // 设置球体网格模型材质的map属性
    obj.children[0].material.map = texture;
    // 告诉threejs渲染器系统,材质对象的map属性已更新
    obj.children[0].material.needsUpdate=true;
  })
})

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文