基于可变分辨率的半透明特效渲染优化方案

2024-03-05 19:12

本文主要是介绍基于可变分辨率的半透明特效渲染优化方案,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

粒子效果在游戏中无处不在。大颗粒系统常见于烟雾、火灾、爆炸、灰尘和雾。如果这些效果填满屏幕,overdraw会非常严重,帧率会掉得很快,即使是在技术成熟的 3A 游戏中也是如此。以至于来半透明渲染的优化问题一直都是难题。

这里的解决方案是将昂贵的粒子渲染到屏幕外渲染目标,其大小是帧缓冲区大小的一小部分。但是这里的解决方案做了一个假设,认为许多用粒子建模的效果都是模糊且柔和的。更专业地说,烟和雾的图像只有低频,没有锐利的边缘。它们可以用少量样本来表示,而不会损失视觉质量。因此,低分辨率帧缓冲区就足够了。如果是具有高图像频率的粒子,例如飞行的岩石碎片。这里的方案可能就不适用了。

离屏渲染

粒子需要被渲染到离屏渲染目标,大小一般要设置主分辨率的一半以上。起码尺度要是二的幂。

离屏深度测试

要正确遮挡场景中其他的粒子,需要深度测试和深度缓冲区,其大小与我们的离屏渲染目标相匹配。我们通过对主 z 缓冲区进行下采样来获得这一点。基本算法是这样的:

  1. 正常渲染场景中的所有实体对象,并进行深度写入。
  2. 对生成的深度缓冲区进行downsample。
  3. 将粒子渲染到屏幕外渲染目标(也就是额外的rendertarget),并做深度测试。
  4. 将粒子渲染目标合成回主帧缓冲区,进行upsample。
获取深度
获取 DirectX 9 中的深度

在 DirectX 9 下,无法直接访问主 z 缓冲区。必须使用三种方法之一显式创建深度。

可以使用多个渲染目标(MRT):颜色信息写入第一个目标;深度写入第二个。这种方法有一些缺点。所有目标必须具有相同的位深度。后台缓冲区将为 32 位(或更多),但更少的缓冲区可能足以满足深度。更严重的是,MRT 与 DirectX 9 中的多重采样抗锯齿 (MSAA) 不兼容。

或者,可以通过在单独的通道中写入单个渲染目标来创建深度。这有一个明显的缺点,即需要对场景的大部分几何体或至少与粒子效果相交的部分进行额外的传递。从好的方面来说,深度可以直接以所需的离屏分辨率写入,无需downsample操作。

如果尚未使用 Alpha,则还可以将深度写入 RGBA 目标的 Alpha 通道。A8R8G8B8可能没有足够的精度。

获取 DirectX 10 中的深度

DirectX 10 允许直接访问深度缓冲区中的值。具体来说,您可以为深度表面绑定着色器资源视图(SRV)。毫不奇怪,您必须首先将其解除绑定为渲染目标。否则,它是相当简单的。

还有一个问题。无法为多重采样深度缓冲区绑定 SRV。原因还是比较深的。MSAA 解析操作应如何应用于深度值?与解析颜色值不同,平均值是不正确的;点采样也是错误的。其实没有正确答案。对于我们对粒子的应用,点采样可能是可以接受的。

MRT 可与 MSAA 配合使用,并且 MRT 目标可以具有不同的位深度。对于浮点表面格式的 MSAA 的使用也没有限制。

downsample深度

无论我们如何获取深度值,深度表面都需要被downsample到离屏渲染目标的较小尺寸。但是没有普遍正确的深度downsample方法。

点采样深度

简单的点采样深度会产生明显的伪影。

绿色三角形是前景对象,靠近视点,具有较低的深度值。白色背景区域具有最大深度。虚线表示的 16 个像素被下采样为 1 个离屏像素。A 点是我们进行深度采样的地方。它不能代表 16 个输入像素中的大部分;只有像素 B 具有相似的深度。

如果绿色三角形是前景对象,后面有一个粒子,则深度测试将遮挡低分辨率像素和所有 16 个高分辨率像素的粒子。结果可能是前景物体周围出现光晕。如下图b所示

最大深度样本

可以通过进行多个单点采样来改善光晕。上图中的c显示了downsample时应用最大函数的结果。从全分辨率深度数据中对四个深度值进行采样,并取最大的一个。这具有缩小粒子屏幕外图像中的对象轮廓的效果。但这绝对没有物理或理论依据。它只是看起来比光环更好。这是一个权宜之计。这就是深度downsample函数必须由应用程序定义的原因。这些瑕疵足够小,当低分辨率粒子图像添加回主帧缓冲区时,它们很大程度上被线性混合隐藏。

深度测试和软粒子

深度测试是通过像素着色器中的比较来实现的。downsample深度缓冲区绑定为纹理(DirectX 10 中的 SRV)。正在渲染的粒子的深度在顶点着色器中计算并向下传递到像素着色器。

在像素着色器中实现的深度测试
float4 particlePS(VS_OUT vIn): COLOR {   float myDepth = vIn.depth;   float sceneDepth = tex2D(depthSampler, vIn.screenUV).x;   if (myDepth > sceneDepth)     discard;   // Compute color, etc.   . . . } 

软粒子效果会在粒子接近与实体场景对象相交处时淡化粒子 alpha。从而避免了恶劣、尖锐的交叉路口。视觉效果非常好。

软粒子比二元深度测试更好
float4 particlePS(VS_OUT vIn): COLOR {   float myDepth = vIn.depth;   float sceneDepth = tex2D(depthSampler, vIn.screenUV).x;   float zFade = saturate(scale * (myDepth - sceneDepth));   // Compute (r,g,b,a), etc.   . . .   return float4(r,g,b, a * zFade); } 

Alpha 混合

部分透明的粒子效果通常混合到帧缓冲区中。设置 Alpha 混合渲染状态以创建混合方程:

1 = d ( 1 - 1 ) + 1 1 ,

其中1是最终颜色,d是帧缓冲区中已有的目标颜色,1和 1是像素着色器输出的传入源颜色和 Alpha。如果随后在p 1上混合更多粒子,结果将变为

2 = ( 1 )(1 - 2 ) + 2 2 = ( d (1 - 1 ) + 1 1 )(1 - 2 ) + 2 2 ,

3 = ( 2 )(1 - 3 ) + 3 3 = (( d (1 - 1 ) + 1 1 )(1 - 2 ) + 2 2 (1 - 3 ) + 3 3 ,

将p 3 的方程重新排列为组ds项给出

3 = d (1 - 1 )(1 - 2 )(1 - 3 ) + 1 1 (1 - 2 )(1 - 3 ) + 2 2 (1 - 3 ) + 3 3。

将除帧缓冲区之外的所有内容存储离屏渲染目标中。最终的组合操作需要生成3,或更一般地说n

先取d项——这样更简单。它乘以每个混合的 alpha 值的倒数。因此,我们将这些乘法累加到渲染目标的 Alpha 通道中。

接下来,检查对3起作用的s项。请注意,如果目标初始化为零,则它们采用与2、3等的传统 alpha 混合方程相同的形式:

0(1 - 1 ) + 1 1

0(1 - 1 )(1 - 2 ) + 1 1 (1 - 2 ) + 2 2

0(1 - 1 )(1 - 2 )(1 - 3 ) + 1 1 (1 - 2 )(1 - 3 ) + 2 2 (1 - 3 )+ 3 3

用于渲染屏幕外粒子的 Alpha 混合状态
AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; SeparateAlphaBlendEnable = true; SrcBlendAlpha  = Zero; DestBlendAlpha = InvSrcAlpha; 

将粒子添加到帧缓冲区中以实现火焰等发射效果也很常见。处理这种情况比前面的 alpha 混合情况简单得多。值会累加到离屏目标中,然后添加到帧缓冲区中。

混合分辨率渲染

使用最大深度值对深度进行下采样可减少光晕。然而,屏幕外的粒子图像仍然可能是不可接受的效果。

当图像动画化时,这些伪影会闪烁并弹出。这在快速移动的动画中可能并不明显。然而,缓慢且连续地移动就会有这种效果。

我们可以通过边缘检测后然后对边缘做全分辨率处理来解决这个问题。

边缘检测

检查渲染目标中的离屏颜色和 Alpha 通道

使用标准 Sobel 滤波器可以轻松实现边缘检测。结果存储在另一个离屏渲染目标中。

使用模板进行排版

边缘检测滤波器选择一小部分块状像素。可以通过仅在出现边缘的地方以全帧缓冲区分辨率渲染粒子来修复像素化区域。

模板缓冲区用于有效屏蔽帧缓冲区的区域。当低分辨率、离屏粒子被组合回主帧缓冲区时,我们同时写入模板缓冲区。模板值无法由像素着色器显式设置。所以需要为所有像素启用模板写入,然后像素着色器可以调用丢弃关键字来禁止输出。这可以防止该像素的模板写入,并且像素着色器可以有效地控制模板值,从而创建蒙版。

然后对粒子进行第二次渲染。模板状态的设置使得像素仅写入先前合成通道未触及的区域 。这里显示下结果。

结果

上图将全分辨率粒子与混合分辨率结果进行了比较,其中屏幕外表面按 4x4 缩放。混合分辨率结果非常接近高分辨率版本。但是要注意低分辨率表面无法充分表示此细节,也要注意高频的图像是无法这样处理的,并且可能会导致画面模糊。

结论

结果表明,低分辨率离屏渲染可以带来显着的性能提升。它有助于使粒子的成本更具可扩展性,以便在过度绘制的最坏情况下(粒子系统填满屏幕)帧速率不会急剧下降。在真实的游戏中,这将转化为更一致的帧速率体验。

从视觉上看,结果永远不可能完全没有伪影,因为没有完美的方法来对深度值进行downsample。所以总会存在一些采样不足的问题。然而,在游戏中,诸如爆炸之类的粒子通常会快速移动,因此小的伪影可能是可以接受的。

这篇关于基于可变分辨率的半透明特效渲染优化方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/777531

相关文章

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

Java进行文件格式校验的方案详解

《Java进行文件格式校验的方案详解》这篇文章主要为大家详细介绍了Java中进行文件格式校验的相关方案,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、背景异常现象原因排查用户的无心之过二、解决方案Magandroidic Number判断主流检测库对比Tika的使用区分zip

分辨率三兄弟LPI、DPI 和 PPI有什么区别? 搞清分辨率的那些事儿

《分辨率三兄弟LPI、DPI和PPI有什么区别?搞清分辨率的那些事儿》分辨率这个东西,真的是让人又爱又恨,为了搞清楚它,我可是翻阅了不少资料,最后发现“小7的背包”的解释最让我茅塞顿开,于是,我... 在谈到分辨率时,我们经常会遇到三个相似的缩写:PPI、DPI 和 LPI。虽然它们看起来差不多,但实际应用

Python如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.

一文详解SpringBoot响应压缩功能的配置与优化

《一文详解SpringBoot响应压缩功能的配置与优化》SpringBoot的响应压缩功能基于智能协商机制,需同时满足很多条件,本文主要为大家详细介绍了SpringBoot响应压缩功能的配置与优化,需... 目录一、核心工作机制1.1 自动协商触发条件1.2 压缩处理流程二、配置方案详解2.1 基础YAML

MySQL中慢SQL优化的不同方式介绍

《MySQL中慢SQL优化的不同方式介绍》慢SQL的优化,主要从两个方面考虑,SQL语句本身的优化,以及数据库设计的优化,下面小编就来给大家介绍一下有哪些方式可以优化慢SQL吧... 目录避免不必要的列分页优化索引优化JOIN 的优化排序优化UNION 优化慢 SQL 的优化,主要从两个方面考虑,SQL 语

IDEA中Git版本回退的两种实现方案

《IDEA中Git版本回退的两种实现方案》作为开发者,代码版本回退是日常高频操作,IntelliJIDEA集成了强大的Git工具链,但面对reset和revert两种核心回退方案,许多开发者仍存在选择... 目录一、版本回退前置知识二、Reset方案:整体改写历史1、IDEA图形化操作(推荐)1.1、查看提

MySQL中慢SQL优化方法的完整指南

《MySQL中慢SQL优化方法的完整指南》当数据库响应时间超过500ms时,系统将面临三大灾难链式反应,所以本文将为大家介绍一下MySQL中慢SQL优化的常用方法,有需要的小伙伴可以了解下... 目录一、慢SQL的致命影响二、精准定位问题SQL1. 启用慢查询日志2. 诊断黄金三件套三、六大核心优化方案方案

Redis中高并发读写性能的深度解析与优化

《Redis中高并发读写性能的深度解析与优化》Redis作为一款高性能的内存数据库,广泛应用于缓存、消息队列、实时统计等场景,本文将深入探讨Redis的读写并发能力,感兴趣的小伙伴可以了解下... 目录引言一、Redis 并发能力概述1.1 Redis 的读写性能1.2 影响 Redis 并发能力的因素二、