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