Three.js中的雾与大气特效
在Three.js中,雾和大气特效可以为场景增添更多的真实感和沉浸感。这些特效模拟了现实世界中的自然现象,如雾、烟、云等,使场景更加生动和引人入胜。本节将详细介绍如何在Three.js中实现雾和大气特效,并提供具体的代码示例和数据样例。
雾特效
雾特效在Three.js中通过Fog
和FogExp2
类来实现。这两种雾的效果不同,可以根据具体需求选择使用。
1. 线性雾(Fog)
线性雾是从近到远逐渐变淡的效果。可以通过设置雾的近距和远距来控制雾的透明度变化。
原理
线性雾的基本原理是根据物体与摄像机之间的距离来计算透明度。距离在近距和远距之间的物体将逐渐变淡,直到完全透明。
使用方法
// 创建场景
const scene = new THREE.Scene();
// 创建雾
const fog = new THREE.Fog(0xffffff, 1, 100); // 雾颜色为白色,近距为1,远距为100
scene.fog = fog; // 将雾添加到场景中
// 创建相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 创建几何体和材质
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
// 渲染循环
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
代码解析
-
THREE.Fog(0xffffff, 1, 100)
:创建一个线性雾,颜色为白色(0xffffff),近距为1,远距为100。 -
scene.fog = fog
:将雾添加到场景中。 -
renderer.render(scene, camera)
:渲染场景。
2. 指数雾(FogExp2)
指数雾是根据距离的指数衰减来计算透明度。这种雾的效果更加自然,适合模拟大气的散射效果。
原理
指数雾的基本原理是根据物体与摄像机之间的距离的指数衰减来计算透明度。距离越远,透明度越快地衰减。
使用方法
// 创建场景
const scene = new THREE.Scene();
// 创建指数雾
const fog = new THREE.FogExp2(0xffffff, 0.05); // 雾颜色为白色,密度为0.05
scene.fog = fog; // 将雾添加到场景中
// 创建相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 创建几何体和材质
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
// 渲染循环
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
代码解析
-
THREE.FogExp2(0xffffff, 0.05)
:创建一个指数雾,颜色为白色(0xffffff),密度为0.05。 -
scene.fog = fog
:将雾添加到场景中。 -
renderer.render(scene, camera)
:渲染场景。
大气特效
大气特效可以模拟天空的光线散射效果,使场景中的天空看起来更加真实。Three.js中可以使用THREE.ShaderMaterial
和自定义着色器来实现大气特效。
1. 简单的大气散射效果
使用THREE.ShaderMaterial
可以创建一个简单的天空大气散射效果。
原理
大气散射效果通过自定义着色器来模拟光线在大气中的散射。可以使用顶点着色器和片段着色器来实现。
使用方法
// 创建场景
const scene = new THREE.Scene();
// 创建相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 创建天空球几何体
const skyGeometry = new THREE.SphereGeometry(1000, 64, 64);
// 定义顶点着色器
const skyVertexShader = `
varying vec3 vWorldPosition;
void main() {
vec4 worldPosition = modelMatrix * vec4(position, 1.0);
vWorldPosition = worldPosition.xyz;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;
// 定义片段着色器
const skyFragmentShader = `
uniform vec3 topColor;
uniform vec3 bottomColor;
uniform float offset;
uniform float exponent;
varying vec3 vWorldPosition;
void main() {
float h = normalize(vWorldPosition + offset).y;
vec3 atmosphere = topColor * pow(max(h, 0.0), exponent) + bottomColor * max(1.0 - h, 0.0);
gl_FragColor = vec4(atmosphere, 1.0);
}
`;
// 创建天空球材质
const skyMaterial = new THREE.ShaderMaterial({
vertexShader: skyVertexShader,
fragmentShader: skyFragmentShader,
uniforms: {
topColor: { value: new THREE.Color(0x0077ff) }, // 天空顶部颜色
bottomColor: { value: new THREE.Color(0xffffff) }, // 天空底部颜色
offset: { value: 33.0 }, // 偏移量
exponent: { value: 0.6 }, // 指数
},
side: THREE.BackSide
});
// 创建天空球
const skyMesh = new THREE.Mesh(skyGeometry, skyMaterial);
scene.add(skyMesh);
// 创建地面几何体和材质
const groundGeometry = new THREE.PlaneGeometry(100, 100);
const groundMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00, side: THREE.DoubleSide });
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
scene.add(ground);
// 渲染循环
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
代码解析
-
THREE.SphereGeometry(1000, 64, 64)
:创建一个天空球几何体,半径为1000,细分64次。 -
THREE.ShaderMaterial
:创建一个自定义着色器材质。 -
skyVertexShader
和skyFragmentShader
:定义顶点着色器和片段着色器。 -
uniforms
:定义着色器中的统一变量,包括天空顶部和底部的颜色、偏移量和指数。 -
THREE.BackSide
:设置材质的渲染面为内侧,以确保天空球的内表面被渲染。 -
skyMesh
:创建天空球网格并添加到场景中。 -
renderer.render(scene, camera)
:渲染场景。
2. 复杂的大气散射效果
为了实现更复杂的大气散射效果,可以使用three-atmosphere
库。这个库提供了预定义的大气散射着色器,可以方便地实现高级的大气特效。
安装
首先需要安装three-atmosphere
库:
npm install three-atmosphere
使用方法
import * as THREE from 'three';
import { Atmosphere, AtmosphereParameters } from 'three-atmosphere';
// 创建场景
const scene = new THREE.Scene();
// 创建相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 创建大气特效
const atmosphereParams = new AtmosphereParameters();
atmosphereParams.topColor.set(0x0077ff); // 天空顶部颜色
atmosphereParams.bottomColor.set(0xffffff); // 天空底部颜色
atmosphereParams.turbidity = 10; // 浑浊度
atmosphereParams.rayleigh = 1; // 瑞利散射系数
atmosphereParams.mieCoefficient = 0.005; // 米氏散射系数
atmosphereParams.mieDirectionalG = 0.8; // 米氏散射方向性
const atmosphere = new Atmosphere(atmosphereParams);
atmosphere.renderToScene(scene);
// 创建地面几何体和材质
const groundGeometry = new THREE.PlaneGeometry(100, 100);
const groundMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00, side: THREE.DoubleSide });
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
scene.add(ground);
// 渲染循环
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
代码解析
-
import { Atmosphere, AtmosphereParameters } from 'three-atmosphere'
:导入three-atmosphere
库中的Atmosphere
和AtmosphereParameters
类。 -
AtmosphereParameters
:创建大气参数对象。 -
atmosphereParams.topColor.set(0x0077ff)
和atmosphereParams.bottomColor.set(0xffffff)
:设置天空顶部和底部的颜色。 -
atmosphereParams.turbidity
:设置大气的浑浊度。 -
atmosphereParams.rayleigh
:设置瑞利散射系数。 -
atmosphereParams.mieCoefficient
:设置米氏散射系数。 -
atmosphereParams.mieDirectionalG
:设置米氏散射方向性。 -
new Atmosphere(atmosphereParams)
:创建大气特效对象。 -
atmosphere.renderToScene(scene)
:将大气特效添加到场景中。 -
renderer.render(scene, camera)
:渲染场景。
实例分析
1. 结合雾和大气特效
在实际应用中,可以同时使用雾和大气特效来增强场景的真实感。以下是一个结合线性雾和大气散射效果的示例。
代码示例
import * as THREE from 'three';
import { Atmosphere, AtmosphereParameters } from 'three-atmosphere';
// 创建场景
const scene = new THREE.Scene();
// 创建线性雾
const fog = new THREE.Fog(0xffffff, 1, 100); // 雾颜色为白色,近距为1,远距为100
scene.fog = fog; // 将雾添加到场景中
// 创建相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 创建大气特效
const atmosphereParams = new AtmosphereParameters();
atmosphereParams.topColor.set(0x0077ff); // 天空顶部颜色
atmosphereParams.bottomColor.set(0xffffff); // 天空底部颜色
atmosphereParams.turbidity = 10; // 浑浊度
atmosphereParams.rayleigh = 1; // 瑞利散射系数
atmosphereParams.mieCoefficient = 0.005; // 米氏散射系数
atmosphereParams.mieDirectionalG = 0.8; // 米氏散射方向性
const atmosphere = new Atmosphere(atmosphereParams);
atmosphere.renderToScene(scene);
// 创建地面几何体和材质
const groundGeometry = new THREE.PlaneGeometry(100, 100);
const groundMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00, side: THREE.DoubleSide });
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
scene.add(ground);
// 创建立方体几何体和材质
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.position.z = 20; // 将立方体放置在较远的位置
scene.add(cube);
// 渲染循环
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
代码解析
-
THREE.Fog(0xffffff, 1, 100)
:创建一个线性雾,颜色为白色,近距为1,远距为100。 -
scene.fog = fog
:将雾添加到场景中。 -
AtmosphereParameters
:创建大气参数对象。 -
new Atmosphere(atmosphereParams)
:创建大气特效对象。 -
atmosphere.renderToScene(scene)
:将大气特效添加到场景中。 -
cube.position.z = 20
:将立方体放置在较远的位置,以展示雾的效果。 -
renderer.render(scene, camera)
:渲染场景。
2. 动态雾和大气特效
在某些场景中,可能需要动态调整雾和大气特效的参数,以实现不同的效果。以下是一个动态调整雾和大气特效参数的示例。
代码示例
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { Atmosphere, AtmosphereParameters } from 'three-atmosphere';
import { GUI } from 'dat.gui';
// 创建场景
const scene = new THREE.Scene();
// 创建线性雾
const fog = new THREE.Fog(0xffffff, 1, 100); // 雾颜色为白色,近距为1,远距为100
scene.fog = fog; // 将雾添加到场景中
// 创建相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 创建大气特效
const atmosphereParams = new AtmosphereParameters();
atmosphereParams.topColor.set(0x0077ff); // 天空顶部颜色
atmosphereParams.bottomColor.set(0xffffff); // 天空底部颜色
atmosphereParams.turbidity = 10; // 浑浊度
atmosphereParams.rayleigh = 1; // 瑞利散射系数
atmosphereParams.mieCoefficient = 0.005; // 米氏散射系数
atmosphereParams.mieDirectionalG = 0.8; // 米氏散射方向性
const atmosphere = new Atmosphere(atmosphereParams);
atmosphere.renderToScene(scene);
// 创建地面几何体和材质
const groundGeometry = new THREE.PlaneGeometry(100, 100);
const groundMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00, side: THREE.DoubleSide });
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
scene.add(ground);
// 创建立方体几何体和材质
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.position.z = 20; // 将立方体放置在较远的位置
scene.add(cube);
// 创建轨道控制
const controls = new OrbitControls(camera, renderer.domElement);
// 创建GUI控件
const gui = new GUI();
const fogFolder = gui.addFolder('Fog');
fogFolder.add(fog, 'near', 0, 100).onChange(value => {
fog.near = value;
scene.fog = fog;
});
fogFolder.add(fog, 'far', 100, 1000).onChange(value => {
fog.far = value;
scene.fog = fog;
});
const atmosphereFolder = gui.addFolder('Atmosphere');
atmosphereFolder.add(atmosphereParams, 'turbidity', 0, 20).onChange(value => {
atmosphereParams.turbidity = value;
atmosphere.parameters = atmosphereParams;
});
atmosphereFolder.add(atmosphereParams, 'rayleigh', 0, 10).onChange(value => {
atmosphereParams.rayleigh = value;
atmosphere.parameters = atmosphereParams;
});
atmosphereFolder.add(atmosphereParams, 'mieCoefficient', 0, 0.1).onChange(value => {
atmosphereParams.mieCoefficient = value;
atmosphere.parameters = atmosphereParams;
});
atmosphereFolder.add(atmosphereParams, 'mieDirectionalG', 0, 1).onChange(value => {
atmosphereParams.mieDirectionalG = value;
atmosphere.parameters = atmosphereParams;
});
// 渲染循环
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
代码解析
-
THREE.Fog(0xffffff, 1, 100)
:创建一个线性雾,颜色为白色,近距为1,远距为100。 -
scene.fog = fog
:将雾添加到场景中。 -
AtmosphereParameters
:创建大气参数对象。 -
new Atmosphere(atmosphereParams)
:创建大气特效对象。 -
atmosphere.renderToScene(scene)
:将大气特效添加到场景中。 -
cube.position.z = 20
:将立方体放置在较远的位置,以展示雾的效果。 -
renderer.render(scene, camera)
:渲染场景。
动态调整参数
-
const gui = new GUI()
:创建一个GUI控件,用于动态调整参数。 -
fogFolder.add(fog, 'near', 0, 100).onChange(value => { ... })
:添加一个控件来调整雾的近距,并在值变化时更新雾的参数。 -
fogFolder.add(fog, 'far', 100, 1000).onChange(value => { ... })
:添加一个控件来调整雾的远距,并在值变化时更新雾的参数。 -
atmosphereFolder.add(atmosphereParams, 'turbidity', 0, 20).onChange(value => { ... })
:添加一个控件来调整大气的浑浊度,并在值变化时更新大气参数。 -
atmosphereFolder.add(atmosphereParams, 'rayleigh', 0, 10).onChange(value => { ... })
:添加一个控件来调整瑞利散射系数,并在值变化时更新大气参数。 -
atmosphereFolder.add(atmosphereParams, 'mieCoefficient', 0, 0.1).onChange(value => { ... })
:添加一个控件来调整米氏散射系数,并在值变化时更新大气参数。 -
atmosphereFolder.add(atmosphereParams, 'mieDirectionalG', 0, 1).onChange(value => { ... })
:添加一个控件来调整米氏散射方向性,并在值变化时更新大气参数。
3. 优化和注意事项
雾特效的优化
-
颜色选择:选择适合场景的雾颜色,可以增强场景的氛围感。例如,蓝色雾可以模拟清晨或傍晚的天空。
-
距离设置:合理设置雾的近距和远距,可以避免物体在较近的距离内就完全透明,影响视觉效果。
-
材质兼容:确保场景中的所有材质都支持雾效果。例如,
THREE.MeshBasicMaterial
不支持雾,而THREE.MeshStandardMaterial
和THREE.MeshPhongMaterial
则支持。
大气特效的优化
-
性能:大气特效使用自定义着色器,可能会对性能产生一定影响。可以通过减少几何体的细分次数或使用较低分辨率的纹理来优化性能。
-
参数调整:大气特效的参数需要根据具体场景进行调整,以达到最佳效果。例如,浑浊度(
turbidity
)可以调整天空的浑浊程度,瑞利散射系数(rayleigh
)可以调整天空的蓝色调。
总结
在Three.js中,雾和大气特效可以显著提升场景的真实感和沉浸感。通过使用THREE.Fog
和THREE.FogExp2
类,可以轻松实现线性雾和指数雾效果。而使用THREE.ShaderMaterial
和three-atmosphere
库,则可以实现更复杂的大气散射效果。动态调整这些特效的参数,可以使场景更加灵活和交互友好。在实际应用中,需要根据场景的需求和性能情况,合理选择和优化这些特效。
希望本节内容对你在Three.js中实现雾和大气特效有所帮助。如果你有任何疑问或需要进一步的帮助,请随时联系我。