WebGPU学习(十):介绍“GPU实现粒子效果”
大家好,本文介绍了“GPU实现粒子效果”的基本思想,并推荐了相应的学习资料。
本文学习webgpu-samplers->computeBoids示例,它展示了如何用compute shader实现粒子效果,模拟鸟群的行为。
上一篇博文:
WebGPU学习(九):学习“fractalCube”示例
下一篇博文:
WebGPU学习(十一):学习两个优化:“reuse render command buffer”和“dynamic uniform buffer offset”
最终渲染结果:

为什么不在CPU端实现粒子效果?
虽然在CPU端实现会更灵活和可控,但如果粒子数量很大(如上百万),且与场景有交互,则最好在GPU端实现。
示例的实现思想
首先执行compute pass
代码如下:
const numParticles = 1500;
...
let t = 0;
return function frame() {
...
const commandEncoder = device.createCommandEncoder({});
{
const passEncoder = commandEncoder.beginComputePass();
passEncoder.setPipeline(computePipeline);
passEncoder.setBindGroup(0, particleBindGroups[t % 2]);
passEncoder.dispatch(numParticles);
passEncoder.endPass();
}
...
++t;
}
我们对这个pass进行分析:
particleBindGroups包含两个storage buffer:ParticlesA和ParticlesB
ParticlesA存储了上一帧所有粒子的数据。compute shader首先读取它,然后计算出下一帧所有粒子的数据,最好写到ParticlesB中。这样就打了一个ping-pong操作;
注:storage buffer在shader中可被读或写,而uniform buffer、vertex buffer等在shader中只能被读
dispatch到1500个instance,每个instance执行一次compute shader
compute shader计算每个粒子的数据时,需要遍历其它的所有粒子,计算相互的交互作用。
一共有1500个粒子,共需要计算15001500次。
如果在CPU端执行,只能串行计算,一共需要计算15001500次;
如果在GPU端执行,GPU有1500个instance,每个instance并行地计算1500次,因此一共只需要计算1500次,大大提高了效率。
然后执行render pass
代码如下:
const numParticles = 1500;
...
const renderPipeline = device.createRenderPipeline({
...
vertexState: {
vertexBuffers: [{
// instanced particles buffer
arrayStride: 4 * 4,
stepMode: "instance",
attributes: [{
// instance position
shaderLocation: 0,
offset: 0,
format: "float2"
}, {
// instance velocity
shaderLocation: 1,
offset: 2 * 4,
format: "float2"
}],
}, {
// vertex buffer
arrayStride: 2 * 4,
stepMode: "vertex",
attributes: [{
// vertex positions
shaderLocation: 2,
offset: 0,
format: "float2"
}],
}],
},
...
});
...
const vertexBufferData = new Float32Array([-0.01, -0.02, 0.01, -0.02, 0.00, 0.02]);
const verticesBuffer = device.createBuffer({
size: vertexBufferData.byteLength,
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
});
verticesBuffer.setSubData(0, vertexBufferData);
...
return function frame() {
...
const commandEncoder = device.createCommandEncoder({});
...
{
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
passEncoder.setPipeline(renderPipeline);
//ParticlesB使用“instance”的stepMode,被设置到第一个vertex buffer中
passEncoder.setVertexBuffer(0, particleBuffers[(t + 1) % 2]);
//vertices buffer(包含3个顶点数据,每个顶点数据包含x坐标和y坐标)使用“vertex”的stepMode,被设置到第二个vertex buffer中
passEncoder.setVertexBuffer(1, verticesBuffer);
//draw一次,绘制1500个实例(使用ParticlesB的数据),其中每个实例有3个顶点(使用vertices buffer的数据)
//注:每个粒子作为一个实例,由包含3个顶点的三角形组成
passEncoder.draw(3, numParticles, 0, 0);
passEncoder.endPass();
}
...
}
推荐学习资料
大家可以参考WebGPU-8,来学习示例的具体的代码。
虽然该文对应的示例代码的版本比较老(如它的示例中是1000个粒子,而不是1500个粒子),但与本文对应的最新版本基本上相同,而且它对示例代码分析得比较详细,所以推荐大家学习。
另外,大家可以通过Get started with GPU Compute on the Web,学习如何使用compute shader计算矩阵运算。
参考资料
WebGPU-8
webgpu-samplers Github Repo
WebGPU学习(十):介绍“GPU实现粒子效果”的更多相关文章
- WebGPU学习(九):学习“fractalCube”示例
大家好,本文学习Chrome->webgpu-samplers->fractalCube示例. 上一篇博文: WebGPU学习(八):学习"texturedCube"示 ...
- WebGPU学习(十一):学习两个优化:“reuse render command buffer”和“dynamic uniform buffer offset”
大家好,本文介绍了"reuse render command buffer"和"dynamic uniform buffer offset"这两个优化,以及Ch ...
- three.js粒子效果(分别基于CPU&GPU实现)
前段时间做了一个基于CPU和GPU对比的粒子效果丢在学习WebGL的群里,技术上没有多作讲解,有同学反馈看不太懂GPU版本,干脆开一篇文章,重点讲解基于GPU开发的版本. 一.概况 废话不多说,先丢上 ...
- cocos2d 粒子效果以及Particle Designer粒子工具的学习
最近在学习cocos2d中的粒子效果吧,下面就把学到的和大家分享下吧! Now!我们先了解下类结构吧 -- CCParticleSystem(所有粒子系统的父类) -- CCParticleSyste ...
- iOS开发——UI进阶篇(十八)核心动画小例子,转盘(裁剪图片、自定义按钮、旋转)图片折叠、音量震动条、倒影、粒子效果
一.转盘(裁剪图片.自定义按钮.旋转) 1.裁剪图片 将一张大图片裁剪为多张 // CGImageCreateWithImageInRect:用来裁剪图片 // image:需要裁剪的图片 // re ...
- cocos2d-x 3.1.1 学习笔记[16] Particle 粒子效果
//plist文件中面有粒子效果的各种參数 //textureFileName相应着使用粒子的图片 auto particle = ParticleSystemQuad::create("s ...
- iOS学习笔记-084.粒子效果——路径移动
https://blog.csdn.net/qiwenmingshiwo/article/details/75806637 粒子效果路径移动一说明1 效果2 步骤分析二代码1 VCViewh2 VCV ...
- 强化学习(十五) A3C
在强化学习(十四) Actor-Critic中,我们讨论了Actor-Critic的算法流程,但是由于普通的Actor-Critic算法难以收敛,需要一些其他的优化.而Asynchronous Adv ...
- 对比深度学习十大框架:TensorFlow 并非最好?
http://www.oschina.net/news/80593/deep-learning-frameworks-a-review-before-finishing-2016 TensorFlow ...
随机推荐
- github.com访问慢解决
修改hosts(HOSTS文件路径:C:\Windows\System32\drivers\etc\hosts) 1.打开Dns查询 - 站长工具 http://tool.chinaz.com/dn ...
- win10 uwp 使用动画修改 Grid column 的宽度
今天 wurstmitbrot 问如何通过动画修改 Grid 的 column ,虽然 column 是一个依赖属性,可以绑定,但是做出动画还是比较难的. 本文告诉大家如何对 Grid 做动画. 首先 ...
- Flask学习之一 hello world
本人电脑环境: 系统:linux
- shell不排序去重
一条命令搞定: awk '!a[$0]++' file 如果是第一次出现a[$0]++的值为0(假),而!a[$0]++的值就为1(真),之后就执行print $0 第二次或者两次以上的出现a[$ ...
- python----操作Memcache、redis、RabbitMQ、SQLAlchemy
操作本质都是通过socket发送命令 Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次 ...
- Oracle中组合索引的使用详解(转)
在Oracle中可以创建组合索引,即同时包含两个或两个以上列的索引.在组合索引的使用方面,Oracle有以下特点: 1. 当使用基于规则的优化器(RBO)时,只有当组合索引的前导列出现在SQL语句的w ...
- @bzoj - 2388@ 旅行规划
目录 @description@ @solution@ @accepted code@ @details@ @description@ 请你维护一个序列,支持两种操作: (1)某个区间 [x, y] ...
- @codechef - SERSUM@ Series Sum
目录 @description@ @solution@ @part - 1@ @part - 2@ @part - 3@ @accepted code@ @details@ @description@ ...
- 认识一下ES6的Reflect和Proxy
Reflect Reflect要替代Object的很多方法, 将Object对象一些明显属于言内部的方法放到了Reflect对象上,有13个方法 Reflect.apply(target, thisA ...
- 创建JAVASCRIPT对象3种方法
创建JAVASCRIPT对象3种方法 方法一:直接定义并创建对象实例 var obj = new Object(); //创建对象实例 //添加属性obj.num = 5; //添加属性 o ...