粒子和粒子系统

1.粒子材质和粒子几何体

创建粒子系统的点,可以存放在Geometry几何体中。使用Geometry的vertices保存点、colors保存点的颜色。但我们必须使用粒子的专用材质对象PointCloudMaterial(原名叫做ParticleBasicMaterial)设置材质。包含的属性如下列表:

名称/描述

color/PointCloud对象中所有粒子的颜色。如果vertexColors设置为true,而且也指定了几何体的colors属性,那么该属性被忽略

map/可以在粒子上应用某种材质。例如可以让粒子看起来像雪花

size/粒子大小

sizeAttenuation/如果设置为false,所有粒子都有拥有相同的尺寸。如果为true,粒子的大小取决于离相机的远近

vertexColors/如果设置为true,并且几何体的colors数组也有值,那就使用颜色数组中的值

opacity/跟transparent属性一起使用,用来设置粒子的透明度

transparent/如果为true,那么opacity设置有效

blending/渲染粒子时的融合方式

fog/是否采用场景的雾化效果

把点vertex和颜色color都附加到Geometry对象中后,使用PointCloud(原ParticleSystem对象)创建几何粒子系统。如下面的例子:

function createParticle(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);

            }

2.使用Canvas输出结果作为粒子材质

和1中的创建PointCloudMaterial相似,只是这里增加了一个属性map,减少了属性vertexColors(因为直接使用纹理而不是颜色)。新增了一个map属性,具体值是调用getTexture函数返回一个Texture对象。创建PointCloudMaterial代码如下:

var material = new THREE.PointCloudMaterial({
                    size: size,
                    transparent: transparent,
                    opacity: opacity,
                    map: getTexture(),
                    sizeAttenuation: sizeAttenuation,
                    color: color,
                });

Texture对象可以直接接受一个canvas对象,把canvas的输出作为纹理。创建Texture代码如下:

var getTexture = function () {
            var canvas = document.createElement(‘canvas‘);
            canvas.width = 32;
            canvas.height = 32;

            var ctx = canvas.getContext(‘2d‘);
            // the body
            ctx.translate(-81, -84);

            ctx.fillStyle = "orange";
           ...
            ctx.fill();

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

需要设置纹理的needsUpdate为true。另外,在创建PointCloud对象时也要额外设置它的sortParticles属性为true。这样可以保证粒子在渲染之前沿着屏幕上的z轴排好序。

3.使用外部图片作为粒子的材质

和2相似,只不过这里我们在创建纹理时直接如下方式读取外部图片作为纹理:

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

如果我们想模拟下雨的效果,可在创建vertices时,给每个位置指定x和y方向的移动速度。

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);
                    var color = new THREE.Color(0x00ff00);
                    color.setHSL(color.getHSL().h, color.getHSL().s, Math.random() * color.getHSL().l);
                    geom.colors.push(color);
                }

在渲染的时候,可以没渲染一次,vertices根据速度移动一次。渲染代码如下:

if(controls.rotateSystem){
                    var vertices = cloud.geometry.vertices;
                    vertices.forEach(function(vector){
                        vector.y -= vector.velocityY;
                        vector.x += vector.velocityX;

                        if(vector.y <= 0) vector.y = 60;
                        if(vector.x <= -20 || vector.x >= 20) vector.x = -vector.x;
                    });
                }

另外,在创建PointCloudBasicMaterial时,可以指定depthWrite属性为false。该属性决定这个对象是否影响WebGL的深度缓存。设置为false,可以保证各个粒子系统之间不受影响。如果不设置如此,当一个粒子处在另外一个粒子的前面,而后者来自别的例子系统,有时候会看到纹理的黑色背景。

4.使用精灵THREE.Sprite

THREE.Sprite类可用于如下两种目的:

创建一个可以基于屏幕坐标移动、定位和缩放的对象。你可以用它来创建一个平视显示器(HUD),就像在三维场景上蒙了一层;

创建一个类似粒子的、可以在三维空间移动的对象,类似使用CanvasRenderer的THREE.Particle。三维场景中的精灵有事有称作广告牌。总是相面镜头,就像高速公路上的广告牌总是面向司机。

使用精灵,需要用到材质对象SpriteMaterial和网格对象Sprite。如果我们要实现一个外部图片作为纹理,像广告一样在屏幕底部左右移动。应该怎样实现?要使用精灵对象。摄像头一般使用正射投影。例如:

var cameraOrtho = new THREE.OrthographicCamera(0, window.innerWidth, window.innerHeight, 0, -10, 10);

left为0, right为window的width,top为window的height,bottom为0,near为-10, far为10。

下面的一个方法实现了如何创建Sprite网格对象:

function createSprite(size, transparent, opacity, color, spriteNumber){
                var spriteMaterial = new THREE.SpriteMaterial({
                    transparent: transparent,
                    opacity: opacity,
                    color: color,
                    map: getTexture()
                });

                spriteMaterial.map.offset = new THREE.Vector2(0.2 * spriteNumber, 0);
                spriteMaterial.map.repeat = new THREE.Vector2(1/5, 1);
                spriteMaterial.depthTest = false;

                spriteMaterial.blending = THREE.AdditiveBlending;

                var sprite = new THREE.Sprite(spriteMaterial);
                sprite.scale.set(size, size, size);
                sprite.position.set(100, 50, -10);
                sprite.velocityX = 5;

                sceneOrtho.add(sprite);
            }

首先创建了一个SpriteMaterial,传递的参数和创建粒子参数差不多。创建之后,需要设置map的一些属性,包括offset和repeat。由于我们使用的图片是一个横排包含了五个图标的压缩图片。所以需要指定偏移量offset。offset值从0到1。如果要显示第三个图标,那么x偏移量为0.2*2。y偏移量不变。repeat是指重复显示,x轴重复为1/5是指显示整个图片的1/5,y轴重复1次。设置SpriteMaterial,可以使Sprite和其他的粒子系统更好的融合显示。

接下来床架Sprite对象,设置它的scale和position属性,velocityX是我们自定义x轴移动速度的因子。最后,我们还得考虑如何渲染。代码如下:

function render(){
                stats.update();

                camera.position.y = Math.sin(step += 0.01) * 20;

                sceneOrtho.children.forEach(function(e){
                    if(e instanceof THREE.Sprite){
                        e.position.x = e.position.x + e.velocityX;
                        if(e.position.x > window.innerWidth){
                            e.velocityX = -5;
                            e.material.map.offset.set(1/5 *(controls.sprite % 4), 0);
                        }
                        if(e.position.x < 0){
                            e.velocityX = 5;
                        }
                    }
                });

                requestAnimationFrame(render);

                webGLRenderer.render(scene, camera);
                webGLRenderer.autoClear = false;
                webGLRenderer.render(sceneOrtho, cameraOrtho);
            }

camera是用来显示三维图形的摄像头,和我们显示精灵的sceneOrtho互不影响。我们遍历了sceneOrtho.children集合。如何元素时THREE.Sprite,我们重重新设置position.x,让Sprite动起来。

如果要让两个场景都渲染出来,我们需要设置WebGLRenderer的autoClear属性为false。

5.使用THREE.Sprite实现三维效果

要实现三维效果,可使用THREE.Object3D对象作为Sprite对象的集合。如下所示:

function createSprites(){
                group = new THREE.Object3D();
                var range = 200;
                for(var i = 0; i < 400; i++){
                    group.add(createSprite(10, false, 0.6, 0xffffff, i % 5, range));
                }
                scene.add(group);
            }

createSprite和4中的createSprite函数显示,只是多了一个range参数,限制坐标范围。

6.从高级几何体中创建粒子系统

粒子系统所渲染的粒子来自于几何体的顶点。如果我们提供一个复杂的几何体,诸如环面纽结或管道,我们可以基于这个几何体的顶点创建出一个粒子系统。

首先创建一个复杂几何体TorusKnotGeometry。创建代码如下:

var geom = new THREE.TorusKnotGeometry(
                            controls.radius,
                            controls.tube,
                            Math.round( controls.radialSegments),
                            Math.round(controls.tubularSegments),
                            Math.round(controls.p), Math.round(controls.q),
                            controls.heightScale
                        );

参数这里不再多说了。接下来基于这个几何体创建粒子对象PointCloud。代码如下:

function createPointCloud(goem){
            var material = new THREE.PointCloudMaterial({
                color: 0xffffff,
                size: 3,
                transparent: true,
                blending: THREE.AdditiveBlending,
                map: generateSprite()
            });

            var cloud = new THREE.PointCloud(goem, material);
            cloud.sortParticles = true;

            return cloud;
        }

和创建其他网格相似,字节把复杂几何体传递和材质传递给PointCloud的构造函数。这里的generateSprite函数是通过Canvas绘制一个高亮的纹理。纹理的绘制如下:

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;
        }

通过createradialGradirent函数创建一个从内向外的渐变效果,达到的效果就是一个比较明亮的发光点。运行结果如下:

时间: 2024-10-12 08:26:54

粒子和粒子系统的相关文章

Three.js开发指南---粒子和粒子系统(第七章)

使用粒子可以很容易的创建很多细小的物体,例如雨滴雪花等 本章主要内容: 1 使用ParticleBasicMaterial(基础粒子材质)来创建和设计粒子 2 使用ParticleSystem来创建一个粒子集合 3 使用已有的几何体来创建一个粒子系统 4 让粒子和粒子系统动起来 5 用纹理给粒子造型 6 使用ParticleCanvasMaterial在画布上为粒子造型 名称 描述 Sprite粒子 参数是material,生成的sprite可以设置position和scale等属性直接添加到场

【Unity】9.3 粒子系统生成器详解

分类:Unity.C#.VS2015 创建日期:2016-05-02 一.简介 上一节已经介绍过了在Unity 5.x中两种创建粒子效果的方式(方式1.方式2). 这一节我们主要学习第2种方式的基本概念和用法. Unity 5.x提供的新版粒子系统生成器(Particle System)也叫Shuriken粒子系统,该生成器采用模块化管理,个性化的粒子模块,配台粒子曲线编辑器,使用户很容易就能创作出各种缤纷复杂的粒子效果. 1.粒子系统检视器 粒子系统检视器 (Particle System I

Ogre参考手册(六)3.3 粒子

3.3 粒子Particle 粒子系统脚本可以作为模板,在运行时创建多个粒子系统 粒子系统脚本在初始化时加载,默认为所有公共资源位置(Root::addResourceLocation)下的’.particle’文件.你可以通过ParticleSystemManager::getSingleton().parseAllSources方法加载自定义扩展名的文件类型,或者通过ParticleSystemManager::getSingleton().parseScript解析单个脚本文件 示例: p

粒子系统主

粒子系统主要分为如下两种模式: 1.重力式粒子系统(CCParticleSystemPoint  ): 这种粒子存在重力,好像地球的万有引力一样,所有的粒子都会收到重力的约束,当然重力的大小是可以自己定义的 2.放射性粒子系统(CCParticleSystemQuad):: 这种粒子不存在重力,因此粒子好像都在空中,不再收到地球万有引力的作用 @1——根据 plist 文件创建粒子系统: [cpp] view plaincopyprint? CCParticleSystemQuad *emitt

粒子系统(一)

一.初识粒子系统 1.主模块 ● Duration: 持续时间.即把循环关了以后,持续多少秒停止发射粒子 ● Looping: 循环 ● Prewarm: 预热.粒子系统在游戏开始前就开始计算 ● Start Delay: 延迟.即延迟多少秒开始发射粒子 ● Start Lifetime: 初始化粒子寿命(生命周期) ? Constant: 常数 ? Curve: 曲线 ? Random Between Two Constants: 两个常数之间的随机数 ? Random Between Two

cocos2d-x 粒子效果

大规模运动的物体通常有两种方法实现 1,使用帧动画来模拟 2,粒子效果 粒子系统有CCParticleSystem类实现,CCParticleSystem实现了对粒子的控制与调度,对粒子的操作包括: 1,产生粒子 2,更新粒子状态 3,回收无效粒子 粒子系统继承自CCNode ,可以添加到其他节点之中 cocos2d-x内置了一些粒子效果如: - CCParticleSystem(所有粒子系统的父类) -- CCParticleSystemPoint.CCParticleSystemQuad (

粒子系统模块(Particle System Modules40)

粒子系统模块(忍者飞镖) 粒子系统(忍者飞镖)(Particle System (Shuriken)) 用模块描述粒子一段时间内的行为.此处记载了模块的详细说明.有关模块介绍,请参阅此页面. 初始化模块 该模块始终存在,无法删除或禁用.     持续时间 (Duration) 粒子系统 (Particle System) 发射粒子的持续时间. 循环 (Looping) 粒子系统 (Particle System) 是否循环. 预热 (Prewarm) 只可预热循环系统,这意味着,粒子系统 (Pa

粒子系统与雨的效果 (DirectX11 with Windows SDK)

前言 最近在学粒子系统,看这之前的<<3D图形编程基础 基于DirectX 11 >>是基于Direct SDK的,而DXSDK微软已经很久没有更新过了并且我学的DX11是用Windows SDK来实现. 顺手安利一波:我最近在学DX11 with WindowSDK 教程 博客地址: https://www.cnblogs.com/X-Jun/p/9028764.html 所以下面的都是基于这个教程和上面提到的那本书来写的,推荐看到教程17章和书里第15章之后再来看这篇博客,有助

QML官方教程——Using the Qt Quick Particle System

附网址:http://qt-project.org/doc/qt-5/qtquick-effects-particles.html Using the Qt Quick Particle System-- 使用Qt Quick粒子系统 所有粒子系统的类型都可以在QtQuick.Particles模块文档中找到. 注意想要使用粒子模块中的类型,你需要使用下面这个代码进行引入: import QtQuick.Particles 2.0 · The ParticleSystem 粒子系统包含4个主要的