Unity3D 进阶教程 - 07 URP 渲染管线深入

概述

入门系列使用的是默认渲染管线(Built-in Render Pipeline)。本系列假设你已经迁移到了 URP(通用渲染管线)——它是 Unity 的现代渲染架构,性能更好、功能更灵活。

URP 的核心优势在于 可编写渲染管线Shader Graph。本篇深入 URP 的渲染机制、配置项含义、Renderer Feature 的自定义 Pass,以及性能调优的实用技巧。

1. URP 渲染流程概览

URP 的每帧渲染流程如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
相机 ->
深度纹理(可选)
->
不透明物体 ->
前向渲染(逐物体光照计算)
->
天空盒
->
透明物体
->
后处理
->
输出到屏幕

URP 默认使用 前向渲染(Forward Rendering),适合追求性能的移动端和低端设备。相比 Built-in 管线,URP 在相同画质下通常有 1.5-2 倍的性能提升。


2. URP Asset 配置详解

URP 的质量设置通过 URP Asset 控制。建议每个平台建一个独立的 URP Asset。

2.1 关键配置项

配置项 影响 推荐值(移动端)
Main Light 主方向光阴影 Cascades=2
Additional Lights 额外点光源/聚光灯数量 Count=1, Per Vertex
Shadows 阴影质量 Max Distance=15, Soft Shadows
Post Processing 后处理开关 按需启用
Anti Aliasing 抗锯齿 MSAA 2x 或 4x
Render Scale 渲染分辨率缩放 1.0
HDR 高动态范围 开启(后处理需要)
Depth Texture 生成深度纹理 按需
Opaque Texture 生成不透明纹理 按需
1
2
3
4
5
var renderPipeline = GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset;
if (renderPipeline != null)
{
renderPipeline.renderScale = 0.75f;
}

3. Renderer Feature

Renderer Feature 是 URP 最强大的扩展机制——可以在渲染管线的特定阶段插入自定义渲染 Pass。

3.1 自定义 Renderer Feature

创建自定义渲染效果,如全屏像素化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class PixelateRenderFeature : ScriptableRendererFeature
{
[System.Serializable]
public class Settings
{
public RenderPassEvent renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing;
public Material pixelateMaterial;
[Range(1, 256)] public int pixelSize = 32;
}

public Settings settings = new();
private PixelateRenderPass _renderPass;

public override void Create()
{
_renderPass = new PixelateRenderPass(settings);
}

public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
if (settings.pixelateMaterial == null) return;
renderer.EnqueuePass(_renderPass);
}

private class PixelateRenderPass : ScriptableRenderPass
{
private readonly Settings _settings;
private RenderTargetIdentifier _cameraColorTarget;
private RenderTextureDescriptor _descriptor;

public PixelateRenderPass(Settings settings)
{
_settings = settings;
renderPassEvent = settings.renderPassEvent;
}

public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
{
_cameraColorTarget = renderingData.cameraData.renderer.cameraColorTargetHandle;
_descriptor = renderingData.cameraData.cameraTargetDescriptor;
}

public override void Execute(ScalableBufferManager context, ref RenderingData renderingData, CommandBuffer cmd)
{
var tempTex = Shader.PropertyToID("_TempTex");
cmd.GetTemporaryRT(tempTex, _descriptor.width / _settings.pixelSize,
_descriptor.height / _settings.pixelSize, 0, FilterMode.Point);

cmd.Blit(_cameraColorTarget, tempTex);
cmd.Blit(tempTex, _cameraColorTarget, _settings.pixelateMaterial);
cmd.ReleaseTemporaryRT(tempTex);
}
}
}

4. SRP Batcher

SRP Batcher 是 URP 的核心性能特性。它通过 持久化的着色器数据缓冲区 减少 CPU 设置渲染状态的开销。

4.1 兼容性要求

SRP Batcher 对着色器的要求:

  • 所有材质属性通过 CBUFFER_START(UnityPerMaterial) 声明
  • 内置 Lit/LitTessellation 着色器默认兼容
  • 自定义着色器需要手动适配
1
2
3
4
5
CBUFFER_START(UnityPerMaterial)
float4 _BaseColor;
float _Metallic;
float _Smoothness;
CBUFFER_END

4.2 为什么 SRP Batcher 没有生效

原因 解决办法
使用了不兼容的着色器 检查自定义着色器是否有 CBUFFER
使用了 Material.SetProperty 用 PropertyBlock 替代
材质数量过多(>100) 合并材质或减少变体
启用了 GPU Instancing 两者不能同时使用,优先 SRP Batcher

5. 常见问题排查

5.1 后处理不生效

1
2
3
4
5
确认:
1. URP Asset 勾选了 Post Processing
2. 相机组件勾选了 Post Processing
3. 场景中有 Global Volume
4. Volume 的 Profile 包含了效果组件

5.2 材质变紫

1
2
3
确认着色器是否兼容 URP:
- Built-in 的 Standard 着色器在 URP 中会显示紫色
- 需要替换为 URP/Lit 或 URP/Unlit

总结

  • URP 通过 SRP Batcher变体剥离 实现大幅性能提升
  • Renderer Feature 是扩展渲染效果的标准方式
  • 自定义渲染 Pass 通过 ScriptableRenderPass 实现
  • 多平台使用不同的 URP Asset 配置
  • Frame Debugger 是排查渲染问题的最佳工具

下一篇将深入 Shader Graph 与着色器基础,带你从可视化编程过渡到自定义 HLSL。

ByteFisher
分享编程技术 · 记录钓鱼乐趣
扫码关注
▸ 扫码关注 ◂
分享: