目录微信 |
1 渲染比例函数 1.1 向下缩放性能 1.2 渲染到缩放后的纹理flex 1.3 向上缩放url 2 MSAAspa 2.1 配置.net 2.2 多采样渲染纹理翻译 2.3 解析纹理贴图3d 2.4 无深度解析教程 2.5 Depth-Only 通道 3 HDR 3.1 配置 3.2 纹理格式 3.3 色调映射 3.4 莱因哈德(Reinhard) 3.5 修改Reinhard |
本文重点:
一、调整渲染比例
二、支持MSAA
三、启用HDR,带有可选的色调映射
这是涵盖Unity的可脚本化渲染管道的教程系列的第12部分。它涉及经过调整渲染比例,应用MSAA以及与色调映射结合使用HDR缓冲区进行渲染来提升图像质量。
本教程是CatLikeCoding系列的一部分,原文地址见文章底部。“原创”标识意为原创翻译而非原创教程。
本教程使用Unity 2018.4.6f1制做。
(HDR,MSAA和渲染比例一块儿使用)
1 渲染比例
要渲染的图像的宽度和高度由相机肯定,这不受管道的控制。可是咱们能够在渲染到摄像机目标以前作任何咱们想作的事情。若是渲染为中间的纹理,能够提供咱们想要的任何大小。例如,咱们能够将全部内容渲染为较小的纹理,而后对相机目标进行最后的blit处理以将其缩放到所需大小。这会下降图像质量,但因为要处理的片断较少,所以加快了渲染速度。Lightweight/Universal管道具备“Render Scale”选项来支持此功能,所以咱们也将其添加到咱们本身的管道中。
1.1 向下缩放
将渲染比例的滑块添加到MyPipelineAsset,初始范围为?~1。将分辨率下降到四分之一会使质量降低不少(像素数除以16),而且除非原始分辨率很高,不然极可能没法接受。
(Render scale 滑块设置为最小值)
将渲染比例传递给管道实例。
并让MyPipeline跟踪它。
在“渲染”(Render)中渲染摄影机时,请肯定在建立渲染纹理以前是否使用缩放渲染,以防出现活动堆栈。缩小渲染比例后,咱们将使用缩放渲染,可是仅对游戏窗口摄影机使用,所以场景,预览和其余摄影机不会受到影响。使用布尔变量跟踪此决策,让咱们能够参照。
还要跟踪变量中的渲染宽度和高度。它们默认状况下由相机肯定,可是在使用缩放渲染时必须进行调整。
1.2 渲染到缩放后的纹理
如今,当使用缩放渲染或后处理时,咱们必须渲染为中间纹理。还要使用布尔值对此进行跟踪,并在获取纹理时使用调整后的宽度和高度。
从如今开始,当调用RenderAfterOpaque时,必须将调整后的宽度和高度传递到活动堆栈。
RenderAfterTransparent也是如此。如今,咱们必须始终在渲染纹理时释放纹理,而仅在使用堆栈时才调用RenderAfterTransparent。若是不是,咱们可使用常规blit将缩放后的纹理复制到相机的目标。
(渲染比例一、0.7五、0.5和0.25;放大且无后处理)
调整渲染比例会影响管道渲染的全部内容,但阴影除外,由于阴影具备本身的大小。有时候偶然地,稍微减少渲染比例彷佛会带来一些抗锯齿效果。可是进一步减小能够清楚地看出,这只是细节损失致使的,当blit到最终渲染目标时,会因为双线性插值而模糊不清。
渲染比例如何与双线性插值交互的?
0.5的渲染比例是最简单的:最终,每块2×2目标像素只有一个像素。每一个最终像素使用相同的四个权重进行插值,可是有四个可能的方向。
(Render scale 0.5 filtering)
其余渲染比例尺会生成具备不一样权重配置的像素,由于从源像素到目标像素的距离会根据比例尺以规则模式变化。
(Render scale 0.75 filtering)
1.3 向上缩放
咱们能够按比例缩小图像质量以提升性能。也能够作相反的事情:以性能为代价扩大规模以提升图像质量。为此,在MyPipelineAsset中将最大渲染比例增长到2。
而且还能够在MyPipeline.Render中激活缩放渲染。
(渲染比例1.2五、1.五、1.75和2)
(Render scale 1.5 和2 filtering)
进一步增长渲染比例不会改善图像质量。在3的时候,咱们获得的结果与渲染比例1相同,而在4的时候,咱们以每一个像素2×2块的块返回,但距离更近。那是由于单个双线性blit只能平均四个像素。利用更高的比例将须要一个通道,每一个片断执行一次以上的纹理采样。尽管可行,但这是不切实际的,由于所需的工做比例与渲染比例成平方关系。SSAA 4x将须要使用渲染16倍的像素。
2 MSAA
SSAA的替代方法是MSAA:多样本抗锯齿。想法是相同的,可是执行方式不一样。MSAA跟踪每一个像素的多个样本,而没必要将其放置在常规网格中。最大的区别是片断程序每一个片断的每一个图元仅被调用一次,在原始分辨率下调用。而后将结果复制到栅格化三角形覆盖的全部子样本中。这显着减小了必须完成的工做量,但这意味着MSAA仅影响三角形的边缘,而没有其余影响。高频表面(High-frequency surface)模式和alpha裁剪的边缘仍然有锯齿。
alpha-to-coverage是什么?
这是在某种程度上平滑alpha裁剪边缘的技巧,在某些状况下能够产生不错的效果。本教程将不涉及它。
2.1 配置
为MyPipelineAsset添加一个选项以选择MSAA模式。默认状况下,MSAA是关闭的,其余选项是2×,4×和8×,能够用枚举表示。枚举值表示每一个像素的样本数量,所以默认值为1。
(MSAA模式)
为何不支持MSAA 16×?
能够支持,可是与8倍相比,它几乎没有额外的质量增益,由于很是昂贵,而且没有普遍的支持。
将每一个像素的样本量传递到管道实例。
并在MyPipeline中对其进行跟踪。
并不是全部平台都支持MSAA,最大样本数也有所不一样。超过最大值可能会致使崩溃,所以咱们必须确保保持在限制以内。咱们能够经过将样本计数分配给QualitySettings.antiAliasing来实现。咱们的管道不使用此质量设置,但在分配给它时会注意执行限制。在分配给它以后,咱们将其复制回咱们本身的样本计数。咱们惟一须要知道的是,当不支持MSAA时,它会产生零,咱们必须将其转换为样本计数1。
2.2 多采样渲染纹理
每一个相机都设置了MSAA支持,所以请在“Render”中跟踪用于渲染的样本,若是相机未启用MSAA,则将其强制为1。而后,若是最终每一个像素有多个样本,则必须渲染为中间的多采样纹理,简称MS纹理。
为了正确配置渲染纹理,咱们必须在GetTemporaryRT中再添加两个参数。首先是读写模式,这是颜色缓冲区的默认模式,而对于深度缓冲区则是线性的。下一个参数是样本计数。
在禁用全部后期处理的状况下尝试此操做。
(MSAA 2×,4×,8×,和没有MSAA比较 render scale为 2)
MSAA是否能够与定向阴影一块儿使用?
对于咱们的渲染管道,它工做正常。Unity的管道有麻烦,由于它们使用屏幕空间通道来级联定向阴影。在本教程中,咱们会再遇到相似的问题。
与将渲染比例增长一倍相比,MSAA 4X的最终效果要好于渲染比例2,但须要注意的是,渲染比例不只影响几何边缘,还影响全部事物。你也能够将两种方法结合起来。例如,渲染比例为2的MSAA 4x大体可与渲染比例为1的MSAA 8x大体相比,尽管它使用16个样本而不是每一个最终像素使用8个样本。
(MSAA 4× and 8×,render scale 2)
2.3 解析纹理贴图
虽然咱们能够直接渲染为MS纹理,可是不能以常规方式直接从它们读取图像。若是要对像素进行采样,则必须首先对其进行解析,这意味着将全部采样取平均值以得出最终值。整个纹理在特殊的“Resolve Color”通道中当即进行解析,该通道在采样以前自动插入。
(在最终blit以前解决颜色)
解析MS纹理会建立一个临时的常规纹理,该纹理在全部新纹理渲染到MS纹理以前一直有效。所以,若是咱们屡次采样而后渲染到MS纹理,则最终将得到相同纹理的额外解析通道。激活启用了模糊的后效果堆栈时,你会看到此信息。在强度为5的时候,咱们得到了3个解析通道。
(解析三遍,模糊强度5。)
附加的解析通道没有用,由于咱们的全屏效果没法从MSAA中受益。为了不没必要要地渲染到MS纹理,咱们能够一次渲染到中间纹理,而后使用它代替相机目标。为此,能够在MyPostProcessingStack中的RenderAfterOpaque和RenderAfterTransparent方法中添加示例参数。若是启用了模糊而且使用了MSAA,则将其复制到已解析的纹理并将其传递给Blur。
将渲染样本添加为MyPipeline.Render中的参数。
如今将三个解析通道减小为一个,再加上一个简单的blit。
(只用了一次 模糊强度为5)
2.4 无深度解析
颜色样本经过对它们进行平均来解决,但这不适用于深度缓冲区。平均相邻深度值没有任何意义,也没有可使用的通用方法,所以多采样深度根本没法解析。因此,启用MSAA时,深度条纹效果不起做用。
使效果再次起做用的幼稚方法是在启用深度条纹时不将MSAA应用于深度纹理。首先,向MyPostProcessingStack添加一个getter属性,该属性指示是否须要从深度纹理读取。仅在使用深度条纹效果时才须要。
如今,咱们能够跟踪MyPipeline.Render中是否须要可访问的深度纹理。仅当须要深度时,才须要得到单独的深度纹理,不然咱们能够经过设置颜色纹理的深度位来解决。并且,若是确实须要深度纹理,那么让咱们明确地始终将其样本设置为1,以禁用它的MSAA。
这也会影响绘制不透明效果后设置渲染目标。
最后须要释放哪些纹理。
(MSAA 8×的深度条纹)
如今,启用MSAA时会显示深度条纹,可是抗锯齿功能彷佛已损坏。发生这种状况是由于深度信息再也不受MSAA的影响。咱们须要另寻解决方案。
2.5 Depth-Only 通道
咱们须要一个MS深度纹理来进行常规渲染,并须要一个非MS深度纹理来进行深度条纹效果。能够经过为深度纹理建立自定义解析过程来解决此问题,但不幸的是,对此的支持很是有限。另外一种方法是经过添加Depth-Only的通道将深度渲染两次,以将其渲染到常规深度纹理。这是昂贵的但可行。当深度缓冲区与MSAA结合使用时,例如当级联方向阴影须要屏幕空间阴影通道时,这就是Unity的实现方式。
这是否意味着Unity的Depth-Only 通道不影响常规渲染?
确实。它不用于填充深度缓冲区,咱们也不会使用它。
首先要区分是能够直接使用深度纹理仍是由于MSAA处于活动状态而须要一个Depth-Only通道。咱们如今拥有的获取纹理和设置渲染目标的逻辑适用于不使用MSAA的状况。
若是须要,在调用RenderAfterOpaque以前添加Depth-Only通道。就像不透明的通道同样,除了咱们使用DepthOnly做为通道名称,不须要渲染器配置,而且必须设置和清除深度纹理做为渲染目标。
将所需的过程添加到Lit着色器。它是默认通道的拷贝,其中除去了实例化,剪切和LOD淡入淡出的全部功能。它不会写入颜色信息,所以请将其颜色掩码设置为零。它始终写入深度,并依赖于单独的DepthOnly HLSL文件中的专用顶点和片断函数。
DepthOnly.hlsl是Lit.hlsl的副本,其中删除了全部不影响深度的数据。
咱们只关心位置和UV坐标。片断功能仅适用LOD并执行裁剪。它的最终结果就是零。
如今,在深度条纹和MSAA再次起做用以前,咱们得到了Depth-Only通道。不幸的是,深度条纹效果自己没法从MSAA中受益,所以仍然会在严重影响图像的地方引入锯齿。Unity的级联方向阴影以相同的方式干扰MSAA。
(深度条纹具备功能性MSAA 8倍)
可是后来得到渲染的透明几何体仍然能够从MSAA中受益。
(透明,带有MSAA和深度条纹)
3 HDR
咱们将讨论的最后一个主题是高动态范围渲染。到目前为止,纹理的每一个颜色通道的范围为0-1,所以它能够表示强度为1的光照级别。可是入射光的强度没有固有的上限。太阳是很是明亮的光源的一个例子,这就是为何你不该该直接看它的缘由。它的强度远大于咱们在眼睛受损以前所能感知的强度。可是许多常规光源也会产生强度超过观察者极限的光,尤为是近距离观察时。例如,我将场景中的点光源的强度增长到100,并将白色球体的发射强度提升了一步。
(高强度光和自发光)
结果是过亮的像素被吹散为均匀的白色,而且在边缘附近有一些颜色偏移。HDR渲染的目的是防止图像的很是亮的部分退化为均匀的白色。这将须要存储明亮的数据并将其转换为可见的颜色。
3.1 配置
经过向MyPipelineAsset添加“Allow HDR”切换,将其传递给管道实例,使咱们的管道是否支持高动态范围渲染成为可选。
MyPipeline只须要跟踪它。
(HDR 开启)
3.2 纹理格式
要存储超过1的颜色值,咱们须要更改用于渲染纹理的纹理格式。若是咱们的管道和摄像机都启用了HDR,则咱们须要默认的HDR格式,不然咱们可使用常规默认值。区别在于HDR纹理的颜色通道包含浮点值而不是8位值。所以它们须要更多的内存,这意味着你仅应在须要时使用HDR。
咱们没必要根据是否启用HDR来决定renderToTexture,由于在不使用后期处理的状况下也没有理由使用HDR,由于最终的摄影机目标是每通道LDR 8位。
HDR显示器呢?
Unity当前不支持HDR显示器,所以咱们也不能支持。除此以外,HDR显示的问题是使用颜色分级的游戏必须在色调映射以后(或同时)进行此操做,从而生成常规的LDR图像,而后在发送以前将其转换回HDR 到显示器上,而后它会作本身的事情。
不使用渲染纹理时,请不要使用HDR。所以,让咱们也用MSAA,并不进行其余后处理。最初的结果看起来没有什么不一样,只是抗锯齿质量变差了。之因此发生这种状况,是由于只有在全部值均为LDR时,平均颜色才能很好地起做用,不然很是明亮的样本将主导结果。所以,当涉及HDR颜色时,MSAA会下降。
(MSAA×4都可打开和关闭HDR)
在MyPostProcessingStack中添加所需的参数。咱们只须要将其用于DepthStripes中的临时纹理,由于不管如何须须在LDR中执行模糊处理才能得到最佳效果。
3.3 色调映射
从HDR到LDR的转换称为色调映射,它来自摄影和胶片开发。传统的照片和胶片范围也颇有限,所以已经开发了许多技术来执行转换。没有惟1、绝对正确的方法来处理此问题。可使用不一样的方法来设置最终结果的气氛,例如经典的电影外观。可是,调整颜色属于色调分级以后的颜色等级。咱们只关心下降图像的亮度,以使其最终落在LDR范围内。
色调映射是一种后期处理效果,能够是可选的,所以请将其切换添加到MyPostProcessingStack中。
(开启色调映射)
它是经过本身的过程完成的,所以为其添加一个枚举值和方法,最初只是使用其本身的探查器样本进行涂抹。设置源ID和目标ID参数RenderTargetIdentifier,以便咱们能够灵活地传递给它。
若是禁用了模糊,则在RenderAfterTransparent中,将色调映射到摄像机目标而不是常规blit。不然,当使用色调映射或MSAA时,经过适当的遍历建立解析的纹理。所以,在这种状况下解决可能意味着MSAA解决,色调映射解决或二者兼而有之。
将新的通道添加到PostEffectStack着色器。
并将所需的功能添加到HLSL文件。最初返回的颜色为负1,饱和度。这能够指示咱们哪些像素包含过亮的颜色。
(只有过亮的颜色)
3.4 莱因哈德(Reinhard)
色调映射的目的是下降图像的亮度,以使均匀的白色区域显示各类颜色,从而揭示丢失的细节。就像你的眼睛不适应忽然明亮的环境,直到再次看的清楚。可是咱们不想均匀地缩小整个图像,由于那样会使深色变得难以区分,将高亮度换成曝光不足。所以,咱们须要一个非线性转换,该转换不会减小不少暗值,但会减小不少高值。在极端状况下,零保持为零,而且接近无穷大的值减少为1。完成的函数为 c/(1 + c),其中c是颜色通道。该功能被称为Reinhard色调映射操做,最初由Mark Reinhard提出,只是他将其应用于亮度,而咱们将其应用于各个颜色通道。使咱们的色调映射通道使用它。
(没有VS有 Reinhard RGB 色调映射)
结果是保证没有任何过亮像素的图像,可是整个图像已经去饱和并有些暗了。彻底处于满强度状态的像素减半,你能够在禁用HDR的状况下应用色调映射来清楚地看到。
(色调映射在LDR图像上的应用)
咱们不能在解决MS纹理以前执行色调映射吗?
能够,经过自定义解析通道,在对每一个样本进行平均以前对每一个样本执行色调映射,这比每一个像素执行一次代价更高。除此以外,像bloom这样的后处理效果还须要HDR数据。为了使这些工做有效,解析通道必须在平均后转换回HDR,以近似原始强度。
3.5 修改Reinhard
色调映射有多种方法-可使用颜色分级对其进行进一步调整-但每通道RGB Reinhard最简单,所以咱们先将其保留下来。可是咱们能够进行的简单调整是经过调整压缩为LDR的值范围来限制效果的强度。超出此范围的任何东西都保持明亮。这样一来,咱们就能够减小对亮度较弱的场景的调整,或者接受一些亮度太高的效果,以保持较暗的颜色不变。
Reinhard也描述了此调整,并将函数转换为,其中w 是白点,或本例中的最大色调映射范围。若是 w是无限的,那么咱们将再次拥有原始函数,当w 为1时,色调映射将不执行任何操做。
( w从1到5)
为该范围添加一个配置选项,最小值为1,由于较低的值会过分曝光整个图像。最大值能够为100,足以近似原始功能。而后计算,并将其做为Reinhard函数的修改器发送到GPU。
而后,着色器只需计算
(色调映射范围减小到2)
如今咱们结束了原始的SRP教程系列,该系列从尚处于实验阶段开始。Unity 2019发生了不少变化。为此,有一个新的自定义SRP系列,它以更现代的方式涵盖了新旧主题。
本文翻译自 Jasper Flick的系列教程
原文地址:
https://catlikecoding.com/unity/tutorials

本文分享自微信公众号 - 壹种念头(OneDay1Idea)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。