后期处理材质

如何使用材质编辑器创建和混合自定义后期处理通道。

Windows
MacOS
Linux

后期处理材质使您能够设置与后期处理一起使用的材质,以创建破坏的视觉屏幕效果、区域类型效果或 只能通过后置处理材质才能实现的游戏整体外观。

在下面的部分中,您将了解如何设置后期处理材质,您可以使用的可用设置,以及如何使用不同的缓冲区设置您自己的一些后期处理材质, 混合各种后期处理材质,等等。

后期处理图表

该引擎已经具有基于后期处理节点图表的复杂后期处理功能。后期处理材质(Post Processing Materials) 可以额外插入到某些特定位置。有关 r.CompositionGraphDebug,请参阅常见问题部分 ,获取完整图表的转储。 这张图表实际上不仅在做后期处理,还在做部分照明事宜。

大多数时候,图表会自动创建中间渲染目标。这意味着,如果您想与前一种颜色混合,您需要在着色器中进行混合 (使用来自PostProcessInput0的输入)。

后期处理材质应该节约使用,仅在真正需要时使用。在可能的情况下,如颜色校正或调整、泛光、景深和各种其他效果,您应该使用后期处理体积中固有的设置,这些设置已经过优化,而且更有效。

使用后期处理材质

通过后期处理设置(通常用后期处理体积或摄像机设置定义),可以混合(所谓的)可混合资源。 目前,只有 材质(Materials)材质实例(Material Instances) 是可混合资源。该引擎提供了一些后期处理材质,但有了这个特性, 您可以创建自己的 自定义后期处理,无需任何程序员的帮助。

只需将一个或多个后期处理材质分配到 可混合(Blendables) 部分的后期处理体积中。首先按 + 添加新槽, 在 内容浏览器(Content Browser) 中选择一个材质,然后按左箭头进行分配。这里的顺序并不重要,未使用的插槽将被忽略。

PostProcessSettings.png

制作简单的后期处理材质

有关从头开始创建简单的后期处理材质效果的概述,请参阅后期处理材质示例

FinalPostEffect.png

后期处理材质的关键设置

后期处理材质需要指定材质域 后期处理

DomainPostProcess.png

材质只能使用 自发光颜色(Emissive Color) 输出新颜色。此外,您还可以定义在后期处理过程中应在何处应用此通道, 如果有多个通道,则应按什么顺序处理(优先级):

PostProcessMaterialProps.png

可混合位置

说明

色调映射前(Before Tonemapping)

PostProcessInput0为HDR中的所有照明提供场景颜色。用它来修复时间抗锯齿和GBuffer查找的问题,如深度,法线。

色调映射后(After Tonemapping)

首选性能位置,因为颜色是LDR,因此需要的精度和带宽较少。这是在色调映射和颜色分级之后。

半透明前(Before Translucency)

这在通道中甚至比半透明与场景颜色结合之前的"色调映射前"还要早。注意SeparateTranslucency的混合比法线透明度要晚。

替换色调映射器(Replacing the Tonemapper)

PostProcessInput0为HDR提供场景颜色,PostProcessInput1具有SeparateTranslucency(Alpha是遮罩),PostprocessInput2具有低分辨率泛光输入。

典型的后期处理输入来自以前的通道。当使用 PostProcessInput0 时,可以通过SceneTexture材质表达式访问该颜色。使用SceneColor可能不会得到正确的结果。

混合不同的材质实例

使用后期处理材质

使用后期处理体积,很容易在多个后期处理材质之间设置软过渡。这里我们使用一个标记为未绑定的体积和一个具有更大混合半径的体积(例如,1000):

BlendingAVolume.png

BlendingAVolume1.png

后期处理设置为未绑定

后期处理绑定体积

我们为每个体积指定了相同材质的不同材质实例。颜色被指定为一个材质参数,它允许对两个材质实例进行不同的设置。

BlendMatInst1.png

BlendMatInst2.png

材质实例RED

材质实例GREEN

根据摄像机位置,在混合半径范围内使用和混合一个体积的设置:

Blend1.png

Blend2.png

Blend3.png

未绑定后期处理材质实例(RED)设置为0.75

混合半径1000

后期处理体积材质实例(GREEN)设置为0.75

随着摄像机的移动,您可以感知到两个效果设置之间的软线性过渡。

下面显示了一个关卡的自上而下视图,其中有两个体积。大的未绑定体积有一个红色的材质实例,小的体积有一个指定为可混合的绿色材质实例。 较小的体积具有较高的优先级。材质参数根据摄像机位置进行混合。 模糊边界由体积中指定的混合半径属性定义,并扩展体积形状。

使用了正确的设置,所有的混合都按预期进行。

Bad Setup

Good Setup

这两种设置之间的区别是在材质(标量或矢量)参数上指定的默认值。 良好设置有一些值使通道看似没有任何效果(例如,乘以白色或用使用插值0)。

这两种设置中,我们都能看到:当摄像机不受任一体积的影响时,后期处理通道不会被渲染(用灰色网格表示)。 如果我们完全在任一体积内,我们也会看到正确的混合。

不良设置:当摄像机进入影响半径时,我们看到一个硬过渡,因为使用了错误指定的默认参数。

良好设置:使摄像机进入影响半径的过渡隐藏得很好,我们会看到向体积颜色的平滑过渡。

所有材质实例属性都将混合,无论是否选中属性复选框(在这种情况下, 它混合了来自父项的属性)。这与未选中属性没有任何效果的后期处理设置不同。 这意味着如果混合一个材质实例,所有属性都将被混合。

材质表达式"SceneTexture"

您可以将 SceneTexture 材质表达式添加到材质中,并在表达式属性中选择要引用的纹理:

SceneTextureProps.png

节点有一个可选输入和多个输出:

SceneTextureExpression.png

UV 输入允许您指定要进行纹理查找的位置(仅用于颜色输出)。 颜色输出是4通道输出(实际的通道分配取决于场景纹理id)。大小(Size) 是一个包含纹理宽度和高度的 两分量矢量。该两分量矢量的倒数(1/宽度、1/高度)在 InvSize 输出中获得。在引用如下例所示的邻近样本时, 它非常方便:

DepthNextTo.png

材质表达式计算当前像素与相邻像素的深度差(例如In = 0,1会将delta返回到下面的像素)。

使用GBuffer属性

GBuffer由多个存储材质的纹理组成(例如次表面颜色/高光颜色、粗糙度...)和对象属性(例如法线、深度) 没有光照来计算阴影(光源如何与材质相互作用)。在延迟渲染器中,我们首先渲染GBuffer, 然后使用GBuffer属性计算所有的照明(延迟)。如果UE4使用延迟着色路径(例如DirectX 11或高端OpenGL),我们可以在后期处理期间访问这些缓冲区。

抗锯齿通常会使这一操作更加困难,因为GBuffer像素/纹素不再是与输出像素呈1:1关联(参见下面的部分)。

自定义深度

这个单独的特性通过将某些对象渲染到另一个深度缓冲区(称为自定义深度缓冲区)来屏蔽它们。 这增加了额外的绘制调用,但不使用更多材质。渲染相当便宜,因为我们只输出深度。该特性可以在网格体上激活 (例如静态网格体属性/渲染自定义深度):

CustomDepth.png

在这个场景中,我们在两个对象上激活了这个特性,但是如果没有后期处理通道对内容进行可视化处理,此特性仍然是不可见的:

scene.png

这里我们可以看到自定义深度的可视化效果,如下:

sceneCustomDepth.png

这是我们用来对其进行可视化的材质:

CustomDepthMat.png

自定义深度模具

自定义深度模具(Custom Depth Stencil)是自定义深度(Custom Depth)的扩展,您可以在其中使用渲染对象的模具或挖剪,然后做一些视觉效果上比较有趣的东西(如下例所示), 使您能够可视化遮挡对象,绘制对象轮廓,或仅从特定视角可见。通过访问场景中Actor的模具,您可以做很多事情 。使用以下设置启用并分配模具值。

CustomStencilSettings.png

在这个场景中,在三个对象上启用了自定义深度(Custom Depth),并且为每个对象设置了 自定义深度模具值(Custom Depth Stencil Value),但是如果没有任何后期处理来可视化内容,这个特性仍然是不可见的。

CustomDepthStencilScene.png

一旦设置好您的后期处理材质,您就可以可视化自定义深度模具的外观,根据使用的 自定义深度模具值(Custom Depth Stencil Value),使用随机分配的颜色渲染被遮挡的对象。

CustomDepthStencilVisualization.png

这是我们用来对其进行可视化的材质设置:

单击图像以查看完整尺寸。

这绝不是使用自定义深度模具(Custom Depth Stencil)的唯一方法,在这个特殊的材质设置中,对该模具进行划分,使其使用1到255之间的值,对介于这些值之间的任何值使用一个蒙板, 并为这些值创建一个随机颜色,以便当自定义深度模具值(Custom Depth Stencil Value)更改时,颜色也随之更改, 最后,所创建的蒙板仅在对象被遮挡时才对模具进行着色。

时间抗锯齿或为何GBuffer抖动

时间抗锯齿是一个独特的UE4功能,它能大大提高图像质量,而性能成本非常适中。

默认情况下,后期处理材质被插入到后期处理图表的末尾(在色调映射器之后)。这意味着在色调映射、颜色分级和应用时间抗锯齿之后, 您将得到最终的LDR颜色。这是许多简单的后期处理效果的最佳位置,以提高性能和易用性。

这里您可以看到我们如何使用自定义深度输入来可视化特定对象周围的轮廓:

sceneAfterTonemapper.png

注意,之前的图像中,轮廓上没有抗锯齿效果,但在运动中,您也会看到轮廓抖动约1像素。 这是因为时间抗锯齿将整个场景的渲染每帧移动一个亚像素。将多个帧组合在一起生成最终的抗锯齿图像。 不过,我们可以将材质移到后期处理图表中较早的位置来解决这个问题。

结果如下:

sceneBeforeTonemapper.png

我们得到一个稳定的抗锯齿图像。在运动中,我们可能会看到一些带时间抗锯齿的瑕疵。这个特性使用深度缓冲区来替换旧图像。在对象内部渲染了边框时,此特性可以正常工作, 但在对象外部,我们还需要调整深度缓冲区(尚未完成,需要额外的性能), 但理想情况下不应该这样做。

UV和ScreenPosition

使用后期处理材质,您可以查看屏幕对齐的缓冲区,但您需要知道正确的UV。 将映射选项设置为 ViewportUV 时,ScreenPosition 材质表达式输出UV,其中0,0位于视口的左上角,1,1位于右下角。 相反,在这个材质表达式中使用 SceneTextureUV 映射可能会得到不同的结果。这是因为实际的纹理(更准确地说是渲染目标)可能比视口更大。 它在编辑器中可以更大,因为我们为多个视口共享这个纹理,而最大的范围是用于所有视口。 即使在游戏中,它在某些情况下也可能更大(例如SceneCaptureActor可能拥有更小的视口、Matinee黑边框、分屏、VR等等)。 SceneTextureUV 选项为这个较大的纹理提供UV。如果您只需要一个相对偏移(如像素大小的边缘检测),您需要用正确的大小缩放。 SceneTexture 材质表达式输出大小和大小的倒数(对于像素偏移非常有效且有用)。 要测试所有这些,可以使用控制台变量 r.ViewPortTest,它允许您测试各种视口配置。

过滤纹理查找

SceneTexture材质表达式有一个复选框用于获取[双线性]过滤查找。使用此选项会导致渲染较慢,因此应仅在需要时使用。 许多屏幕空间纹理不支持过滤(例如GBuffer)。不公开此属性允许引擎在需要时压缩数据(打包会防止过滤)。

替换色调映射器

通过使用"替换色调映射器"可混合位置,可以用您自己的色调映射器覆盖引擎色调映射器。这是一个正在开发的特性,意味着它可能会发生变化,而且还没有全部的功能。

ReplacingTheTonemapper.png

我们开始向色调映射器公开一些后期处理设置参数,但是这部分可能会发生很大的变化。 这些值作为材质参数公开,需要有确切的名称。

矢量参数:

Engine.FilmWhitePoint

标量参数:

Engine.FilmSaturation
Engine.FilmContrast

为了获得这些参数,您需要根据后期处理材质创建一个材质实例。

您仍然可以使用自己的参数,并让它们像其他后期处理材质设置那样混合。

已知问题

以下问题仍需解决:

  • 材质表达式SceneTexture(Material expression SceneTexture) SeparateTranslucency无法正常工作。 某些查找在某些通道中不起作用(例如,有些我们可能无法修复,因为它们会花费太多的性能)。 * MaterialFunction可能会报告错误,但它仍然可以用于具有后期处理域的材质中。

  • 材质(Material) PostProcesMaterial中的UV可能不在0-1范围内(例如,在编辑器中减小视口大小时),这与查找一致,但会导致难以实施类似于晕映效果的东西。 后期处理材质的资源缩略图看起来不正确。 还不支持输出alpha(应该支持不透明)。 材质编辑器中的预览材质看起来不正确。 曾经出现过这样一种情况,即材质更改并未导致后期处理发生变化。变通方案:重启编辑器。 内容浏览器(Content Browser) 应允许方便地过滤后期处理材质。

  • 混合(Blending) * 当使用混合半径混合两个后期处理体积时,可能会看到非软过渡。这可以通过使用带有表示默认值的材质实例设置的未绑定体积来防止。

常见问题解答

* **我可以用"仅照明模式"纹理作为输入吗?**

不,我们没有这个数据作为中间步骤。对于这个视图模式,我们通过忽略材质颜色来生成它
。要使其成为一个快速选项,需要重新构造大部分渲染代码。
  • 为什么SceneColor查找显示条带,但当使用PostProcessInput0时,却没有显示?

    使用SceneColor时,我们创建一个较低质量的场景副本,以允许对我们当前写入的纹理进行查找 (通常情况是在不可能的位置进行网格体渲染)。 在后期处理中,您应使用PostProcessInput0。

  • 后期处理要消耗多少内存?

    内存消耗取决于屏幕分辨率。在色调映射之前,我们使用HDR(每个像素8字节),之后我们使用LDR(每个像素4字节)。

  • 如何降低后期处理的渲染成本?

    在目标平台上测量,保持纹理查找计数低,执行较少的数学运算,减少依赖性纹理查找, 避免随机纹理查找(会由于纹理缓存丢失而变得更慢)。

  • 我可以使用多少通道?

    每条通道都会增加性能消耗。尝试仅在需要时组合通道和激活通道。一般游戏功能 例如,为了获得更好的性能,可以在引擎的通道上增加噪音。

  • 每个后期处理和混合需要多少CPU性能?

    混合材质所需的性能成本消耗很低。所有的材质实例属性都被混合,只需渲染一个使用这些设置的后期处理材质通道。

  • 我需要使用"色调映射器之前(Before Tonemapper)"来获取适当的时间抗锯齿。当我使用一种颜色,它会经过色调映射,因此看起来不同。如何避免出现该情况?

    没有简单的解决办法。你需要做一个逆向色调映射运算(高消耗)。根据人眼适应度, 颜色也可能看起来不同。您可以把眼睛适应度水平对SceneTexture公开以弥补这一点。

  • 我如何得到后期处理图表的完整转储?

    r.CompositionGraphDebug 可将图表记录到控制台。示例:

    FRenderingCompositePassContext:Debug 'PostProcessing' ---------
    Node#1 'SceneColor'
        ePId_Output0 (2D 1136x768 PF_FloatRGBA RT) SceneColor Dep: 2
    Node#4 'Velocity'
        ePId_Output0 (2D 1136x768 PF_G16R16 RT) Velocity Dep: 1
    Node#2 'SceneDepthZ'
        ePId_Output0 (2D 1136x768 PF_DepthStencil) SceneDepthZ Dep: 1
    Node#5 'MotionBlurSetup0MotionBlurSetup1'
        ePId_Input0: Node#4 @ ePId_Output0 'Velocity'
        ePId_Input1: Node#1 @ ePId_Output0 'SceneColor'
        ePId_Input2: Node#2 @ ePId_Output0 'SceneDepthZ'
        ePId_Output0 (2D 568x384 PF_FloatRGBA RT) MotionBlurSetup0 Dep: 2
        ePId_Output1 (2D 568x384 PF_FloatRGBA RT) MotionBlurSetup1 Dep: 1
    Node#6 'QuarterResVelocity'
        ePId_Input0: Node#5 @ ePId_Output0 'MotionBlurSetup0MotionBlurSetup1'
        ePId_Input1:
        ePId_Output0 (2D 284x192 PF_FloatRGBA RT) QuarterResVelocity Dep: 1
    Node#7 'VelocityBlurX'
        ePId_Input0: Node#6 @ ePId_Output0 'QuarterResVelocity'
        ePId_Input1:
        ePId_Output0 (2D 284x192 PF_FloatRGBA RT) VelocityBlurX Dep: 1
    ...
Select Skin
Light
Dark

Welcome to the new Unreal Engine 4 Documentation site!

We're working on lots of new features including a feedback system so you can tell us how we are doing. It's not quite ready for use in the wild yet, so head over to the Documentation Feedback forum to tell us about this page or call out any issues you are encountering in the meantime.

We'll be sure to let you know when the new system is up and running.

Post Feedback