游戏引擎的cpu/gpu粒子系统设计思想

开篇

网上有很多篇粒子系统源码解析,但是只是简单的接口罗列,没有从最原理出发去讲清楚粒子系统的来龙去脉,我将从粒子系统的本质去讲清楚它的设计理念,当理解了它的理念以后,很多粒子遇到的问题就会迎刃解决了,这篇文章主讲粒子的实现和一些框架级的优化方式,其实有很多优化细节就不赘述

粒子系统的设计思想

在早期游戏发展的时候,有一些粒子效果是实现一些鼠标特效的,比如《刀剑封魔录》中滑动鼠标后,鼠标本身就会作为一个粒子发射器,在鼠标拖动后,会产生很多粒子并随着时间消亡,这就是最早的粒子系统模型

 在早期的桌面系统中实现的粒子全是用cpu在屏幕上渲染的,如果需要世界中的3D粒子,则会将世界坐标转换为屏幕坐标,在屏幕指定位置渲染个粒子,而且这个粒子是每一帧去更新的

我给一个imgui类型渲染系统的粒子伪代码方便大家去理解,每一帧都去更新所有粒子的信息,当然现代游戏引擎粒子实现也类似于此

//定义粒子结构
struct particle{float x;float y;image  img;
}//定义粒子集合
vector<particle> particles//设置粒子位置
void setparticlepositon(particle &p)
{p.x++;p.y++;
}tick::update()  //每一帧更行所有需要渲染的信息
{for(auto i : particles){    setparticlepositon(i);//循环更新粒子位置draw(i);//循环更新粒子绘制}
}

更复杂的话就是定义每个粒子的周期,并定义粒子发射器,另外可以在setparticlepositon中设置更复杂的更新条件

class ParticleEmitter{
protected:void Tick() {Spawn();                //生成阶段:创建新粒子UpdateAndRecycle();     //更新阶段:更新每个粒子的状态数据并回收已死亡的粒子Render();               //渲染阶段:使用粒子渲染器将粒子效果渲染出来}
private:vector<Particle> Particles;};

万变不离其宗,都是源于这个思想

既然有大量相同的粒子,那么结合现代游戏引擎的特性,可以用到实例化(Instancing),将相同的mesh和材质用一套,大大减少了数据量,另外也可以用GPU粒子优化

使用几何着色器做优化

Nvidia在2006年的GeForce 8系列中出了DirectX 10.0,并推出了几何着色器

简单说,就是几何着色器可以把单个顶点扩充成多个顶点,如果粒子的mesh都一样的话,只需要从顶点着色器中传入的单个顶点和扩展规则,就可以生成想渲染的粒子mesh,而并不需要每回传入大量的顶点了

使用之前:

可见每个粒子需要传入五个位置然后生成五角星 

使用之后:

 想渲染一个五角星只要传入一个顶点,就可以用几何着色器扩充为五角星,大大减少了draw所占的带宽

使用SMID粒子做的优化

关于smid的介绍我前面有篇文章可以看看,这里就不赘述它的原理了

(1条消息) 使用SIMD指令加速计算_星空_MAX的博客-CSDN博客

这种情况试用语cpu对大量粒子计算和更新的情况

unreal引擎的nigara和chaos就是用这种缓存友好的内存布局,和unity的ECS架构原理一样

 写个大概的数据结构参考一下:


//定义粒子的组件集合
vector<particle> particlesx;
vector<particle> particlesy;//设置粒子x位置
void setparticlepositonx(particlex &px)
{px++;
}
//设置粒子y位置
void setparticlepositonx(particley &py)
{py++;
}//定义粒子和组件集合
class particle
{vector<particle> *particlesx = particlesx;vector<particle> *particlesx = particlesy;
}//定义粒子集合
vector<particle> particles;tick::update()  //每一帧更行所有需要渲染的信息
{for(auto i : particlesx){    setparticlepositonx(i);//循环更新粒子位置	}for(auto i : particlesy){    setparticlepositony(i);//循环更新粒子位置	}for(auto i : particles){    draw(i);//循环更新粒子绘制}
}

使用GPU粒子做的优化

CPU粒子设计上和我上一节提到的东西大同小异,不过原来的draw是CPU去绘制,现代会把这个内容送到GPU,会调用一次drawcall,但是粒子的消耗消耗会非常大,粒子渲染的数量非常有限

这时候能不能把把粒子更新的逻辑放在gpu里面呢,当然可以了

同样是DirectX 10.0引用了Stream Output的新特性,在OpenGL3.0中也加入了这种特性,不过在OpenGL称为Transform Feedback,在顶点着色器或者几何着色器之后,可以把顶点数据缓存到这个结构中,而这个结构在gpu中,这样每回就可以根据这个信息去更新顶点信息,重新传入顶点着色器中去做渲染

整体流程如下:

 这时候就会发现GPU和cpu可以不进行数据传输了,粒子完成自我更新,大大减少了传输量和cpu的计算负担

带来的问题

如果用gpu粒子的话无法实时计算出剔除范围了,因为剔除步骤在传入顶点着色器之前,所以一开始就需要传入效果的bounds,并预估出粒子的最大范围,否则可能出现特效消失的问题

结尾

粒子系统还有其他很多部分,可做优化的部分非常多,我这里只介绍了一些粒子系统设计的基础思想,其他更全面的内容网上很多,就不赘述了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/13478.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

3 STM32标准库函数 之 窗口看门狗(WWDG)所有函数的介绍及使用

3 STM32标准库函数 之 窗口看门狗&#xff08;WWDG&#xff09;所有函数的介绍及使用 1. 图片有格式2 文字无格式三 库函数之窗口看门狗&#xff08;WWDG&#xff09;所有函数的介绍及使用前言一、IWDG库函数固件库函数预览1.1 函 数 IWDG_WriteAccessCmd1.1.1 IWDG_WriteAcces…

IDEA完全免费AI辅助编程插件BITO-GPT4安装及中文国产化设置

打开IDEA的plugins 搜索BITO&#xff1a; 下载后右边工具栏上会出现BITO的小蓝标&#xff0c;这样就可以使用了但是里面是全英文的 设置中文 1.打开BITO点击右上角设置 点击里面的Settings 进入BITO的Web网页 右边这个改成中文&#xff1a; 这样回到IDEA AI就会生成中…

0126 线性表

目录 2.线性表 2.1线性表的定义和基本概念 2.1部分习题 2.2线性表的顺序表示 2.2部分习题 2.3线性表的链式表示 2.3部分习题 2.线性表 2.1线性表的定义和基本概念 2.1部分习题 1.线性表是具有n个&#xff08;&#xff09;的有限序列 A.数据表 B.字符 C.…

【计算机组成原理总结】

第一章计算机系统概述 第二章数据的表示与运算 第三章存储系统 第四章 指令系统 第五章 中央处理器 第六章 总线 第七章 输入输出设备

LVS-DR排错思路

一.LVS-DR实验排错思路 1.案例架构图 DR服务器&#xff1a;192.168.27.11 web服务器1&#xff1a;192.168.27.12 web服务器2&#xff1a;192.168.27.13 vip&#xff1a;192.168.27.180 客户端&#xff1a;192.168.27.2 1&#xff1a;配置负载调度器&#xff1a;&#xff…

前端学习——HTML5

新增语义化标签 新增布局标签 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content&qu…

LVS+Keepalived 群集及搭建

文章目录 一.keepalived 概述1.keepalived服务重要功能1.1 管理LvS负载均衡器软件1.2 支持故障自动切换 (failover)1.3 实现LVS集中节点的健康检查 (health checking)1.4 实现LVS负载调度器 节点服务器的高可用性 (HA) 2. keepalived 高可用故障切换转移原理及VRRP通信原理3.ke…

Flink的状态是否支持任务间共享

背景&#xff1a; 在日常编写代码的过程中&#xff0c;我们经常会在方法内部new很多的其他类对象来进行编码工作&#xff0c;那么对于这种情况怎么让new出来的对象是一个我们特意创建出来的一个mock实例&#xff0c;从而让我们能完全控制new出来的对象的所有行为呢&#xff1f…

后端开发常见技术场景

文章目录 1、单点登录这块怎么实现的1.1 概述1.2 JWT解决单点登录1.3 回答要点 2、权限认证是如何实现的2.1 概述2.2 RBAC权限模型2.3 回答要点 3、上传数据的安全性你们怎么控制&#xff1f;3.1 概述3.2 对称加密3.3 非对称加密3.4 回答要点 4、你负责项目的时候遇到了哪些比较…

css:鼠标经过el-dropdown 组件上会出现一个蓝色的小框

问题描述 效果如下&#xff0c;原以为是浏览器的bug&#xff0c;升级后就好了&#xff0c;没想到一直有这个问题 页面刷新后&#xff0c;鼠标经过el-dropdown 组件上会出现一个蓝色的小框 原因 浏览器默认有一个样式&#xff0c;加了一个边框 :focus-visible {outline: -we…

RabbitMQ

一、初识 MQ 1. 同步通讯 时效性强&#xff0c;立即获取结果 微服务间基于 Feign 的调用就属于同步 方式&#xff0c;存在一些问题&#xff1a; ① 耦合度高 ② 性能和吞吐能力不如异步 ③ 额外资源消耗 ④ 级联失败问题 2. 异步通讯 异步调用常见实现就是事件驱动模式 优点…

IDEA+spring boot+mybatis+spring mvc+bootstrap+Mysql停车位管理系统源码

IDEAJavaSpring BootMyBatisshiroLayuiMysql停车位管理系统源码 一、系统介绍1.环境配置 二、系统展示1.登录2.注册3.个人信息4.修改密码5.我的订单6.我的留言7.查车位8.管理员登录9.公告列表10.车位列表11. 订单列表12. 积分排行13. 留言列表14.管理员列表15. 用户列表16.修改…