18.环境贴图
在我们以前玩过的一些游戏或是看过的游戏,如果你是以第一人称视角在游玩的话,那么你会发现你是可以往前后左右上下六个方向看的。所以呢我们首先需要准备6张图,(我也没有QAQ)
但前面所说到的我们能从前后左右上下六个方向看到的是属于我们场景中的景象。我们这一小节要讲的是,我们中心的物体去反射看到周围的一切,在停车场我们通常会看到有一个凸面镜来扩大我们的视野,那么类似的我们在中心放上一个物体球,让它去照出四面八方的景象。也就是给一个球上帖帖图。
加载图片呢跟之前一样,我们用到的对象是CubeTextureLoader,一次来添加一组(6张)图片。而且还是需要顺序的。
px代表x轴正方向,nx代表x轴负方向。顺序分别是x,y,z轴的正负方向,如下图:
//设置cube纹理加载器
const cubeTextureLoader = new THREE.CubeTextureLoader()
const envMapTexture = cubeTextureLoader.load([//加载六张图
'texture/environmentMaps/px.jpg',//x正方向
'texture/environmentMaps/nx.jpg',//x负方向
'texture/environmentMaps/py.jpg',
'texture/environmentMaps/ny.jpg',
'texture/environmentMaps/pz.jpg',
'texture/environmentMaps/nz.jpg',
])
ok,那么我们把纹理加载进来后,下一步要创建物体(球)
//导入物体
const sphereGeometry = new THREE.SphereGeometry(1, 20, 20)//设置几何体:球
const material = new THREE.MeshStandardMaterial({ //设置纹理
metalness: 0.7, //金属度,如果1的话会太黑
roughness: 0.1, //光滑度
envMap: envMapTexture, //环境贴图
})
const sphere = new THREE.Mesh(sphereGeometry, material)
scene.add(sphere)
19.经纬线映射贴图与HDR
这节我们用到的是Scene(场景)里的属性。
background: 若不为空,在渲染场景的时候将设置背景,且背景总是首先被渲染的。默认值为null。
environment: 若该值不为null,则该纹理贴图将会被设为场景中所有物理材质的环境贴图。然而,该属性不能覆盖已存在的、已分配给MeshStandardMaterial.envMap的贴图。默认值为null。
在上一节中,我们加载了一组(6张)图片,分别是我们环境的前后左右上下六个方向的图片。如下:
//设置cube纹理加载器
const cubeTextureLoader = new THREE.CubeTextureLoader()
const envMapTexture = cubeTextureLoader.load([ //加载六张图
'texture/environmentMaps/px.jpg', //x正方向
'texture/environmentMaps/nx.jpg', //x负方向
'texture/environmentMaps/py.jpg',
'texture/environmentMaps/ny.jpg',
'texture/environmentMaps/pz.jpg',
'texture/environmentMaps/nz.jpg',
])
那么这六张图片,我们把它们放到scene的background中,就可以给场景添加背景了
//给场景添加背景
scene.background = envMapTexture
在上一节中,给小球加了环境贴图,让小球看起来像反射出环境的样子。如下:
const material = new THREE.MeshStandardMaterial({
metalness: 0.7, //金属度,如果1的话会太黑
roughness: 0.1, //光滑度
envMap: envMapTexture, //环境贴图
})
在上面介绍的environment,可以为场景中所有物体添加环境贴图。首先我们把上面的envMap可以去掉,然后加上environment,如下:
const material = new THREE.MeshStandardMaterial({
metalness: 0.7, //金属度,如果1的话会太黑
roughness: 0.1, //光滑度
//envMap: envMapTexture, //环境贴图
})
//给场景所有的物体添加默认的环境贴图
scene.environment = envMapTexture
环境贴图呢可以在网上去下载,而且不止是有6张图的,还有==一张图包含了6个面==的 .hdr 图片。简单的说嘞就是HDR的
图片会有更多的光线细节,同样呢大小就会更大。
那么加载HDR图片,three.js也有专门的加载器:
DataTextureLoader: 用于加载二进制文件格式的(rgbe,hdr,......)抽象类。内部使用FileLoader来加载文件,和创建一个新的DataTexture。
我们用到它的子类:RGBELoader
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader'
//加载hdr环境图
const rgbeLoader = new RGBELoader()
rgbeLoader.loadAsync("/textures/bk.hdr").then((texture) => { //这是个异步的
scene.background = texture
})
这样子展示出来的呢,是不完全正确的,因为它无法知道这是一张什么图。所以我们需要去修改它的纹理。hdr是一张图,想要变成立方体属实是不太可能,但是呢可以是一个圆柱体。下面介绍的纹理常量就可以做到。
如果是立方体的纹理贴图,就使用CubeReflectionMapping 这也是默认值,如果是圆柱体的纹理贴图,就使用EquirectangularReflectionMapping。
//加载hdr环境图
const rgbeLoader = new RGBELoader()
rgbeLoader.loadAsync("/textures/bk.hdr").then((texture) => { //这是个异步的
texture.mapping = THREE.EquirectangularReflectionMapping
scene.background = texture
scene.environment = texture
})
这样就实现了!