当前位置: 首页 > news >正文

游戏引擎中的粒子系统

一、粒子基础

粒子系统里有各种发射器(emitter),发射器发射粒子(particle)。

粒子是拥有位置、速度、大小尺寸、颜色和生命周期的3D模型。
粒子的生命周期中,包含产生(Spawn)、与环境交互以及死亡。设计中很重要的一点是要控制场景中粒子的数量。

粒子发射器有三个作用:

  • 具体规定粒子产生的规则
  • 具体规定粒子模拟的逻辑
  • 描述如何渲染粒子
    在这里插入图片描述

粒子系统经常有不止一类发射器,比如火堆这个系统中有火焰、火星和烟雾三种发射器

在这里插入图片描述
关于粒子的产生,位置上可以分为单点产生、在区域上产生和在mesh上产生三类;
在这里插入图片描述

在模式上也可以分为连续产生和间歇性产生等
在这里插入图片描述

粒子的模拟:

1、常规的受力

在这里插入图片描述
2、粒子如何变动,一般使用显式欧拉法就行。受力状态决定加速度,决定速度的更新,速度决定位置的更新
3、模拟时,除了重力,还可以加上粒子的旋转、颜色的变化、大小的变化以及和环境的碰撞等

粒子的形状一般有三类:

1、Billboard Particle。这种粒子由一些面片构成,其形状其实只有一面,但它始终保持面向摄像头,所以看起来是一个3D的粒子。如果这个particle比较小就无所谓,但如果比较大的时候建议是其形状也会随时间而变化,不然比较假

2、Mesh Particle。要模拟散的碎的粒子时往往直接用3D mesh当做粒子,然后给它们设置各种不同类别的随机属性,从而艺术家也更容易实现想要的效果

3、Ribbon Particle。样条形粒子,其实粒子是样条上的控制点,然后通过连接获得完整的条状。往往使用在比如武器挥舞的残影之类的地方。在控制点连接过程中需要插值,不然每一个连接点间的形状是不连续的(看起来像一个个四边形拼在一起)。一般使用向心的catmull-rom插值(在粒子间加入额外的分割块且数量可自己选定,不过对CPU要求会变高)
在这里插入图片描述

二、粒子渲染

2.1 粒子排序

常见的透明融合问题在粒子渲染处也需要解决,排序一定要从远到近。

粒子排序有两种方式,一种是全局法,完全按粒子个体来排序,很精准但消耗巨大;另一种是按层级,从简单到复杂的排序是依照粒子系统排序、依照emitter排序和在emitter之内排序。
具体来说,如果依照粒子排序,则按粒子离相机的距离排序;如果按系统或发射器排序,则按Bounding box排序。
在这里插入图片描述

2.2 Low-Resolution

另一方面,粒子渲染会带来巨大消耗的原因是“全分辨率粒子”。当我们渲染普通场景时,由于Z-buffer的帮助,其实只需要渲染接触到的场景的第一个物体(其他被遮挡不需要渲染),但粒子效果有时候(最差情况下)会在一瞬间产生叠满整个分辨率好多层的粒子,而且它们不存在完全遮挡关系,所以相当于一下子要进行超大量的渲染。

overdraw:同一个像素被绘制了多少次。

解决方案是:
降分辨率下采样进行粒子的渲染,此时与原场景无关,获得粒子的颜色和透明度alpha。然后再上采样融合到原场景中。
在这里插入图片描述

三、GPU粒子

从上面的所述可以看到,粒子计算功耗很大,所以放到GPU中是一个解决方案,原因有三:

  • 高并行运算,适合大量粒子的模拟计算
  • 可以释放CPU功耗来进行游戏本身计算
  • 方便获得深度缓冲来做遮挡判断

但有一个难点是粒子拥有生命周期,会不断产生消失,所以如何在GPU中实现粒子是一个难点。

解决方案:

Intial State
先建立一个粒子池,设计一个数据结构,设定系统包含的粒子总数量,每个粒子的位置、速度等。再有两个list,一个是Dead List,记录当前死亡的粒子,初始时包含所有粒子序号,还有一个是alive list,记录当前活着的粒子,初始时为空。
比如emitter发射了5个粒子,则从池子结尾取5个粒子(序号)放入alive list,同时把dead list的后5个序号清空。
在这里插入图片描述

Simulate
当时间跳转到下一次tick时,会新建一个alive list1,并依序检索alive list中的粒子,如果发现某个粒子死亡了,就会把这个粒子序号移到死亡列表中,并且在渲染时也跳过这个粒子,如果仍存活就照抄到alive list1中。
这个操作因为compute shader的发明变得容易,因为compute shader可以进行原子级操作。
同时,在更新完活着的粒子之后,还可以利用GPU进行frustum culling视角剔除(针对活着的粒子),并且计算它们的距离,写入距离buffer。
在这里插入图片描述

Sort, Render and Swap Alive Lists

接着,还需要进行排序、渲染和交换alive list:
1、排序。根据距离buffer对活着的剔除后的粒子排序
2、渲染。对排序后的粒子渲染
3、交换。交换alive list1和alive list,更新存活列表。
在这里插入图片描述

具体来说排序。GPU的排序类似归并算法,复杂度为nlogn。采取的方式是针对目标序列(排序后)的每一个位置设置一个线程,考虑它应该从两个列表中哪个取得。这样做会比每个源列表位置一个线程去考虑插入到哪里更简单,因为后者会让“写过程”跳来跳去不连续 。

同时利用深度缓冲还可以进行碰撞的检测,具体:
1、把粒子的当前位置投影到上一帧的屏幕空间纹理坐标(相当于投影到上一帧相机坐标系?)
2、读取上一帧的深度纹理图中的深度值
3、检查1和2中的深度值,判断是否碰撞了但又没完全穿过去(厚度值会被用到)
4、如果碰撞发生了,就计算碰撞表面法向和粒子反弹的方向
在这里插入图片描述

四、粒子应用

直接利用粒子来模拟物体,比如鸟群、大地图下行走的路人(因为很小),此时同样也有骨骼,但基本上每个顶点只受一个节点限制(简化版人体)。

在这种情况下,我们可以把原本一个例子的加速等行为换成更复杂的人体姿态动作,相当于每个particle设置了一个状态机。我们把这个particle的各种状态和对应的速度等属性的情况设置成一张纹理图。当particle的属性变化时就从纹理图中找到对应的状态不断切换。

Navigation Texture。在上述基础上,可以利用一个粒子一个人来模拟一个导航纹理图。具体来说,利用SDF来避免人走入建筑物内,然后依次也可以设定一个方向纹理图,当我们给一个粒子设定目的地和初始速度后,它会根据DT的场驱动着往目的地走。当然,过程中可以加一些随机性。
在这里插入图片描述

粒子系统在游戏中的应用早起是“预设型”,即在最初就设定好particle可能的行为,并用stack来表示和存储;后来又有“基于图“的设计,减少代码量增加灵活性;最好的是两者混合型,如下图:
在这里插入图片描述

相关文章:

游戏引擎中的粒子系统

一、粒子基础 粒子系统里有各种发射器(emitter),发射器发射粒子(particle)。 粒子是拥有位置、速度、大小尺寸、颜色和生命周期的3D模型。 粒子的生命周期中,包含产生(Spawn)、与环…...

哈佛大学商业评论 -- 第二篇:增强现实是如何工作的?

AR将全面融入公司发展战略! AR将成为人类和机器之间的新接口! AR将成为人类的关键技术之一! 请将此文转发给您的老板! --- 本文作者:Michael E.Porter和James E.Heppelmann 虽然物理世界是三维的,但大…...

『python爬虫』巨量http代理使用 每天白嫖1000ip(保姆级图文)

目录 注册 实名得到API链接和账密 Python3requests调用Scpay总结 欢迎关注 『python爬虫』 专栏,持续更新中 欢迎关注 『python爬虫』 专栏,持续更新中 注册 实名 注册巨量http 用户概览中领取1000ip,在动态代理中使用.用来测试一下还是不错的 得到AP…...

6-95 希尔排序(Java语言描述)

编程实现希尔排序函数。public static void shellSort(int arr[])。其中arr存放待排序的数据,数组长度不大于1000。 函数接口定义: /* 对长度为n的数组arr执行希尔排序 */ public static void shellSort(int arr[]); 请实现 shellSort函数,使排序后的数据从小到大排列。…...

JAVA面试大全之分布式篇

目录 1、一致性算法 1.1、什么是分布式系统的副本一致性?有哪些? 1.2、在分布式系统中有哪些常见的一致性算法?...

qt各种锁使用讲解

在Qt中,主要有以下几种锁的类型: 1. QMutex(互斥锁): 是最常见的锁类型,用于实现简单的互斥访问。可以通过lock()和unlock()手动控制锁的加锁和解锁。 QMutexLocker:是一个RAII类,…...

5.111 BCC工具之ext4dist.py解读

一,工具简介 ext4dist跟踪ext4的读取、写入、打开和fsync操作,并将其延迟总结为2的幂次方直方图。 二,代码示例 #!/usr/bin/env pythonfrom __future__ import print_function from bcc import BPF from time import sleep, strftime import argparse# symbols kallsyms …...

Rust 的 termion 库控制终端光标的位置

在控制台应用程序中,固定打印在屏幕的第一行通常涉及到控制终端光标的位置。Rust 标准库本身并不提供直接控制终端光标位置的功能,但你可以使用第三方库如 termion 来实现这个需求。 termion 是一个用于处理终端的 Rust 库,它提供了很多有用…...

ADB(Android Debug Bridge)操作命令详解及示例

ADB(Android Debug Bridge)是一个强大的命令行工具,它是Android SDK的一部分,主要用于Android设备(包括真实手机和平板电脑以及模拟器)的调试、系统控制和应用程序部署。 下面是一些ADB的常用命令&#xff…...

书生浦语训练营2期-第二节课笔记作业

目录 一、前置准备 1.1 电脑操作系统:windows 11 1.2 前置服务安装(避免访问127.0.0.1被拒绝) 1.2.1 iis安装并重启 1.2.2 openssh安装 1.2.3 openssh服务更改为自动模式 1.2.4 书生浦语平台 ssh配置 1.3 补充(前置服务ok…...

【日常积累】指定ruby版本环境安装

背景说明 在redis的5.0版本之前,使用redis提供的redis-trib创建redis集群时还需要依赖ruby环境。当然有时候我们自已也需要安装指定ruby版本环境。下面是安装时的大致过程,以及过程中遇到的问题解决。我使用的环境是centos7,小版本差别应该不…...

SOC内部集成网络MAC外设+ PHY网络芯片方案:MII/RMII 接口与 MDIO 接口

一. 简介 本文来了解一下常用的一种网络硬件方案:SOC内部集成网络MAC外设 PHY网络芯片方案。 其中涉及的 MII接口,RMII接口(MII接口与RMII接口二选一),MDIO接口,RJ45。 二. MII/RMII 接口,M…...

简单了解HTTP和HTTPS

HTTP的安全问题? 我们都知道HTTP是不安全的,而HTTPS是安全的,那HTTP有哪些安全问题呢?(考虑传输过程以及响应方) 明文传输,有窃听风险:HTTP协议无法加密数据,所有通信数…...

系列学习前端之第 9 章:一文搞懂 Node.js 和 nvm,掌握 npm

1、说说 Node.js Node.js 本质上是一款应用软件(本质上与QQ、微信一样),它可以运行 JavaScript 代码,这样就使得 JavaScript 能够脱离浏览器运行。Node.js 是基于 Google 的 V8 引擎,V8引擎执行 Javascript 的速度非常…...

超强命令行解析工具Apache Commons CLI

概述 为什么要写这篇文章呢?因为在读flink cdc3.0源码的时候发现了这个工具包,感觉很牛,之前写过shell命令,shell是用getopts来处理命令行参数的,但是其实写起来很麻烦,长时间不写已经完全忘记了,现在才发现原来java也有这种工具类,所以先学习一下这个的使用,也许之后自己在写…...

JAVAEE——多线程进阶,锁策略

文章目录 锁策略乐观锁和悲观锁乐观锁悲观锁两者的比较 读写锁重量级锁和轻量级锁重量级锁轻量级锁 自旋锁公平锁和非公平锁公平锁非公平锁 可重入锁和不可重入锁可重入锁不可重入锁 锁策略 乐观锁和悲观锁 乐观锁 什么是乐观锁呢?我们可以认为乐观锁比较自信&am…...

富文本编辑器Quill全套教程

Quill简介 Quill是一款现代的富文本编辑器,它以其API驱动的设计和对文本格式的深度理解而著称。与传统的富文本编辑器不同,Quill专注于以字符为中心,构建了一个直观且易于使用的API,使得开发者能够轻松地对文本进行格式化和编辑。…...

Swift 代码注释的使用

Swift代码注释的使用 在 iOS 开发中,代码注释是一种很好的实践,可以帮助他人更容易理解你的代码。通常可以在代码中使用注释来解释代码的功能、目的、实现细节等。下面是一些常见的 iOS 代码注释示例: 1. 单行注释: // 这是一个…...

蓝桥杯—DS1302

目录 1.管脚 2.时序&官方提供的读写函数 3.如何使用读写函数 4.如何在数码管中显示在DS1302中读取出的数据? 1.管脚 2.时序&官方提供的读写函数 /* # DS1302代码片段说明1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。2. 参赛选手可以自行…...

nginx: 集群环境配置搭建

nginx 集群环境搭建 1 ) 概述 nginx 本身就应该选择性能强劲的机器同时为了满足更多流量的需求, 多台nginx 机器做集群来满足强大的需求故而,我们需要一个负载均衡器,以及多台nginx的机器 这里负载均衡器应该有主从和热备,目前先使用一台来描…...

vscode里如何用git

打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...