使用 Three.js 创建逼真的暴风雨场景
本文将详细介绍如何使用 Three.js 构建一个视觉效果强烈的暴风雨场景。
通过结合粒子系统、纹理加载以及光照控制,我们能创建出带有云层、闪电、雨滴以及雾气效果的逼真动态场景。

一、功能概述
-
云层效果:利用透明的纹理图片实现云层。
-
降雨效果:利用粒子系统生成大量雨滴。
-
闪电效果:通过随机控制点光源实现闪电瞬间的亮光闪烁。
-
雾化效果:场景中启用指数雾效,增加场景真实感和景深感。
二、初始化场景和相机设置
在这一部分,我们初始化了 Three.js 必备的基础元素:场景、相机和渲染器。这三个元素分别负责管理所有物体、观察视角以及画面呈现。相机参数经过精心调整,以产生独特的视角效果。
- 场景:用于包含所有的图像、光线和环境效果。
- 相机:使用透视相机,并且通过特定的旋转来模拟观看天空的角度。
- 渲染器:负责将场景渲染到画布上,并启用雾效背景。
代码实现及详解
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
// 设置相机位置和旋转角度,以模拟向天空仰视的效果
camera.position.set(0, 0, 1);
camera.rotation.set(1.16, -0.12, 0.27);
renderer = new THREE.WebGLRenderer();
scene.fog = new THREE.FogExp2(0x11111f, 0.002); // 指数型雾效,模拟雨雾中的视距衰减
renderer.setClearColor(scene.fog.color);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);我们使用指数雾效(FogExp2)实现真实的景深感,使远处的物体逐渐被雾气遮挡而变得模糊。
三、光源设置与闪电效果
为了模拟暴风雨中特殊的闪电效果,我们组合使用了环境光、方向光以及点光源。特别是点光源(PointLight)用于模拟闪电,通过随机闪烁的位置和强度实现真实感。
代码实现及详解
ambient = new THREE.AmbientLight(0x555555); // 环境光提供基础照明,避免场景过暗
scene.add(ambient);
directionalLight = new THREE.DirectionalLight(0xffeedd); // 模拟方向性的微弱光照,增强立体感
directionalLight.position.set(0, 0, 1);
scene.add(directionalLight);
flash = new THREE.PointLight(0x062d89, 30, 500, 1.7); // 闪电点光源
flash.position.set(200, 300, 100);
scene.add(flash);点光源强度随机变化的逻辑放在动画循环中,通过随机概率实现闪电忽明忽暗的自然效果。
四、雨滴粒子系统的创建与控制
降雨效果通过Three.js的粒子系统实现。我们定义了大量随机位置的粒子,这些粒子将模拟雨滴从天空坠落的效果。
代码实现及详解
rainGeo = new THREE.BufferGeometry();
let positions = [];
for (let i = 0; i < rainCount; i++) {
positions.push(
Math.random() * 400 - 200,
Math.random() * 500 - 250,
Math.random() * 400 - 200
);
}
rainGeo.setAttribute('position', new THREE.BufferAttribute(new Float32Array(positions), 3));
rainMaterial = new THREE.PointsMaterial({
color: 0xaaaaaa,
size: 0.1,
transparent: true
});
rain = new THREE.Points(rainGeo, rainMaterial);
scene.add(rain);此处我们使用了BufferGeometry来高效处理大量粒子,性能更好,渲染更快。
五、云层纹理加载与位置摆放
云层采用透明纹理,通过TextureLoader加载外部图片

并创建多个平面网格(Mesh)组成云层场景,每个云层都随机旋转以增加真实感。
代码实现及详解
let loader = new THREE.TextureLoader();
loader.load(
'YOUR_CLOUD_TEXTURE_URL', // 云纹理URL
function(texture) {
cloudGeo = new THREE.PlaneBufferGeometry(500, 500);
cloudMaterial = new THREE.MeshLambertMaterial({ map: texture, transparent: true });
for (let p = 0; p < 25; p++) {
let cloud = new THREE.Mesh(cloudGeo, cloudMaterial);
cloud.position.set(Math.random() * 800 - 400, 500, Math.random() * 500 - 450);
cloud.rotation.set(1.16, -0.12, Math.random() * Math.PI * 2);
cloud.material.opacity = 0.6;
cloudParticles.push(cloud);
scene.add(cloud);
}
animate();
window.addEventListener('resize', onWindowResize);
}
);云层透明度控制在0.6,以实现较真实的透光效果。
六、动画与动态效果实现
通过动画循环控制云层的缓慢旋转、雨滴位置的动态调整以及闪电随机效果,使整个场景更具动态感和真实感。
代码实现及详解
function animate() {
cloudParticles.forEach((p) => {
p.rotation.z -= 0.002; // 缓慢旋转云层
});
// 雨滴下落效果
rain.position.z -= 0.222;
if (rain.position.z < -200) rain.position.z = 0;
// 闪电随机闪烁
if (Math.random() > 0.93 || flash.power > 100) {
if (flash.power < 100)
flash.position.set(Math.random() * 400, 300 + Math.random() * 200, 100);
flash.power = 50 + Math.random() * 500;
}
renderer.render(scene, camera);
requestAnimationFrame(animate);
}动画循环通过requestAnimationFrame保证流畅的帧率和性能。
七、窗口自适应
场景随着窗口尺寸的变化自动调整画布和相机视野,保证显示效果的一致性。
代码实现及详解
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}八、总结
通过组合运用粒子系统、纹理加载、光照和动态动画,我们成功打造了一个真实的暴风雨场景。
这些技术不仅适用于天气效果模拟,还可以扩展到其他动态特效场景的实现。希望本文能帮你理解 Three.js 中各种技术细节的结合运用,并激发你的更多创作灵感。