故障排除
本节举例说明了使用 Custom Pass 组件时可能遇到的常见问题,并介绍如何解决这些问题。
显示缩放问题
当有两个摄像机未使用相同的分辨率时,构建中可能会出现缩放问题。这种情况在游戏内视图和 Scene 视图之间最常见。在以下情况下会发生此问题:
- 代码调用了 CommandBuffer.SetRenderTarget,并由
CoreUtilsSetRenderTarget
设置了视口。 - 对
RTHandle
缓冲区进行采样时,在着色器代码中没有针对 UV 乘以_RTHandleScale.xy
。
要根除这些情况下的起因,请执行以下操作:
- 使用
CoreUtils.SetRenderTarget
代替CommandBuffer.SetRenderTarget
。 - 对
RTHandle
缓冲区进行采样时,在着色器代码中使用_RTHandleScale.xy
。
不透明对象在构建中消失
在构建程序时,如果场景中具有不透明材质的游戏对象消失,可能需要重新配置 HDRP 资源设置。
要解决此问题:
- 在 Project 窗口中,导航至 HDRenderPipelineAsset(如果使用的是默认 HDRP 构建,请选择
Assets > Settings
)。 - 在 HDRP 资源中,将 Lit Shader Mode 更改为 Both。
启用 TAA 时游戏对象发生抖动
在某些情况下,启用时间抗锯齿 (TAA) 后,一些游戏对象看起来会抖动。
同时满足以下两个条件时,可能会发生抖动:
- 在 AfterPostProcess 注入点 (Injection Point) 中渲染此对象。要解决此问题,请更改 Custom Pass Volume 组件中的 Injection Point。
- 此对象已启用 Depth Test。要解决此问题,请禁用着色器属性中的 Depth Test,或者将绘制渲染器 Custom Pass 组件中的 Depth Test 属性设置为 Disabled。
Shuriken 粒子的方向错误
以下情况可能导致场景中的粒子面向错误方向:
- 粒子系统仅在自定义通道中可见。
- 没有为
AggregateCullingParameters
实现覆盖。
在剔除步骤中执行 AggregateCullingParameters
时,Unity 会计算内置粒子系统中的粒子方向。因此,如果没有覆盖,HRDP 就无法正确渲染粒子。
贴花不可见
以下情况会使场景中的贴花不可见:
- 贴花被应用于 Unity 在自定义通道中渲染的游戏对象
- 贴花位于 Unity 在 AfterOpaqueDepthAndNormal 注入点之前渲染的透明对象上
要解决此问题,请将游戏对象的注入点更改为 AfterOpaqueDepthAndNormal 之后的任何注入点
剔除问题
如果在场景中看不到某些对象,可能是因为在 Execute
方法中收到的 cullingResult
未包含 HDRP 仅在自定义通道中渲染的对象。
如果在摄像机剔除遮罩中禁用对象层,可能会发生此问题。
发生此问题的原因是,默认情况下,此 cullingResult
是摄像机 cullingResult
。要解决此问题,请在 CustomPass
类中重载此方法:
protected virtual void AggregateCullingParameters(ref ScriptableCullingParameters cullingParameters, HDCamera camera) {}
然后,可使用 ScriptableCullingParameters 向 Execute
方法中接收的 cullingResult
添加更多层或自定义剔除选项。
Unity 加载着色器时发生黑屏
如果在 Unity 加载着色器时发生黑屏,可能是因为 Unity 尝试渲染场景中未引用的着色器。在以下情况下会发生此问题:
- 自定义通道仅使用
Shader.Find
来查找着色器。 - 尚未将着色器包含在 Resources 文件夹中。
- 未在自定义通道中引用着色器。
要解决此问题,可以添加以下代码行,在自定义通道中引用着色器:
[SerializeField, HideInInspector]
Shader shaderName;
例如:
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
class Outline : CustomPass
{
public LayerMask outlineLayer = 0;
[ColorUsage(false, true)]
public Color outlineColor = Color.black;
public float threshold = 1;
// 为了确保着色器最终出现在构建中,我们保留对着色器的引用
[SerializeField, HideInInspector]
Shader outlineShader;
Material fullscreenOutline;
RTHandle outlineBuffer;
protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd)
{
outlineShader = Shader.Find("Hidden/Outline");
fullscreenOutline = CoreUtils.CreateEngineMaterial(outlineShader);
// 定义轮廓缓冲区
outlineBuffer = RTHandles.Alloc(
Vector2.one, TextureXR.slices, dimension: TextureXR.dimension,
colorFormat: GraphicsFormat.B10G11R11_UFloatPack32,
// 此效果无需 Alpha
useDynamicScale: true, name: "Outline Buffer"
);
}
protected override void Execute(CustomPassContext ctx)
{
// 渲染所需网格,从而在轮廓缓冲区中应用轮廓效果
CoreUtils.SetRenderTarget(ctx.cmd, outlineBuffer, ClearFlag.Color);
CustomPassUtils.DrawRenderers(ctx, outlineLayer);
// 设置轮廓效果属性
ctx.propertyBlock.SetColor("_OutlineColor", outlineColor);
ctx.propertyBlock.SetTexture("_OutlineBuffer", outlineBuffer);
ctx.propertyBlock.SetFloat("_Threshold", threshold);
// 全屏渲染轮廓缓冲区
CoreUtils.SetRenderTarget(ctx.cmd, ctx.cameraColorBuffer, ClearFlag.None);
CoreUtils.DrawFullScreen(ctx.cmd, fullscreenOutline, ctx.propertyBlock, shaderPassId: 0);
}
protected override void Cleanup()
{
CoreUtils.Destroy(fullscreenOutline);
outlineBuffer.Release();
}
}