Three.JS提升学习3:粒子

本文学习资源来自《Three.js开发指南》


一、理解粒子

粒子用来模拟很多细小的物体,如雨滴、雪花、烟等。

1. 使用THREE.Sprite创建简单粒子

关键代码:

        function createSprites() {
            var material = new THREE.SpriteMaterial();


            for (var x = -5; x < 5; x++) {
                for (var y = -5; y < 5; y++) {
                    var sprite = new THREE.Sprite(material);
                    sprite.position.set(x * 10, y * 10, 0);
                    scene.add(sprite);
                }
            }
        }

创建10*10的粒子,一个粒子是一个二维平面,总是面向摄像机。
这些粒子没有指定属性,默认渲染成白色方块。
这里写图片描述

这里使用的THREE.Sprite用来创建粒子。THREE.Sprite是THREE.Object3D对象的扩展,也就是说THREE.Mesh的大部分属性和函数都可用于THREE.Sprite。

当粒子数量非常大时,使用大量THREE.Sprite会遇到性能问题。

2. 使用THREE.PointCloud处理大量粒子

        function createParticles() {


            var geom = new THREE.Geometry();
            var material = new THREE.PointCloudMaterial({size: 4, vertexColors: true, color: 0xffffff});

            for (var x = -5; x < 5; x++) {
                for (var y = -5; y < 5; y++) {
                    var particle = new THREE.Vector3(x * 10, y * 10, 0);
                    geom.vertices.push(particle);
                    geom.colors.push(new THREE.Color(Math.random() * 0x00ffff));
                }
            }

            var cloud = new THREE.PointCloud(geom, material);
            scene.add(cloud);
        }

这里每个粒子需要创建一个顶点THREE.Vector3对象,并添加到THREE.Geometry中,使用THREE.Geometry和THREE.PointCloudMaterial一起创建THREE.PointCloud,再把云添加到场景中。

这里写图片描述

3. 给粒子使用样式

       function createParticles(size, transparent, opacity, vertexColors, sizeAttenuation, color) {


            var geom = new THREE.Geometry();
            var material = new THREE.PointCloudMaterial({
                size: size,
                transparent: transparent,
                opacity: opacity,
                vertexColors: vertexColors,

                sizeAttenuation: sizeAttenuation,
                color: color
            });


            var range = 500;
            for (var i = 0; i < 15000; i++) {
                var particle = new THREE.Vector3(Math.random() * range - range / 2, Math.random() * range - range / 2, Math.random() * range - range / 2);
                geom.vertices.push(particle);
                var color = new THREE.Color(0x00ff00);
                color.setHSL(color.getHSL().h, color.getHSL().s, Math.random() * color.getHSL().l);
                geom.colors.push(color);

            }

            cloud = new THREE.PointCloud(geom, material);
            cloud.name = "particles";
            scene.add(cloud);
        }
                var step = 0;

        function render() {

            stats.update();

            if (controls.rotateSystem) {
                step += 0.01;

                cloud.rotation.x = step;
                cloud.rotation.z = step;
            }


            requestAnimationFrame(render);
            webGLRenderer.render(scene, camera);
        }

书籍官方式示例效果:
这里写图片描述

3. 使用HTML5画布样式化粒子

Three.js提供了三种使用HTML5画布来样式化粒子的方法。
如果使用的是THREE.CanvasRenderer,可以通过THREE.SpriteCanvasMaterial直接引用HTML5画布。如果用的是THREE.WebGLRenderer,那么需要采取一些额外的步骤才能使用HTML5画布样式化粒子。

在THREE.CanvasRenderer中使用HTML5画布
在WebGLRenderer中使用HTML5画布

4. 使用纹理样式化粒子


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

            var texture = THREE.ImageUtils.loadTexture("../assets/textures/particles/raindrop-3.png");
            var geom = new THREE.Geometry();

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


            var range = 40;
            for (var i = 0; i < 1500; 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;
                geom.vertices.push(particle);
            }

            cloud = new THREE.ParticleSystem(geom, material);
            cloud.sortParticles = true;

            scene.add(cloud);
        }

5. 使用精灵贴图

6. 从高级几何体创建THREE.PointCloud

       render();

        // from THREE.js examples
        function generateSprite() {

            var canvas = document.createElement('canvas');
            canvas.width = 16;
            canvas.height = 16;

            var context = canvas.getContext('2d');
            var gradient = context.createRadialGradient(canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2);
            gradient.addColorStop(0, 'rgba(255,255,255,1)');
            gradient.addColorStop(0.2, 'rgba(0,255,255,1)');
            gradient.addColorStop(0.4, 'rgba(0,0,64,1)');
            gradient.addColorStop(1, 'rgba(0,0,0,1)');

            context.fillStyle = gradient;
            context.fillRect(0, 0, canvas.width, canvas.height);

            var texture = new THREE.Texture(canvas);
            texture.needsUpdate = true;
            return texture;

        }

        function createPointCloud(geom) {
            var material = new THREE.PointCloudMaterial({
                color: 0xffffff,
                size: 3,
                transparent: true,
                blending: THREE.AdditiveBlending,
                map: generateSprite() //把粒子设置成发光点
            });

            var cloud = new THREE.PointCloud(geom, material);
            cloud.sortParticles = true;
            return cloud;
        }

        function createMesh(geom) {

            // assign two materials
            var meshMaterial = new THREE.MeshNormalMaterial({});
            meshMaterial.side = THREE.DoubleSide;

            // create a multimaterial
            var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial]);

            return mesh;
        }

        function render() {
            stats.update();

            if (controls.rotate) {
                knot.rotation.y = step += 0.01;
            }

            // render using requestAnimationFrame
            requestAnimationFrame(render);
            webGLRenderer.render(scene, camera);
        }

官方运行示例:
这里写图片描述
参考:
https://www.cnblogs.com/amy2011/p/6358330.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程圈子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值