0. 前言
在上一篇文章中,我们通过搭建简易的星系场景介绍了使用threejs绘制点线面体,本篇介绍下如何给物体添加上贴图。在此之前,我们将上个星系场景的案例丰富一下,多绘制一些轨道和球体,将太阳也改为球体。为此,我们需要封装下生成球体和其轨道到函数中去。
function createPlanete(size,radius,rotateAngle,color){
//球体
const geometry = new THREE.SphereGeometry(size,30,30);
const material = new THREE.MeshBasicMaterial({
color
});
const mesh = new THREE.Mesh(geometry,material);
scene.add(mesh);
mesh.position.set(radius * Math.cos(rotateAngle),radius * Math.sin(rotateAngle),0)
//球体所在轨道
const geometry_track = new THREE.BufferGeometry();
const segments = 36;
const vertices = [];
for(let i = 0; i <= segments; i++) {
const theta = (i / segments) * Math.PI * 2;
vertices.push(Math.cos(theta) * radius,Math.sin(theta) * radius,0);
}
// 将顶点数据设置到几何体
geometry_track.setAttribute('position',new THREE.BufferAttribute(new Float32Array(vertices),3));
// 创建轨道材质
const material_track = new THREE.LineBasicMaterial(
{
color: 0xffffff,
transparent: true,
opacity: 0.3
});
// 创建Line对象并添加到场景
const circle = new THREE.Line(geometry_track,material_track);
scene.add(circle);
return { mesh }
}
该函数的入参有size-球体尺寸,radius-距中心点的线段的长度,rotateAngle-初始角度,color--给球体一个颜色区分(下面会将其改为对应的贴图)。
使用方法:
//水星
const mercury = createPlanete(3.2,28,0,0xff0f60)
//金星
const venus = createPlanete(5.8,44,40,0x000f60);
//地球
const earth = createPlanete(6,62,100,0x00ff60);
//火星
const mars = createPlanete(4,78,360,0x6f0f60);
由于场景扩大,原来的相机视角不够看,需要将相机离远一些,倾斜一点,看起来完整度高点。可以自行调整下角度。
camera.position.set(20,140,-140);
显示效果如下所示:
1. threejs贴图介绍
1.1 基本概念
一般使用TextureLoader来加载文件。官方文档中的代码示例如下:
const texture = new THREE.TextureLoader().load( 'textures/land_ocean_ice_cloud_2048.jpg' );
// 立即使用纹理进行材质创建
const material = new THREE.MeshBasicMaterial( { map: texture } );
加载完图片之后,将其与材质进行关联。
1.2 代码实现太阳贴图
我们用上述的方式将太阳的贴图加上,看下效果。太阳的贴图八青妹放在项目的public目录下,这里就可以直接引入。这里只贴上更改处的代码。
import sunTexture from '/sun.jpg';
// 创建太阳平面几何体
const textureLoader = new THREE.TextureLoader();
// 创建太阳发光材质
const sunMaterial = new THREE.MeshBasicMaterial({
map: textureLoader.load(sunTexture)
});
把相机往中心点挪了挪,看看太阳的贴图效果:
1.3 使用星空图片替换背景
在一般搭建场景的时候,背景一般都是用图片代替,这样比较节省性能。背景图的设置也是非常简单明了。先准备背景图片,一般需要6张,分别用于贴在环境四周(上下左右前后)。
CubeTextureLoader是 Three.js 中用于加载立方体贴图的加载器类。它可以用来加载由六张图像组成的立方体纹理贴图。
import starsTexture from '/stars.jpg';
const cubeTextureLoader = new THREE.CubeTextureLoader();
scene.background = cubeTextureLoader.load([
starsTexture,
starsTexture,
starsTexture,
starsTexture,
starsTexture,
starsTexture
]);
将原来生成五千个点(星星)的代码删除,替换成上面的代码,效果如下所示:
1.4 替换场景中所有星球
按照同样的方式,将原来星球设置颜色的部分都改为对应的贴图,看看效果。这里只展示更改处的代码,其他不变的代码就省略了哈。
import mercuryTexture from '/mercury.jpg';
import venusTexture from '/venus.jpg';
import earthTexture from '/earth.jpg';
import marsTexture from '/mars.jpg';
//水星
const mercury = createPlanete(3.2,28,0,mercuryTexture)
//金星
const venus = createPlanete(5.8,44,40,venusTexture);
//地球
const earth = createPlanete(6,62,100,earthTexture);
//火星
const mars = createPlanete(4,78,360,marsTexture);
function createPlanete(size,radius,rotateAngle,texture) {
//……省略
const material = new THREE.MeshBasicMaterial({
map: textureLoader.load(texture)
});
//……省略
}
效果:
2. 总结
常规的贴图还是比较简单的,在后面,我们将了解下光照的影响,在有光照的基础上,给材质添加上法线贴图(Normal Map),创建凹凸效果。