大家好,本文介绍了“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端执行,只能串行计算,一共需要计算1500
1500次;

如果在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实现粒子效果”的更多相关文章

  1. WebGPU学习(九):学习“fractalCube”示例

    大家好,本文学习Chrome->webgpu-samplers->fractalCube示例. 上一篇博文: WebGPU学习(八):学习"texturedCube"示 ...

  2. WebGPU学习(十一):学习两个优化:“reuse render command buffer”和“dynamic uniform buffer offset”

    大家好,本文介绍了"reuse render command buffer"和"dynamic uniform buffer offset"这两个优化,以及Ch ...

  3. three.js粒子效果(分别基于CPU&GPU实现)

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

  4. cocos2d 粒子效果以及Particle Designer粒子工具的学习

    最近在学习cocos2d中的粒子效果吧,下面就把学到的和大家分享下吧! Now!我们先了解下类结构吧 -- CCParticleSystem(所有粒子系统的父类) -- CCParticleSyste ...

  5. iOS开发——UI进阶篇(十八)核心动画小例子,转盘(裁剪图片、自定义按钮、旋转)图片折叠、音量震动条、倒影、粒子效果

    一.转盘(裁剪图片.自定义按钮.旋转) 1.裁剪图片 将一张大图片裁剪为多张 // CGImageCreateWithImageInRect:用来裁剪图片 // image:需要裁剪的图片 // re ...

  6. cocos2d-x 3.1.1 学习笔记[16] Particle 粒子效果

    //plist文件中面有粒子效果的各种參数 //textureFileName相应着使用粒子的图片 auto particle = ParticleSystemQuad::create("s ...

  7. iOS学习笔记-084.粒子效果——路径移动

    https://blog.csdn.net/qiwenmingshiwo/article/details/75806637 粒子效果路径移动一说明1 效果2 步骤分析二代码1 VCViewh2 VCV ...

  8. 强化学习(十五) A3C

    在强化学习(十四) Actor-Critic中,我们讨论了Actor-Critic的算法流程,但是由于普通的Actor-Critic算法难以收敛,需要一些其他的优化.而Asynchronous Adv ...

  9. 对比深度学习十大框架:TensorFlow 并非最好?

    http://www.oschina.net/news/80593/deep-learning-frameworks-a-review-before-finishing-2016 TensorFlow ...

随机推荐

  1. bzoj4152 The Captain

    Description 给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用. Input 第一行包含一个正整数n(2 ...

  2. LeetCode110 Balanced Binary Tree

    Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced binary ...

  3. 【git基本操作】总结

    "git fetch GitLab: Your account has been blocked.fatal: Could not read from remote repository. ...

  4. SGU 107 987654321 problem【找规律】

    题目链接: http://acm.sgu.ru/problem.php?contest=0&problem=107 题意: 平方后几位为987654321的n位数有多少个 分析: 虽然说是水题 ...

  5. P4930「FJ2014集训」采药人的路径

    题目:P4930「FJ2014集训」采药人的路径 思路: 这篇不算题解,是让自己复习的,什么都没说清楚. 很久没有写点分治了,以前为了赶课件学的太急,板子都没打对就照着题解写题,导致学得很不扎实. 这 ...

  6. @atcoder - AGC035E@ Develop

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定初始集合为 1 ~ N 的全集,并给定一个 K. 每次对于当 ...

  7. vmware中centos、redhat桥接网络配置

    第一步 第二步 第三步 centos: redhat:

  8. POJ2663 Tri Tiling

    思路: 设a[i]为N=i时的方法数.i为奇数的时候肯定为0. 如果i为偶数,a[i]可以看成a[i-2]加上两个单位组成的,此时多出来的2单位有3种方法. 也可以看成a[i-4]加上四个单位组成的, ...

  9. Rikka with Mista 线段树求交点个数

    由于上下线段是不可能有交点的 可以先看左右线段树,按照y递增的顺序,对点进行排序. 升序构造,那么对于从某一点往下的射线,对于L,R进行区间覆盖,线段交点个数就是单点的被覆盖的次数. 降序构造,那么对 ...

  10. hdu 1596 find the safest road (变形SP && dij+heap)

    Problem - 1596 变形最短路问题,给出邻接矩阵,要求求出给定点对间安全率最大值. 这题可以用dijkstra+heap来做.对于每一个查询,做一次dij即可. 代码如下: #include ...