unity着色器和屏幕特效开发秘笈_Oculus研发分享:开发移动VR内容时应避免的PC渲染技术...

查看引用/信息源请点击:映维网

开发移动VR内容时应避免的PC渲染技术

映维网 2019年11月25日)有不少开发者都是以与PC相同的方式来开发Quest游戏,但这可能会导致优化性能方面出现大量困难。Oculus软件工程师特雷弗·达什(Trevor Dasch)的工作是帮助开发者构建高质量的游戏,并确保它们能够以稳定的72FPS速度运行。日前,达什撰文分享了在为移动VR开发内容时应该避免的PC渲染技术。下面是映维网的具体整理:

b58f925ab58e6fb2114c43c6e8b2b323.png

尽管移动芯片组可以支持下面概述的大多数技术,但我们强烈建议你不要这样做。不过,这并不总是一成不变的规则,因为我有看到开发者有实现下述技术但依然达到帧速率的要求。但通过避免下文提及的PC渲染技术,你会为自己省下大量的麻烦。

1. 延迟渲染

延迟渲染(或延迟着色)这种技术是将光照/渲染计算推迟到第二步进行计算。这样做的目的是为了避免多次渲染同一个像素。延迟渲染主要分为两步:在第一步中,渲染场景,但只是简单地将几何信息(位置坐标,法线向量,纹理坐标和反射系数等等)存储在中间缓冲区中;在第二步中,从中间缓冲区读取信息,应用反射模型,计算出每个像素的最终颜色。延迟渲染对PC开发非常有效,因为它可以将几何图形与照明分离,你只需更新每个照明所触达的像素,即可在更少的GPU周期内渲染更多照明。

为何不适合移动开发?

原因有很多,但主要是因为解析成本。什么是解析费用?在我告诉你什么是解析成本之前,你首先需要理解基于图块渲染的工作原理。

为了以更低功耗实现更高的吞吐量,移动GPU(如Oculus Quest中的骁龙835)通常采用基于图块的架构,其中每个渲染目标都分解为块状网格或“图块”(从16×16像素到256×256像素之间,具体取决于硬件和像素格式)。接下来,你的几何会“绑定”到图块,然后再提交给异步处理器,异步处理器执行渲染工作并计算每个“图块”的图像结果。计算完每个图块图像后,GPU必须从片上内存中将图块复制回通用内存。这实际上非常慢,因为它需要通过总线传输数据。我们将这个转移过程称为“解析”,所以花费的时间称为“解析费用”。

因为要渲染的每个纹理都需要解析,并且延迟渲染需要在计算照明之前渲染大量纹理,所以你的解析成本将从正向渲染的大约1ms增加至3ms以上。如你所见,你可能没有这样的时间。

除了解析成本问题之外,延迟渲染仅在几何形状复杂且有多个光源的情况下才能显露出优势。无论如何,移动设备都真正实现这两者,因为GPU用来处理大量顶点和计算计像素填充的能力有限。

目前的答案是坚持采用正向渲染。

2. Depth Pre-Pass

cd329c806781eaf9364ce796160dad8d.png

Depth/Z Pre-Pass是一种常见的技术,其中所有场景几何图形都作为第一步渲染,无需填充帧缓冲区,仅生成深度缓冲区值。然后,你渲染第二通道,检查每个像素的计算深度是否等于深度缓冲区中的值。如果不是,则可以跳过对这一片段的着色处理。由于处理顶点的速度通常比像素着色快得多,所以可以节省大量时间。

为何不适合移动开发?

首先,如果在提交绘制调用之前对几何进行排序,通过进行Depth Pre-Pass而节省的片段填充时间应该最少。来回绘制会导致常规深度测试拒绝你的像素,所以你只能避免对未正确排序或两个对象在不同点彼此重叠的几何图形进行像素填充。

其次,这需要绘制调用加倍,因为你必须先提交所有内容以进行Depth Pre-Pass,然后再才是Forward Pass。由于CPU的绘制调用已经相当沉重,所以你需要避免这种情况。

第三,所有顶点都需要处理两次,与通过避免填充少数像素两次而节省的时间相比,你通常增加的GPU时间会更多。这是因为移动设备的顶点处理会在PC耗费更多的时间,并且处理片段的时间同样相对较少。

3. HDR纹理

解析成本与图像中的字节数直接相关,而不与像素数直接相关,所以,尽管我们通常以32位RGBA像素来思考量度,但如今大多数开发者都在使用HDR纹理,即每像素64位。这会将你的解析成本增加一倍,并且由于显示器仅支持每通道8位,所以你在解析HDR纹理时会浪费大量时间。更不用说移动GPU是针对32位帧缓冲区进行优化。

4. 后处理

acfbcccc775a4ea2a29a9a824b37f16c.png

后处理是一种经常用于为游戏施加多种效果的技术,如Color Grading,Bloom照明和运动模糊。具体的实现方式是获取游戏渲染的输出,然后对图像运行全屏通道以产生新图像,然后再将其呈现给玩家。一些后期处理效果是作为一个额外的通道执行(如颜色分级),另一些则需要多个通道。

对于移动设备,后处理的主要问题同样是解析成本。生成第二张图像将引起另一次解析,并会立即消耗大约1毫秒的时间。更不用说计算后处理效果所花费的时间,取决于效果,这可能会占用大量资源。所以,最好避免进行后处理。

以下是替代常见后处理效果的方案:

  1. Color grading:与其在后处理中执行Color Grading,不如在每个片段着色器的末尾添加一个函数调用以执行相同的数学运算。这将产生相同的视觉结果,但无需额外的解析。
  2. Bloom:真正的Bloom效果非常耗时。最好的选择是“伪造”。采用包含blob纹理的billboarding sprite可以产生非常接近的效果。

5. 实时阴影

28cc723c36c7272f2259af6d29681d04.png

我认为这是最有争议的一项技术。一系列具有完整实时阴影的应用已成功支持移动设备。但是,这样做存在大量的折衷,而我认为值得避免使用。

实时阴影的一种常用技术是级联阴影贴图,这意味着场景会以各种视口大小进行多次渲染。对于必须由GPU处理的几何,这会令次数增加1到4倍,这从根本上限制了场景可以支持的顶点数量。它同时增加了阴影贴图纹理的解析成本(与纹理大小有关)。在GPU管道的另一端,在对阴影贴图进行采样时有两个选项:硬阴影和软阴影。硬阴影可以更快地渲染,但具有不可避免的锯齿问题。

由于阴影贴图的工作方式,这个测试只能得出二进制结果。你无法对阴影贴图进行双线性采样,因为它表示深度值而非颜色值。应该避免使用软阴影,因为它们需要将多个采样放到阴影贴图中,而这当然很慢。最好的选择是烘烤所有可能的阴影,而如果需要实时阴影,请寻找另一种方法。如果照明大部分都是漫反射,则通常可以接受blob阴影。如果需要强光照明并且阴影表面是平面,则几何阴影的效果同样相当出色。

6. 深度(及帧缓冲区)采样

对于PC,你可以在着色器中采样当前的深度纹理(Unity将其显示为_CameraDepthTexture)。之所以可行,是因为深度纹理只是PC上的另一种纹理,并且由于每个绘制调用都接连发生,所以深度纹理的状态将是上一次绘制调用之后的状态。但对于基于图块渲染,当前深度不在纹理之中,而是仅存储在你的图块内存中,所以无法将其作为普通纹理进行采样。

考虑到上述情况,有一个GLES扩展可允许你查询深度缓冲区(和帧缓冲区)的当前状态。问题是它们非常慢,只能支持你对相同像素的值进行采样(无法查询附近的像素),并且在启用MSAA时它们会产生一系列的问题。

启用MSAA时,图块实际上具有一个足够大,能够容纳所有采样的缓冲区(即2×MSAA的像素为2倍,4×MSAA的像素为4倍)。这意味着默认情况下,如果对深度缓冲区进行采样,则必须按每个采样执行片段着色器,这意味着时间密集度将比预期高2倍或4倍。存在一种“解决方案”,即调用glDisable(FETCH_PER_SAMPLE_ARM)。但这样做的问题是,它将仅检索第一个采样的值,而不是混合采样的结果,所以在启用所述功能后,MSAA将被禁用。

除非绝对必要,否则你应避免它们对帧时间产生的影响。

7. 几何着色器

几何着色器允许你在运行时生成额外的顶点,这对于诸如动态细分等功能十分有用。但是,对于基于图块渲染的GPU而言,几何着色器会产生问题。生成额外顶点的步骤阻止了合并过程的进行,这意味着GPU不能这样做,所以它会切换为“立即”模式(完全跳过分块过程)。可以猜到,这非常缓慢。所以,最好避免使用几何着色器,并且如果有必要,选择CPU生成顶点。

8. Mirrors/Portals

如果你用天真的方式实现它们……对于“天真的方式”,我是指分配两个眼睛缓冲区大小的纹理,计算反射矩阵,然后将场景渲染到两个纹理中。然后,你的mirror几何将进行屏幕空间纹理采样,从而显示反射。这种方法存在众多明显的缺陷:

  1. 绘制调用增加了两倍。
  2. 填充的像素比屏幕可见的像素要多。
  3. 必须解析另外两个纹理。

我发现的最低提升是限制了mirror camera的视口,并更改了相应的投影矩阵,只能在视锥中渲染camera平面边界框。这对上面的第二点问题有所帮助。理想情况下,你同时可以使用多视图,通过一组绘制调用来渲染左右眼,但Unity目前不支持这项功能,它不能解决上面的第三点问题 ,并且会令第二点问题更加恶化,因为你只能为两只眼睛使用单个视口,所以你必须使用两个mirror边界框的重叠。所以,理想的解决方案将首先解决第三点问题,这意味着一次绘制mirror场景和非mirror场景。

有一种解决方案可以利用修改后的着色器和模板缓冲区。场景中的每种材质都将具有两种版本的着色器,一种仅在模板缓冲区中的特定位为0时绘制,而另一种仅在1时绘制。然后,你将使用材质绘制mirror网格。它会在模具缓冲区中设置所述位,使用第一组着色器绘制场景,使用反射矩阵设置camera,并且在最后使用第二组着色器绘制场景。这将产生你想要的反射,同时不会填充超出所需像素的像素,并且避免了不必要的解析。然而,它无法避免绘制一堆对象两次(任何解决方案都无法避免)。

尽管这听起来很容易,但如果是使用Unity,你将会遇到很多问题(我在Unreal中没有遇到过,但你可能会遇到类似的挑战)。首先,在启用Single Pass Stereo(多视图)后,Unity将不允许你修改camera的投影矩阵,所以你不能使用反射camera(如果关心CPU性能,你绝对应该使用这个camera)。其次,这没有考虑Late-Latching(在渲染线程启动时更新camera矩阵,从而尽可能减少延迟)。通常来说,这是一次纯粹的胜利,但如果你使用mirror camera,则反射camera的变形将不再与头部变形匹配,所以你会得到奇怪的伪影,镜面中的元素不会按照预期方式排列。

最简单的解决方案是“伪造”。如果你的镜面是静态,则只需创建所有世界几何的反射副本,然后将其放在场景中即可。你需要使用脚本来移动任何动态对象的“反射”副本,从而模仿包括玩家在内的“真实”版本位置,但这将是最快、最简单的渲染解决方案,无需复杂的矩阵数学。如果可以看到镜子后面,你将不得不使用两组具有不同模板蒙版的着色器,但如果玩家由于墙壁等原因而无法看到后面,则可以只保留一组着色器。

9. 总结

无论你是从零开始一个新项目,还是要从PC移植到移动设备,明确哪里可以沿用原有的知识经验,哪里又需要采取创新的解决方案是获得最佳游戏效果的关键。 但是,你不必遵循本文的建议。请自由探索,并寻找最适合自己的方案。

---
原文链接:https://yivian.com/news/69240.html

72d4e5af7920758e7fed9e226edc74e4.png

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

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

相关文章

Java包装类、java中的方法传参机制:按值调用

各位小伙伴们大家好,欢迎来到这个小扎扎的《Java核心技术 卷Ⅰ》笔记专栏,在这个系列专栏中我将记录浅学这本书所得收获,鉴于 看到就是学到、学到就是赚到 精神,这波简直就是血赚 💡涉及的知识点速通🛫 方法…

尤克里里怎么样_尤克里里和吉他区别?尤克里里与吉他相比有什么不可替代的优势...

尤克里里和吉他有什么区别?想必大家都见过尤克里里吧,就是类似吉他形状的一种小型弦拨乐器。我们可以简单的认为:尤克里里是简化版本的吉他,更加简单,更加便宜。小编弹的就是尤克里里2.从外观上:吉他很大&a…

饿汉懒汉单例设计模式的使用及区别、java中的import关键字

各位小伙伴们大家好,欢迎来到这个小扎扎的《Java核心技术 卷Ⅰ》笔记专栏,在这个系列专栏中我将记录浅学这本书所得收获,鉴于 看到就是学到、学到就是赚到 精神,这波简直就是血赚 💡涉及的知识点速通🛫 关于…

广电运通不好进吗_我可以说郑州新风的安装大部分都是垃圾吗?

说郑州的新风安装都是垃圾,这话很无礼,很自大,很傲慢,但是我能说确实是这样嘛?其实包括我以前安装的也不合格——虽然我不是故意的。这几年见过许多家同行安装的新风,可以说目前见到的很多家都不合格&#…

Java迭代器和Collection接口

各位小伙伴们大家好,欢迎来到这个小扎扎的《Java核心技术 卷Ⅰ》笔记专栏,在这个系列专栏中我将记录浅学这本书所得收获,鉴于 看到就是学到、学到就是赚到 精神,这波简直就是血赚 💡涉及的知识点速通🛫 关于…

私钥经过哈希计算可以产生公钥_「区块链基础概念100」:公钥和私钥 | 027

免责声明:本文旨在传递更多市场信息,不构成任何投资建议。文章仅代表作者观点,不代表火星财经官方立场。小编:记得关注哦投资区块链,猛戳:火星财经App下载来源:学习区块链原文标题:「…

关于List集合类ArrayList、LinkedList、Vector详解

各位小伙伴们大家好,欢迎来到这个小扎扎的《Java核心技术 卷Ⅰ》笔记专栏,在这个系列专栏中我将记录浅学这本书所得收获,鉴于 看到就是学到、学到就是赚到 精神,这波简直就是血赚 💡涉及的知识点速通🛫 关于…

关于Set集合类你都知道什么?来自《卷Ⅰ》的灵魂提问

各位小伙伴们大家好,欢迎来到这个小扎扎的《Java核心技术 卷Ⅰ》笔记专栏,在这个系列专栏中我将记录浅学这本书所得收获,鉴于 看到就是学到、学到就是赚到 精神,这波简直就是血赚 💡涉及的知识点速通🛫 关于…

流程图虚线框表示什么_UI设计|APP的交互线框布局设计

一.流程图设计流程图(Flow Chart):用图示的方式反映出特定主体为了满足特定需求而进行的有特定逻辑关系的一系列操作过程。流程图的四种基本结构:顺序结构,条件结构(又称选择结构),循环结构,分支结构。1.流程图的常用符…

使用Redis完成商品秒杀业务

各位小伙伴们大家好,欢迎来到这个小扎扎的Redis 6专栏,在这个系列专栏中我对B站黑马的Redis教程进行一个总结,鉴于 看到就是学到、学到就是赚到 精神,这波依然是血赚 ┗|`O′|┛ 💡Redis知识点速览&#…

表格列隐藏_【excel每日提升】Excel隐藏列,不让别人打开!

【新朋友】点击标题下面蓝色字“王俊东“关注。 【老朋友】点击右上角,转发或分享本页面内容。excel系列课程excel特效系列课程开始了,今天第2节!第1节:Excel有公式的单元格标记颜色,很简单!第2节&#xf…

“毕业季”|一个java开发实习生的OFFER之路

哈喽哈喽大家好,这里是小扎扎的博客。相信有关注过我的好盆友们可能会发现我已经有一段时间没有出来划水了,那么这段时间小扎扎都在干什么呢?没错!我确实是去找实习了!接下来就给大家介绍一下本次战役的战况如何 活动地…

virtualbox 该内存不能为written_系统提示“该内存不能为read”的原因和解决办法...

我们单位的电脑经常显示这个对话框,已经有好几年了,单位的老头们都不怎么懂电脑,我本人也不爱管闲事。但是出现这种对话框的原因是什么呢?又怎么解决呢?一般电脑经常出现蓝屏和死机,而且频繁出现。有时会出…

插件properties_Mybatis3系列 - 4. mybatis-config的properties属性详解

前两章简单的讲解了MyBatis的使用方式. 接下来先全局的说一下MyBatis的全局的xml配置详细说明.XML格式定义-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">configuration 的映射文件(根据定义顺序说明)properties 属性…

【Redis 6】秒杀业务——分布式锁

各位小伙伴们大家好,欢迎来到这个小扎扎的Redis 6专栏,在这个系列专栏中我对B站黑马的Redis教程进行一个总结,鉴于 看到就是学到、学到就是赚到 精神,这波依然是血赚 ┗|`O′|┛ 💡Redis知识点速览&#…

【Swagger】看这一篇就够了

各位小伙伴们大家好,欢迎跟着小扎扎一起学习【Swagger】这门技术,在本片博客中我对B站狂神的Swagger教程进行一个总结,鉴于 看到就是学到、学到就是赚到 精神,这波依然是血赚 ┗|`O′|┛ 💡Swagger知识点…

用python画大雄_python制作斗图生成器

网上各种带文字的表情图片都被大家玩坏了,今天就和大家一起用 python 亲自做一个带字表情图片生成器。 不知道大家有没有看到网上有很多人都在说 "人生苦短,我用 python",这句话我之前也不是很理解,觉得人生苦短和用pyt…

【spring cloud】(一)使用idea创建可相互调用的多模块应用

各位小伙伴们大家好,欢迎来到这个小扎扎的spring cloud专栏,在这个系列专栏中我对B站尚硅谷阳哥的spring cloud教程进行一个总结,鉴于 看到就是学到、学到就是赚到 精神,这波依然是血赚 ┗|`O′|┛ 💡spr…

python字符串百分号_Python字符串格式化的2种方法

本文介绍了Python字符串格式化,主要有两种方法,分享给大家,具体如下 用于字符串的拼接,性能更优。 字符串格式化有两种方式:百分号方式、format方式。 百分号方式比较老,而format方式是比较先进的&#xff…

【踩坑,已解决】spring cloud删除子模块后创建同名模块时遇到的删除不净,java、resources包失效,java、resources包被标记为模块等问题

💡问题速览📌 问题复现📌 没有任何操作,model又出现了📌 模块重建后java、resources包失效📌 模块重建后java、resources包被标记为了模块📌 问题复现 本人是在跟着B站尚硅谷的视频练习Spring c…