微信小程序集成three.js--4.粒子系统,模拟雨雪天气

1.场景演示

小程序集成Three.js,使用粒子系统模拟雨雪天气

2.源码

(1)导入库文件

import * as THREE from '../../libs/three.weapp.js'
import {
    OrbitControls
} from '../../jsm/controls/OrbitControls'
const app = getApp()

(2)雨天场景源码

//初始化雨天场景
initScene() {
        wx.createSelectorQuery()
            .select('#webgl')
            .node()
            .exec((res) => {
                let canvasId = String(res[0].node.id)
                const canvas = THREE.global.registerCanvas(canvasId, res[0].node)
                this.setData({
                    canvasId: canvasId
                })

                //相机
                const camera = new THREE.PerspectiveCamera(70, canvas.width / canvas.height, 1, 1000);

                //场景
                const scene = new THREE.Scene();
                scene.background = new THREE.Color(0xffffff);
                const renderer = new THREE.WebGLRenderer({
                    antialias: true
                });
                camera.position.set(30, 40, 50);

                //控制器
                const controls = new OrbitControls(camera, renderer.domElement);
                controls.enableDamping = true;

                controls.update();

                //声明创建雨点的函数
                function createPointCloud(size, transparent, opacity, sizeAttenuation, color) {
                    //这里加载的纹理贴图是一张雨滴的贴图
                    var texture = new THREE.TextureLoader().load("/pages/image/raindrop-3.png");
                    var geom = new THREE.Geometry();
                    var material = new THREE.PointsMaterial({
                        size: size,
                        transparent: transparent,
                        opacity: opacity,
                        map: texture,
                        blending: THREE.AdditiveBlending,
                        sizeAttenuation: sizeAttenuation,
                        color: color
                    });
                    var range = 100;
                    for (var i = 0; i < 1500; i++) {
                        var particle = new THREE.Vector3(
                            Math.random() * range - range / 2,
                            Math.random() * range * 1.5,
                            1 + (i / 50)
                        )
                        particle.velocityY = 0.1 + Math.random() / 5;
                        particle.velocityX = (Math.random() - 0.5) / 3;
                        geom.vertices.push(particle);
                    }
                    cloud = new THREE.Points(geom, material);
                    cloud.sortParticles = true;
                    cloud.name = "particles1"
                    scene.add(cloud);
                }

                createPointCloud(3, true, 0.6, true, 0xffffff)

                //创建平面
                const planeGeometry = new THREE.PlaneGeometry(200, 150, 20, 20);
                const planeMaterial = new THREE.MeshBasicMaterial({
                    color: 0xc7c7c7,
                });
                planeMaterial.side = THREE.DoubleSide;
                const plane = new THREE.Mesh(planeGeometry, planeMaterial)
                plane.rotation.x = Math.PI / 2
                plane.position.y = -10
                scene.add(plane)

                //辅助线
                const axesHelper = new THREE.AxesHelper(500);
                scene.add(axesHelper)

                renderer.setPixelRatio(wx.getSystemInfoSync().pixelRatio);
                renderer.setSize(canvas.width, canvas.height);

                function render() {
                    var vertices = cloud.geometry.vertices;
                    vertices.forEach(function (v) {
                        v.y = v.y - (v.velocityY);
                        v.x = v.x - (v.velocityX);

                        if (v.y <= 0) v.y = 60;
                        if (v.x <= -20 || v.x >= 20) v.velocityX = v.velocityX * -1;
                    });
                    cloud.geometry.verticesNeedUpdate = true;
                    canvas.requestAnimationFrame(render);
                    //更新控制器
                    controls.update();
                    renderer.render(scene, camera);
                }
                render()
            })
    },

(3)雪天场景源码

//雪天场景源码
initScene() {
        wx.createSelectorQuery()
            .select('#webgl')
            .node()
            .exec((res) => {
                let canvasId = String(res[0].node.id)
                const canvas = THREE.global.registerCanvas(canvasId, res[0].node)
                this.setData({
                    canvasId: canvasId
                })
                //相机
                const camera = new THREE.PerspectiveCamera(70, canvas.width / canvas.height, 1, 1000);
                //场景
                const scene = new THREE.Scene();
                scene.background = new THREE.Color(0xffffff);
                const renderer = new THREE.WebGLRenderer({
                    antialias: true
                });
                camera.position.set(30, 40, 50);

                //控制器
                const controls = new OrbitControls(camera, renderer.domElement);
                controls.enableDamping = true;

                controls.update();


                function createPointCloud(name, texture, size, transparent, opacity, sizeAttenuation, color) {
                    var geom = new THREE.Geometry();

                    var color = new THREE.Color(color);
                    color.setHSL(color.getHSL().h,
                        color.getHSL().s,
                        (Math.random()) * color.getHSL().l);

                    var material = new THREE.PointsMaterial({
                        size: size,
                        transparent: transparent,
                        opacity: opacity,
                        map: texture,
                        blending: THREE.AdditiveBlending,
                        depthWrite: false,
                        sizeAttenuation: sizeAttenuation,
                        color: color
                    });

                    var range = 100;
                    for (var i = 0; i < 150; i++) {
                        var particle = new THREE.Vector3(
                            Math.random() * range - range / 2,
                            Math.random() * range * 1.5,
                            Math.random() * range - range / 2);
                        particle.velocityY = 0.1 + Math.random() / 5;
                        particle.velocityX = (Math.random() - 0.5) / 3;
                        particle.velocityZ = (Math.random() - 0.5) / 3;
                        geom.vertices.push(particle);
                    }

                    var system = new THREE.Points(geom, material);
                    system.name = name;
                    return system;
                }

                function createPointInstances(size, transparent, opacity, sizeAttenuation, color) {

                    var loader = new THREE.TextureLoader();
                    
                    // 这里加载了4个不同雪片的贴图
                    var texture1 = loader.load("/pages/image/snowflake1_t.png");
                    var texture2 = loader.load("/pages/image/snowflake2_t.png");
                    var texture3 = loader.load("/pages/image/snowflake3_t.png");
                    var texture4 = loader.load("/pages/image/snowflake5_t.png");

                    scene.add(createPointCloud("system1", texture1, size, transparent, opacity, sizeAttenuation, color));
                    scene.add(createPointCloud("system2", texture2, size, transparent, opacity, sizeAttenuation, color));
                    scene.add(createPointCloud("system3", texture3, size, transparent, opacity, sizeAttenuation, color));
                    scene.add(createPointCloud("system4", texture4, size, transparent, opacity, sizeAttenuation, color));
                }

                createPointInstances(10, true, 0.6, true, 0xffffff)

                //平面
                const planeGeometry = new THREE.PlaneGeometry(200, 150, 20, 20);
                const planeMaterial = new THREE.MeshBasicMaterial({
                    color: 0xc7c7c7
                });
                planeMaterial.side = THREE.DoubleSide;
                const plane = new THREE.Mesh(planeGeometry, planeMaterial)
                plane.rotation.x = Math.PI / 2
                plane.position.y = -10
                scene.add(plane)

                //辅助线
                const axesHelper = new THREE.AxesHelper(500);
                scene.add(axesHelper)

                renderer.setPixelRatio(wx.getSystemInfoSync().pixelRatio);
                renderer.setSize(canvas.width, canvas.height);

                function render() {
                    //这里通过变更雪片的位置,创造出下雪的效果
                    scene.children.forEach(function (child) {
                        if (child instanceof THREE.Points) {
                            var vertices = child.geometry.vertices;
                            vertices.forEach(function (v) {
                                v.y = v.y - (v.velocityY);
                                v.x = v.x - (v.velocityX);
                                v.z = v.z - (v.velocityZ);

                                if (v.y <= 0) v.y = 60;
                                if (v.x <= -20 || v.x >= 20) v.velocityX = v.velocityX * -1;
                                if (v.z <= -20 || v.z >= 20) v.velocityZ = v.velocityZ * -1;
                            });

                            child.geometry.verticesNeedUpdate = true;
                        }
                    });
                    canvas.requestAnimationFrame(render);
                    //更新控制器
                    controls.update();
                    renderer.render(scene, camera);
                }

                render()
            })
    },

(4)源码说明

雪天和雨天场景的创建几乎是一样的,区别在于雪天加载了4张不同的雪花纹理图片,创造出更逼真的效果。

动画的实现是在渲染函数中,当渲染下一帧时,遍历scene下的所有子对象,如果是THREE.Points的实例,则对其坐标通过算法进行修改,从而实现雪花飘落的效果。

3.演示小程序

场景演示->粒子系统的应用 

猜你喜欢

转载自blog.csdn.net/weixin_39318421/article/details/128490587
今日推荐