提示:本系列文章参考http://www.webgl3d.cn/Three.js/的three.js教程。
文章目录
前言
本篇主要介绍纹理贴图的部分知识,如目录所示。
一、简单的纹理贴图
1.将几何体模型整个表面进行纹理贴图
声明几何体后使用 THREE.TextureLoader() 方法创建一个纹理加载器对象加载图片作为几何体纹理。
var textureLoader = new THREE.TextureLoader();
在 纹理加载器对象.loadload(‘图片路径’, function(texture) {} 方法里,设置材质对象里 map: texture 设置纹理贴图。
textureLoader.load('图片路径', function(texture) {
var material = new THREE.MeshLambertMaterial({
// color: 0x0000ff,
// 设置颜色纹理贴图:Texture对象作为材质map属性的属性值
map: texture,//设置颜色贴图属性值
}); //材质对象Material
因为贴图已经在材质里了,通过 THREE.Mesh(几何体对象, 材质对象) 方法完成纹理贴图设置。
var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
完整的设置一个球体纹理贴图过程如下:
/**
* 创建场景对象Scene
*/
var scene = new THREE.Scene();
// 纹理贴图映射到一个球体上
var geometry3 = new THREE.SphereGeometry(60, 25, 25); //球体
// TextureLoader创建一个纹理加载器对象,可以加载图片作为几何体纹理
var textureLoader = new THREE.TextureLoader();
// 执行load方法,加载纹理贴图成功后,返回一个纹理对象Texture
textureLoader.load('cwt.jpg', function(texture) {
var material = new THREE.MeshLambertMaterial({
// color: 0x0000ff,
// 设置颜色纹理贴图:Texture对象作为材质map属性的属性值
map: texture,//设置颜色贴图属性值
}); //材质对象Material
var mesh3 = new THREE.Mesh(geometry3, material); //网格模型对象Mesh
scene.add(mesh3); //网格模型添加到场景中
//纹理贴图加载成功后,调用渲染函数执行渲染操作
// render();
})
效果如下:
2.利用数组将几何体模型某些面进行不同的纹理贴图
纹理贴图最后通过材质反映,所以对于纹理贴图不同的面,分别设置不同的材质对象,放在材质数组中,最后设置数组材质对象作为网格模型材质参数。
下面是将立方体的一个面进行纹理贴图
var geometry = new THREE.BoxGeometry(100, 100, 100); //立方体
// var geometry = new THREE.PlaneGeometry(204, 102, 4, 4); //矩形平面
// var geometry = new THREE.SphereGeometry(60, 25, 25); //球体
// var geometry = new THREE.CylinderGeometry(60, 60, 25,25); //圆柱
//
// 材质对象1
var material_1 = new THREE.MeshPhongMaterial({
color: 0xffff3f
})
var textureLoader = new THREE.TextureLoader(); // 纹理加载器
var texture = textureLoader.load('cwt.jpg'); // 加载图片,返回Texture对象
// 材质对象2
var material_2 = new THREE.MeshLambertMaterial({
map: texture, // 设置纹理贴图
// wireframe:true,
});
// 设置材质数组
var materialArr = [material_2, material_1, material_1, material_1, material_1, material_1];
// 设置数组材质对象作为网格模型材质参数
var mesh = new THREE.Mesh(geometry, materialArr); //网格模型对象Mesh
scene.add(mesh); //网格模型添加到场景中
效果如下:
二、利用face3的.materialIndex 将几何体的某些三角面改变材质(颜色、贴图等)
前面说过几何体由一个个三角形面构成,而创建一个4*4的矩形平面由32个三角面构成(16个矩形)
var geometry = new THREE.PlaneGeometry(204, 102, 4, 4); //矩形平面
我们先设置若干个材质对象,放在数组中
// 材质对象1
var material1 = new THREE.MeshPhongMaterial({
color: 0xffff3f,
// wireframe:true,
})
// 材质对象2
var material2 = new THREE.MeshPhongMaterial({
color: 0x0000ff,
// wireframe:true,
}); //材质对象Material
// 数组材质
var materialArr = [material1,material2]
几何体变量名.faces[i]代表第i个三角形,令几何体变量名.faces[i].materialIndex = 某个材质对象的索引值(默认从0开始按顺序)
// 设置几何体的材质索引(对于PlaneGeometry而言所有Face3的材质索引默认0)
geometry.faces[4].materialIndex = 1;
如令4*4矩形平面的第5、6个三角形变成材质对象2的颜色(即第3个矩形)
/**
* 创建场景对象Scene
*/
var scene = new THREE.Scene();
var geometry = new THREE.PlaneGeometry(204, 102, 4, 4); //矩形平面
// 材质对象1
var material1 = new THREE.MeshPhongMaterial({
color: 0xffff3f,
// wireframe:true,
})
// 材质对象2
var material2 = new THREE.MeshPhongMaterial({
color: 0x0000ff,
// wireframe:true,
}); //材质对象Material
// 数组材质
var materialArr = [material1,material2];
// 设置几何体的材质索引(对于PlaneGeometry而言所有Face3的材质索引默认0)
geometry.faces[4].materialIndex = 1;
geometry.faces[5].materialIndex = 1;
var mesh = new THREE.Mesh(geometry, materialArr); //网格模型对象Mesh
scene.add(mesh); //网格模型添加到场景中
效果如下:
三、纹理贴图的阵列、偏移、旋转
1.将草的纹理贴图利用阵列进行uv两个方向重复,形成草地
创建矩形平面后加载草的纹理贴图,设置阵列,用 texture.repeat.set(5, 5); 设置沿uv两个方向纹理重复数为5,再设置材质和网格模型对象。
效果如下:
/**
* 创建场景对象Scene
*/
var scene = new THREE.Scene();
/**
* 创建一个地面
*/
var geometry = new THREE.PlaneGeometry(200, 200); //矩形平面
// 加载草纹理贴图
var texture = new THREE.TextureLoader().load("grass.jpg");
// 设置阵列
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
// uv两个方向纹理重复数量
texture.repeat.set(5, 5);
var material = new THREE.MeshLambertMaterial({
map: texture,
});
var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
scene.add(mesh); //网格模型添加到场景中
2.偏移
将纹理贴图uv方向都偏移0.5个(-1—1之间,因为偏移1个等于没有偏移)
// 在加载纹理贴图后设置偏移效果
texture.offset = new THREE.Vector2(0.5, 0.5)
上面的草地uv方向都偏移0.5个效果如下:
3.旋转
将纹理贴图旋转PI/4
// 设置纹理旋转角度
texture.rotation = Math.PI/4;
设置纹理的旋转中心为(0.5,0.5)
// 设置纹理的旋转中心,默认(0,0)
texture.center.set(0.5,0.5);
将整个模型X轴旋转-PI / 2(-90°)
mesh.rotateX(-Math.PI / 2);
上面的草地整个矩形平面X轴旋转-PI / 2(-90°),效果如下:
4.在管道里利用阵列重复和不断偏移形成动画效果
思路是:颜色半黑半白的贴图利用阵列进行重复贴满管道,在函数里贴图不断偏移形成动画效果。
效果如下:
先使用 THREE.CatmullRomCurve3([new THREE.Vector3(x,y,z),new THREE.Vector3(x,y,z)…])方法,确定顶点设置管道基类(管道路径形状),再使用 THREE.TubeGeometry(继承路径的管道基类,管道分段数,半径,横截面分段数,两端是闭合) 方法创建管道,利用阵列对纹理贴图进行重复。
/**
* 创建一个设置重复纹理的管道
*/
var curve = new THREE.CatmullRomCurve3([
new THREE.Vector3(-80, -40, 0),
new THREE.Vector3(-70, 40, 0),
new THREE.Vector3(70, 40, 0),
new THREE.Vector3(80, -40, 0)
]);
var tubeGeometry = new THREE.TubeGeometry(curve, 100, 2, 50, false);//THREE.TubeGeometry(继承路径的管道基类,管道分段数,半径,横截面分段数,两端是闭合)
var textureLoader = new THREE.TextureLoader();
var texture = textureLoader.load('WhiteBlack.png');
// 设置阵列模式为 RepeatWrapping
texture.wrapS = THREE.RepeatWrapping
texture.wrapT=THREE.RepeatWrapping
// 设置x方向的偏移(沿着管道路径方向),y方向默认1
//等价texture.repeat= new THREE.Vector2(20,1)
texture.repeat.x = 20;
var tubeMaterial = new THREE.MeshPhongMaterial({
map: texture,
transparent: true,
});
var tubeMesh = new THREE.Mesh(tubeGeometry, tubeMaterial); //网格模型对象tubeMesh
scene.add(tubeMesh); //网格模型添加到场景中
最后在函数里使用 texture.offset.x -= 0.06 一直沿X方向偏移,形成动画效果。
/**
* 创建渲染器对象
*/
var renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);//设置渲染区域尺寸
renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
document.body.appendChild(renderer.domElement); //body元素中插入canvas对象
function render() {
renderer.render(scene,camera);//执行渲染操作
// mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度
requestAnimationFrame(render);//请求再次执行渲染函数render
// 使用加减法可以设置不同的运动方向
// 设置纹理偏移
texture.offset.x -= 0.06
}
render();