「这是我参与2022首次更文挑战的第18天,活动详情查看:2022首次更文挑战」
天空盒
- 在3D场景中,为了增强场景表现力,我们通常会为场景添加天空盒。就是在整个场景的上方绘制天空这一类图片。
- 最简单的做法是,制作一个很大的立方体为6个面添加纹理,这里要注意我们渲染的是内部。纹理是特殊处理了的能组合成一个整体。当然还有其他的方式比如创建球体或半圆的穹顶等。
创建
- 基础代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>学习</title>
</head>
<body>
<canvas id="c2d" class="c2d" width="1000" height="500"></canvas>
<script type="module">
import * as THREE from './file/three.js-dev/build/three.module.js'
import { OrbitControls } from './file/three.js-dev/examples/jsm/controls/OrbitControls.js'
const canvas = document.querySelector('#c2d')
// 渲染器
const renderer = new THREE.WebGLRenderer({ canvas })
const fov = 40 // 视野范围
const aspect = 2 // 相机默认值 画布的宽高比
const near = 0.1 // 近平面
const far = 10000 // 远平面
// 透视投影相机
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far)
camera.position.set(10, 3, 0)
camera.lookAt(0, 0, 0)
// 控制相机
const controls = new OrbitControls(camera, canvas)
controls.update()
// 场景
const scene = new THREE.Scene()
// 渲染
function render() {
renderer.render(scene, camera)
requestAnimationFrame(render)
}
requestAnimationFrame(render)
</script>
</body>
</html>
- 添加几何体,给每个面设置纹理。
- 需要注意材质要设置
THREE.BackSide
渲染内部,相机的远平面必须大于盒子的长度。directions[]
数组中的图片也是有序的。
{
var directions = [
'./file/18/pos-x.jpg',
'./file/18/neg-x.jpg',
'./file/18/pos-y.jpg',
'./file/18/neg-y.jpg',
'./file/18/pos-z.jpg',
'./file/18/neg-z.jpg'
] // 获取对象
const loader = new THREE.TextureLoader()
// 创建盒子,并设置盒子的大小为( 5000, 5000, 5000 )
const skyGeometry = new THREE.BoxGeometry(5000, 5000, 5000)
// 设置盒子材质
const materialArray = []
for (let i = 0; i < 6; i++)
materialArray.push(
new THREE.MeshBasicMaterial({
map: loader.load(directions[i]), // 将图片纹理贴上
side: THREE.BackSide // 镜像翻转
})
)
// 创建一个完整的天空盒,填入几何模型和材质的参数
const skyBox = new THREE.Mesh(skyGeometry, materialArray)
scene.add(skyBox) // 在场景中加入天空盒
}
three.js
提供了一种特殊的纹理CubeTextureLoader
,可以模拟正方形的6个边。只需要很少的代码就能实现上面的效果。
{
const loader = new THREE.CubeTextureLoader()
const texture = loader.load([
'./file/18/pos-x.jpg',
'./file/18//neg-x.jpg',
'./file/18//pos-y.jpg',
'./file/18//neg-y.jpg',
'./file/18//pos-z.jpg',
'./file/18//neg-z.jpg'
])
scene.background = texture
}
three.js
中除几张图组合的方式,还可以使用360度的全景图来设置天空。- 使用
WebGLCubeRenderTarget
渲染器的.fromEquirectangularTexture
,把全景图转换为立方体贴图格式。
{
const loader = new THREE.TextureLoader()
const texture = loader.load('./file/18/2.webp', () => {
const rt = new THREE.WebGLCubeRenderTarget(texture.image.height)
rt.fromEquirectangularTexture(renderer, texture)
scene.background = rt.texture
})
}
- 天空盒子在3D场景中,是最常见的一种增强效果的方式。使用那种方式去实现,就需要根据需求来判断什么方式最简单了。