HTML5技术

three.js粒子效果(分别基于CPUGPU实现) - cnwander

字号+ 作者:H5之家 来源:H5之家 2017-05-18 13:00 我要评论( )

前段时间做了一个基于CPU和GPU对比的粒子效果丢在学习WebGL的群里,技术上没有多作讲解,有同学反馈看不太懂GPU版本,干脆开一篇文章,重点讲解基于GPU开发的版本。 一、概况 废话不多说,先丢上demo,用移动设备更能明显感觉性能差异。 维护粒子位移、颜色

前段时间做了一个基于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实现

维护位移、颜色、尺寸:

维护位移:

步骤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实现

维护粒子位移、颜色、尺寸:

对比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,即点的尺寸这个值。

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • Css3中拖拽效果的实例(带有注释~欢迎指教) - 一混五六年

    Css3中拖拽效果的实例(带有注释~欢迎指教) - 一混五六年

    2017-03-04 10:00

  • c3和js写的切割轮播图 喜欢宋仲基的妹子汉子们来,观看效果需要引入jQuery^^ - 柿子橙

    c3和js写的切割轮播图 喜欢宋仲基的妹子汉子们来,观看效果需要引入j

    2017-02-26 14:01

  • 10种非常值得收藏的csshover效果 - 张三木

    10种非常值得收藏的csshover效果 - 张三木

    2017-02-16 12:01

  • 纯CSS3实现不错的表单验证效果 - 绿岛之北

    纯CSS3实现不错的表单验证效果 - 绿岛之北

    2017-01-18 12:00

网友点评
y