前期回顾:
本期主要介绍环境
1 简介
通过前面的学习, 我们了解到场景就是对一个3D世界的模拟
在threejs
中, Scene
是一个对象. 主要属性
- background: 背景(颜色, 纹理)
- environment: 环境
- fog: 雾化
2 背景颜色
通过scene
的background
属性, 可以设置一个纯色作为背景
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
// 导入封装的MeshGui
import { MeshGui } from '../gui'
// 一. 创建场景
const scene = new THREE.Scene()
scene.background = new THREE.Color(0x0000ff)
// 二. 创建相机
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight
)
camera.position.set(0, 0, 5)
// 三. 创建物体
const sphereGeometry = new THREE.SphereGeometry(1, 32, 32)
const sphereMaterial = new THREE.MeshNormalMaterial()
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial)
scene.add(sphere)
new MeshGui({
target: sphere,
})
// 四. 创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setAnimationLoop(animation)
// 将渲染的canvas添加到body元素中
document.body.appendChild(renderer.domElement)
// 五. 辅助工具
const control = new OrbitControls(camera, renderer.domElement)
const axesHelper = new THREE.AxesHelper(10)
scene.add(axesHelper)
const gridHelper = new THREE.GridHelper(20, 20, 0xffffff, 0xffffff)
gridHelper.material.transparent = true
gridHelper.material.opacity = 0.5
scene.add(gridHelper)
function animation() {
renderer.render(scene, camera)
}
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
})
3 背景图片
1) 单一图片
background
属性也可以接收一个texture
纹理对象作为参数
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
// 导入封装的MeshGui
import { MeshGui } from '../gui'
// 一. 创建场景
const scene = new THREE.Scene()
// 创建一个纹理加载器, 加载纹理图片
const texture = new THREE.TextureLoader().load('/src/assets/texture/bg.jpeg')
scene.background = texture
// 二. 创建相机
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight
)
camera.position.set(0, 0, 5)
// 三. 创建物体
const sphereGeometry = new THREE.SphereGeometry(1, 32, 32)
const sphereMaterial = new THREE.MeshNormalMaterial()
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial)
scene.add(sphere)
new MeshGui({
target: sphere,
})
// 四. 创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setAnimationLoop(animation)
// 将渲染的canvas添加到body元素中
document.body.appendChild(renderer.domElement)
// 五. 辅助工具
const control = new OrbitControls(camera, renderer.domElement)
const axesHelper = new THREE.AxesHelper(10)
scene.add(axesHelper)
const gridHelper = new THREE.GridHelper(20, 20, 0xffffff, 0xffffff)
gridHelper.material.transparent = true
gridHelper.material.opacity = 0.5
scene.add(gridHelper)
function animation() {
renderer.render(scene, camera)
}
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
})
提示: 如果图片不显示
- 检查路径是否正解
- 是否开启了动画循环
2) 全景图
为了模拟更加逼真的3D场景, 我们可以使用全景图, 就是由6张图拼接
- px: x轴正方向
- nx: x轴负方向
- py: y轴正方向
- ny: y轴负方向
- pz: z轴正方向
- nz: z轴负方向
基础原理
在上面我们模拟过全景图, 就是设置一个足够大的立方体, 给每个面都贴上图, 这里我们给场景设置
示例:
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
// 一. 创建场景
const scene = new THREE.Scene()
// 创建一个纹理加载器, 加载纹理图片
const texture = new THREE.CubeTextureLoader()
.setPath('/src/assets/texture/park/')
.load([
'posx.jpg',
'negx.jpg',
'posy.jpg',
'negy.jpg',
'posz.jpg',
'negz.jpg',
])
scene.background = texture
// 二. 创建相机
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight
)
camera.position.set(0, 0, 5)
// 四. 创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setAnimationLoop(animation)
// 将渲染的canvas添加到body元素中
document.body.appendChild(renderer.domElement)
// 五. 辅助工具
const control = new OrbitControls(camera, renderer.domElement)
function animation() {
renderer.render(scene, camera)
}
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
})
3) HDR图
什么是HDR图
HDR 是高动态范围 (High Dynamic Range) 的缩写。它是一种通过在数字图像中捕捉比传统图像技术更广泛的亮度范围来提高图像质量的技术。HDR 图像可以展现更多的颜色和阴影细节,使图像看起来更接近真实世界的视觉效果。
一句话解释
HDR图有更好的显示效果, 高清无码
示例
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js'
// 一. 创建场景
const scene = new THREE.Scene()
// 创建一个纹理加载器, 加载纹理图片
const texture = new RGBELoader().load('/src/assets/hdr/city.hdr', () => {
texture.mapping = THREE.EquirectangularReflectionMapping
scene.background = texture
})
// 二. 创建相机
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight
)
camera.position.set(0, 0, 5)
// 四. 创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setAnimationLoop(animation)
// 将渲染的canvas添加到body元素中
document.body.appendChild(renderer.domElement)
// 五. 辅助工具
const control = new OrbitControls(camera, renderer.domElement)
function animation() {
renderer.render(scene, camera)
}
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
})
效果
4 环境属性
统一设置场景中所有物理材质
的环境贴图
如果给每一个物体都单独设置环境纹理贴图
比较麻烦. 可以在场景中统一设置
设置后, 场景中所有物理材质都会使用该环境纹理贴图
背景与环境的区别
- 场景的
背景
设置的是整个3D世界的背景, 作用于场景
- 场景的
环境
设置的是3D世界中所有PBR材质的默认环境纹理贴图
, 作用于物体
完整示例
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
// 一. 创建场景
const scene = new THREE.Scene()
// 创建一个纹理加载器, 加载纹理图片
const texture = new THREE.CubeTextureLoader()
.setPath('/src/assets/texture/Park3Med/')
.load(['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'])
scene.background = texture
scene.environment = texture
// 二. 创建相机
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight
)
camera.position.set(0, 0, 100)
const cubeGeometry = new THREE.BoxGeometry(10, 10, 10)
const cubeMaterial = new THREE.MeshStandardMaterial({
roughness: 0,
metalness: 1,
})
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial)
const sphereGeometry = new THREE.SphereGeometry(10, 32, 32)
const sphereMaterial = new THREE.MeshStandardMaterial({
roughness: 0,
metalness: 1,
})
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial)
sphere.position.set(20, 0, 0)
scene.add(cube)
scene.add(sphere)
// 四. 创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setAnimationLoop(animation)
// 将渲染的canvas添加到body元素中
document.body.appendChild(renderer.domElement)
// 五. 辅助工具
const control = new OrbitControls(camera, renderer.domElement)
function animation() {
renderer.render(scene, camera)
}
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
})
效果
5 雾化
雾化效果
场景中的物体距离相机的距离不同, 显示的颜色不同
- 越近越清晰(接近物体本身的颜色)
- 越远越模糊(接近雾的颜色)
scene.fog = new THREE.Fog(0x0000ff, 50, 100)
- 第一个参数: 雾的颜色
- 第二个参数: 雾化生效的近面距离. 小于该值显示物体本身的颜色
- 第三个参数: 雾化生效的远面距离. 大于该值显示雾的颜色
完整示例
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import * as dat from 'dat.gui'
// 一. 创建场景
const scene = new THREE.Scene()
scene.fog = new THREE.Fog(0x0000ff, 1, 100)
// 二. 创建相机
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight
)
camera.position.set(0, 0, 50)
// 三. 创建物体
const gui = new dat.GUI()
const data = {
addCube: function () {
const size = Math.random() * 3
const cubeGeometry = new THREE.BoxGeometry(size, size, size)
const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 })
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial)
cube.position.x = Math.random() * 20 - 10
cube.position.y = Math.random() * 20 - 10
cube.position.z = Math.random() * 20 - 10
// console.log(cube)
scene.add(cube)
},
}
gui.add(data, 'addCube')
// 四. 创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setAnimationLoop(animation)
// 将渲染的canvas添加到body元素中
document.body.appendChild(renderer.domElement)
// 五. 辅助工具
const control = new OrbitControls(camera, renderer.domElement)
const axesHelper = new THREE.AxesHelper(10)
scene.add(axesHelper)
const gridHelper = new THREE.GridHelper(20, 20, 0xffffff, 0xffffff)
gridHelper.material.transparent = true
gridHelper.material.opacity = 0.5
scene.add(gridHelper)
function animation() {
renderer.render(scene, camera)
}
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
})