前段时间做了一个基于CPU和GPU对比的粒子效果丢在学习WebGL的群里,技术上没有多作讲解,有同学反馈看不太懂GPU版本,干脆开一篇文章,重点讲解基于GPU开发的版本。

一、概况

废话不多说,先丢上demo,用移动设备更能明显感觉性能差异。

维护粒子位移颜色尺寸
GPU版本  CPU版本

维护粒子位移
GPU版本  CPU版本

 

结论:
同时需要维护多种粒子特征变化时,GPU有明显优势。
只是维护粒子位移时,GPU版本稍流畅,但优势并不明显。
当然,这还得具体到设备,一些中低端Android机器,GPU太渣,不如CPU计算。

二、技术实现

three.js中,粒子效果的实现方式大概分为三种:
1、Javascript直接计算粒子的状态变化,即基于CPU实现;
2、Javascript通知顶点着色器粒子的生命周期,由顶点着色器运行,即基于GPU实现;
3、粒子生成与状态维护全部由片元着色器负责,即屏幕特效,同样是基于GPU中实现。
第3种方式本文暂不介绍。

2.1、基于CPU实现

维护位移、颜色、尺寸:
http://tgideas.qq.com/2017/three/shader/particle-gpu/cpu.html维护位移:
http://tgideas.qq.com/2017/three/shader/particle-gpu/gpu-position.html

步骤1&2:
首先加载由三维软件制作的几何体,然后生成粒子系统 。

var material = new THREE.PointsMaterial({size:4, color:0xff0000});
var particleSystem = new THREE.Points(geometry , material);

从代码中可以看出,材质是针对整介粒子系统设置的,所以只能维护粒子位移。
如果要维护粒子颜色、尺寸呢?
我们必须为每个粒子设置不同的材质,由此也造成不小的性能损耗 。
 
步骤3:
使用Tween修改所有顶点位置。

var tween = new TWEEN.Tween(pos).to({val: 0}, 2000).easing(TWEEN.Easing.Quadratic.InOut).delay(1000).onUpdate(callback);
function callback(){
var val = this.val;
var particles = particleSystem.geometry.vertices;
for(var i = 0; i < particles.length; i++) {
var pos = particles[i];
pos.x = position1[i].x * val + position2[i].x * (1-val);
pos.y = position1[i].y * val + position2[i].y * (1-val);
pos.z = position1[i].z * val + position2[i].z * (1-val);
}
particleSystem.geometry.verticesNeedUpdate = true;
}

从代码中可以看出,粒子的状态都是通过Javascript,由CPU来计算。

2.2、基于GPU实现

维护粒子位移、颜色、尺寸:
http://tgideas.qq.com/2017/three/shader/particle-gpu/gpu.html

对比CPU实现流程图,我们会发现,Tween并不直接计算所有顶点位置,而是只通知动画运行时间,由顶点着色器来完成具体运算。
既然运算部分在顶点着色器,那么,需要我们自己书写着色器(opengl es),所以我们选用three.js中的ShaderMaterial。

步骤1:
首先生成粒子系统:

var uniforms = {
texture:{value: new THREE.TextureLoader().load( "dot.png")},
val: {value: 1.0}
};
var shaderMaterial = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: document.getElementById('vertexshader').textContent,
fragmentShader: document.getElementById('fragmentshader').textContent,
blending: THREE.AdditiveBlending,
depthTest: false,
transparent: true
});
particleSystem = new THREE.Points(moreObj, shaderMaterial);

uniforms是连接javascript与着色器的通道。
uniforms.val 即由tween来维护的动画运行值。
vertexShader和fragmentShader,即我们要定义的顶点着色器,和片元着色器,它们负责具体的粒子状态的运算,我们定义在网页中。

步骤2:
定义顶点着色器:

attribute float size; // 粒子尺寸
attribute vec3 position2; // 目标顶点位置
uniform float val; // 动画运行时间
varying vec3 vPos; // 将顶点位置传输给片元着色器 void main() {
// 计算粒子位置
vPos.x = position.x * val + position2.x * (1.-val);
vPos.y = position.y* val + position2.y * (1.-val);
vPos.z = position.z* val + position2.z * (1.-val);
// 坐标转换
vec4 mvPosition = modelViewMatrix * vec4( vPos, 1.0 );
gl_PointSize = size * ( 300.0 / -mvPosition.z );
gl_Position = projectionMatrix * mvPosition; }

three.js内置,自动传递给顶点着色器的变量:
attribute position - 顶点坐标
mat4 modelViewMatrix - 模型+视图矩阵
mat4 projectionMatrix - 投影矩阵

定义片元着色器:

uniform sampler2D texture;
varying vec3 vPos; void main() {
// 计算粒子颜色,通过位置
vec3 vColor = vec3(1.0, 0., 0.);
vColor.r = vPos.z/50.;
vColor.g = vPos.y/50.;
vColor.b = vPos.x/50.; gl_FragColor = vec4(vColor, 1.0 );
// 顶点贴图
gl_FragColor = gl_FragColor * texture2D( texture, gl_PointCoord ); }

  

步骤3:
负责维护粒子运行时间:

tween = new TWEEN.Tween(pos).to({val: 0}, 2000).onUpdate(callback);
function callback(){
particleSystem.material.uniforms.val.value = this.val;
}

三、延伸阅读

类THREE.Points做了什么?
其实真没干什么,主要是申明它的type是Points。
当我们执行渲染时,WebGL会绘制Point,即调用gl.drawArrays(gl.POINTS…
而通常,比如type为Mesh时,three.js会调用gl.drawArrays(gl.TRIANGLES…

类THREE.PointsMaterial做了什么?
同样,点材质也是three.js最简单的类之一,相对于基类Material,它多做的事情只是传递了size,即点的尺寸这个值。

three.js粒子效果(分别基于CPU&GPU实现)的更多相关文章

  1. Three.js粒子特效,shader渲染初探(一篇非常详细的介绍)

    Three.js粒子特效,shader渲染初探 转载来源:https://juejin.im/post/5b0ace63f265da0db479270a 这大概是个序 关于Three.js,网上有不多 ...

  2. WebGPU学习(十):介绍“GPU实现粒子效果”

    大家好,本文介绍了"GPU实现粒子效果"的基本思想,并推荐了相应的学习资料. 本文学习webgpu-samplers->computeBoids示例,它展示了如何用compu ...

  3. 如何在《救赎之路》中使用CPU粒子效果

    Unreal游戏引擎4.19版本的发布,可以使得游戏可以更好地利用Intel多核心处理器的性能,以提供更精彩的游戏体验.这里以<救赎之路>这款优秀的国产独立游戏为例说明如何在游戏中使用CP ...

  4. 基于HTML5 Canvas粒子效果文字动画特效

    之前我们分享过很多超酷的文字特效,其中也有利用HTML5和CSS3的.今天我们要来分享一款基于HTML5 Canvas的文字特效,输入框中输入想要展示的文字,回车后即可在canvas上绘制出粒子效果的 ...

  5. 基于HTML5 Canvas生成粒子效果的人物头像

    前面我们分享过一个HTML5 Canvas实现的图像马赛克模糊效果,HTML5处理图片真的非常简单.今天我们要再利用HTML5 Canvas实现一个粒子效果的人物头像,你可以任意选择一张头像图片,接下 ...

  6. [转帖]双剑合璧:CPU+GPU异构计算完全解析

    引用自:http://tech.sina.com.cn/mobile/n/2011-06-20/18371792199.shtml 这篇文章写的深入浅出,把异构计算的思想和行业趋势描述的非常清楚,难得 ...

  7. canvas实现的粒子效果

    前言:我的这个share很简单,没什么技术水准,主要是我自己觉得canvas这个标签很cool!,简单实用又能装X,而且又能实现很多看起来很炫的东西. 一 关于canvas <canvas> ...

  8. 简直要逆天!超炫的 HTML5 粒子效果进度条

    我喜欢粒子效果作品,特别是那些能够应用于实际的,例如这个由 Jack Rugile 基于 HTML5 Cavnas 编写的进度条效果.看着这么炫的 Loading 效果,即使让我多等一会也无妨:)你呢 ...

  9. CodePen 作品秀:Canvas 粒子效果文本动画

    作品名称——Shape Shifter,基于 Canvas 的粒子图形变换实验.在页面下方的输入框输入文本,上面就会进行变换出对应的粒子效果文本动画. CodePen 作品秀系列向大家展示来自 Cod ...

随机推荐

  1. 第六章:3D向量类

    第一节:类接口的设计 1.好的类在设计之前首先要回答下列问题:“这些类将包含哪些数据?”,“这个类将提供什么样的操作?”,“在哪些数据上执行操作?”. 我们已经知道我们要设计的是3D向量类,用来存储x ...

  2. 机器学习:Python实现单层Rosenblatt感知器

    如果对Rosenblatt感知器不了解,可以先查看下相关定义,然后对照下面的代码来理解. 代码中详细解释了各步骤的含义,有些涉及到了数学公式的解释. 这篇文章是以理解Rosenblatt感知器的原理为 ...

  3. 老李推荐:第8章6节《MonkeyRunner源码剖析》MonkeyRunner启动运行过程-启动Monkey 4

    在获得比对设备序列号后,findAttachedDevice就会跟提供的序列号进行比对,如果吻合就返回给调用者” 代码8-6-3 AdbBackend - waitForConnection”了.而A ...

  4. llinux svn安装

    1,安装SVN服务端 直接用apt-get或yum安装subversion即可(当然也可以自己去官方下载安装) [plain] view plain copy print? sudo apt-get  ...

  5. linux常用脚本

    转载于http://justcoding.iteye.com/blog/1943504 我们在运维中,尤其是linux运维,都知道脚本的重要性,脚本会让我们的 运维事半功倍,所以学会写脚本是我们每个l ...

  6. java线程池ThreadPoolExector源码分析

    java线程池ThreadPoolExector源码分析 今天研究了下ThreadPoolExector源码,大致上总结了以下几点跟大家分享下: 一.ThreadPoolExector几个主要变量 先 ...

  7. add spring-boot-modules to maven project

    spring boot 项目中 多modules parent 冲突 在IDEAJ 中,如果建立多多modules 项目,pom文件应该是这样: <groupId>cn.ifengkou& ...

  8. 【web】之 jquery上传插件的Plupload的使用

    首先下载plupload->http://www.plupload.com 因为Plupload可配置参数比较多,所以这里讲解最常用的,结合jquery-ui展示的界面!如下: Plupload ...

  9. Tomcat access log配置

    在tomcat的access中打印出请求的情况可以帮助我们分析问题,通常比较关注的有访问IP.线程号.访问url.返回状态码.访问时间.持续时间. 在Spring boot中使用了内嵌的tomcat, ...

  10. 点击按钮,缩放图片(img.width、img.style.width、img.offsetWidth)

    前几天在慕课网上看到一个关于图片缩放的教学视频,因为当时对老师使用img.width,而不是使用img.style.width而感到奇怪,所以周末得空了,想来自己试着写出来,相关视频网址如下:http ...