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

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

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

顶点数据positioncolor顶点法线方向向量数据顶点纹理座标数据UV和顶点位置、颜色、法向量等数据一一对应GeometryBufferGeometry.faceVertexUvs[0].faceVertexUvs[1].attributes.uv.attributes.uv2normal顶点颜色数据顶点位置座标数据图片映射

纹理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;
  })
})
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章