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

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

相关文章

Java Response返回值的最佳处理方案

《JavaResponse返回值的最佳处理方案》在开发Web应用程序时,我们经常需要通过HTTP请求从服务器获取响应数据,这些数据可以是JSON、XML、甚至是文件,本篇文章将详细解析Java中处理... 目录摘要概述核心问题:关键技术点:源码解析示例 1:使用HttpURLConnection获取Resp

Java实现优雅日期处理的方案详解

《Java实现优雅日期处理的方案详解》在我们的日常工作中,需要经常处理各种格式,各种类似的的日期或者时间,下面我们就来看看如何使用java处理这样的日期问题吧,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言一、日期的坑1.1 日期格式化陷阱1.2 时区转换二、优雅方案的进阶之路2.1 线程安全重构2

MySQL索引的优化之LIKE模糊查询功能实现

《MySQL索引的优化之LIKE模糊查询功能实现》:本文主要介绍MySQL索引的优化之LIKE模糊查询功能实现,本文通过示例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录一、前缀匹配优化二、后缀匹配优化三、中间匹配优化四、覆盖索引优化五、减少查询范围六、避免通配符开头七、使用外部搜索引擎八、分

Python通过模块化开发优化代码的技巧分享

《Python通过模块化开发优化代码的技巧分享》模块化开发就是把代码拆成一个个“零件”,该封装封装,该拆分拆分,下面小编就来和大家简单聊聊python如何用模块化开发进行代码优化吧... 目录什么是模块化开发如何拆分代码改进版:拆分成模块让模块更强大:使用 __init__.py你一定会遇到的问题模www.

Java图片压缩三种高效压缩方案详细解析

《Java图片压缩三种高效压缩方案详细解析》图片压缩通常涉及减少图片的尺寸缩放、调整图片的质量(针对JPEG、PNG等)、使用特定的算法来减少图片的数据量等,:本文主要介绍Java图片压缩三种高效... 目录一、基于OpenCV的智能尺寸压缩技术亮点:适用场景:二、JPEG质量参数压缩关键技术:压缩效果对比

SpringBoot首笔交易慢问题排查与优化方案

《SpringBoot首笔交易慢问题排查与优化方案》在我们的微服务项目中,遇到这样的问题:应用启动后,第一笔交易响应耗时高达4、5秒,而后续请求均能在毫秒级完成,这不仅触发监控告警,也极大影响了用户体... 目录问题背景排查步骤1. 日志分析2. 性能工具定位优化方案:提前预热各种资源1. Flowable

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

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