参考资料:threejs中文网

threejs qq交流群:814702116

Sprite模拟下雨、下雪

在实际开发的时候,物联网3D可视化、数字孪生、游戏等项目可能会模拟天气的效果。

如果你想模拟下雨效果,一个雨滴用一个3D水滴形曲面表示,假设一个水滴用40个三角形表示,1万个雨滴,就是40万个三角形,精灵模型Sprite在threejs内部就像相当于两个三角形构成的矩形,1万个精灵模型,相当于2万个三角形,Sprite模拟雨滴相比比3D曲面几何体表示雨滴顶点数量就会少很多,这样threejs渲染性能就更好。

Sprite模拟雨滴

提供一个背景透明的png雨滴贴图,然后作为Sprite的颜色贴图,用来模拟雨滴3D几何体。

const texture = new THREE.TextureLoader().load("./雨滴.png");
const spriteMaterial = new THREE.SpriteMaterial({
    map: texture, 
});
const sprite = new THREE.Sprite(spriteMaterial);

雨滴在3D空间随机分布

批量创建多个精灵模型,在一个长方体空间上随机分布。

Sprite分布渲染范围和数量,根据渲染范围来预先给一个大概的值,然后可以根据需要,在调整雨滴分布范围尺寸。

const group = new THREE.Group();
for (let i = 0; i < 16000; i++) {
    // 精灵模型共享材质
    const sprite = new THREE.Sprite(spriteMaterial);
    group.add(sprite);
    sprite.scale.set(1, 1, 1);
    // 设置精灵模型位置,在长方体空间上上随机分布
    const x = 1000 * (Math.random() - 0.5);
    const y = 600 * Math.random();
    const z = 1000 * (Math.random() - 0.5);
    sprite.position.set(x, y, z)
}

周期性改变雨滴Sprite位置

function loop() {
    // loop()每次执行都会更新雨滴的位置,进而产生动画效果
    group.children.forEach(sprite => {
        // 雨滴的y坐标每次减1
        sprite.position.y -= 1;
        if (sprite.position.y < 0) {
            // 如果雨滴落到地面,重置y,从新下落
            sprite.position.y = 600;
        }
    });
    requestAnimationFrame(loop);
}
loop();

loop()执行时间间隔和渲染循环render()是一样的。

根据时间计算Sprite位置

const clock = new THREE.Clock();
function loop() {
    // loop()两次执行时间间隔
    const t = clock.getDelta();
    group.children.forEach(sprite => {
        // 雨滴的y坐标每次减t*60
        sprite.position.y -= t*60;
        if (sprite.position.y < 0) {
            sprite.position.y = 600;
        }
    });
    requestAnimationFrame(loop);
}
loop();

相机镜头附近的雨滴偏大

相机在下雨的场景中,相机会渲染nearfar范围的Sprite,距离相机0near范围不会渲染,小部分Sprite会在相机镜头前经过,大家都知道透视投影远小近大,这时候相机near附近雨滴Sprite会显示比较大,你可以把near调整大一些,这样距离相机非常近的Sprite不会渲染。

const camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000);

near调整大一些,避免距离相机非常近的雨滴渲染非常大的现象。

const camera = new THREE.PerspectiveCamera(30, width / height, 50, 3000);

下雪效果模拟

把雨滴代码中与雨滴贴图更换雪花纹理贴图,雪花下降速度可以适当调整。当然这也只是近似模拟,比如雪花随风飘动、角度旋转等等都没有模拟。

const texture = new THREE.TextureLoader().load("./雪花.png");
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐