threejs(四)给各星球加上贴图

311 阅读3分钟

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);

显示效果如下所示:

planete1.png

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)
});

把相机往中心点挪了挪,看看太阳的贴图效果:

sunsun.png

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
]);

将原来生成五千个点(星星)的代码删除,替换成上面的代码,效果如下所示:

back.png

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),创建凹凸效果。

贴图地址planetpixelemporium