4.2 可编程渲染管线 (SRP) (URP, HDRP) 4.2 可编程渲染管线 (SRP) (URP, HDRP) 4.2.1 SRP 的核心概念 传统的内置渲染管线是一个“黑盒”,虽然易于上手,但缺乏定制性和优化空间。SRP 的出现旨在解决这一问题,它将渲染过程模块化,并开放了关键渲染阶段的控制权给开发者。SRP 的核心思想是可编程性,这意味着渲染管线的行为不再是固定的,而是可以通过脚本代码进行自定义和扩展。 SRP 的主要组成部分包括: ScriptableRenderPipelineAsset (SRP Asset): 这是 SRP 的核心配置文件,定义了渲染管线的全局设置,例如渲染路径、资源配置等。项目需要使用哪种 SRP,就需要创建并配置对应的 SRP Asset。
传统的内置渲染管线是一个“黑盒”,虽然易于上手,但缺乏定制性和优化空间。SRP 的出现旨在解决这一问题,它将渲染过程模块化,并开放了关键渲染阶段的控制权给开发者。SRP 的核心思想是可编程性,这意味着渲染管线的行为不再是固定的,而是可以通过脚本代码进行自定义和扩展。
SRP 的主要组成部分包括:
ScriptableRenderPipelineAsset (SRP Asset): 这是 SRP 的核心配置文件,定义了渲染管线的全局设置,例如渲染路径、资源配置等。项目需要使用哪种 SRP,就需要创建并配置对应的 SRP Asset。URP 和 HDRP 各有其独立的 SRP Asset 类型。
Renderer (渲染器): 渲染器负责实际的渲染执行。URP 和 HDRP 都有默认的渲染器实现,例如 URP 的 ForwardRenderer 和 HDRP 的 HDRenderPipeline。渲染器内部包含一系列的 Render Pass (渲染通道),这些 Pass 按照特定的顺序执行,完成整个渲染流程。
Render Pass (渲染通道): 渲染通道是 SRP 中最基本的渲染单元,负责执行特定的渲染任务,例如深度预通道、不透明物体渲染、透明物体渲染、后处理等。开发者可以自定义 Render Pass 来扩展渲染管线的功能,例如实现自定义的渲染效果或优化特定的渲染流程。
Render Features (渲染特性): Render Feature 是对 Render Pass 的封装和扩展,它提供了一种更便捷的方式来添加和管理自定义的渲染功能。开发者可以将多个相关的 Render Pass 组合成一个 Render Feature,并通过 Inspector 界面进行配置和启用。
Shader Graph 集成: SRP 与 Shader Graph 深度集成,允许开发者使用节点式的可视化编辑器创建自定义 Shader,这些 Shader 可以与 SRP 管线无缝协作,充分发挥 SRP 的可编程性优势。
我们可以用下图来概括 SRP 的基本架构:
通用渲染管线 (Universal Render Pipeline, URP),原名轻量级渲染管线 (Lightweight Render Pipeline, LWRP),旨在提供一个高性能、可扩展、跨平台的渲染解决方案。URP 适用于广泛的平台,包括移动设备、Web、VR/AR 以及低端到中端 PC 和主机。它在性能和画面质量之间取得了良好的平衡,非常适合需要高效渲染和快速迭代的项目。
URP 的主要特点:
前向渲染路径 (Forward Rendering Path): URP 主要采用前向渲染路径,这是一种相对简单的渲染方式,非常适合移动平台和需要高性能的应用。前向渲染路径对于每个物体,都会对场景中的每个光源进行计算,因此光源数量增加会显著影响性能。
单 Pass 光照 (Single-Pass Lighting): URP 默认使用单 Pass 光照,优化了前向渲染的性能。
基于物理的渲染 (Physically Based Rendering, PBR): URP 支持 PBR 材质,可以实现更真实的光照和材质效果。
后处理效果 (Post-Processing Effects): URP 集成了后处理框架,可以方便地添加各种屏幕后处理效果,例如 Bloom、Color Grading、Depth of Field 等。
Shader Graph 支持: URP 与 Shader Graph 深度集成,可以方便地创建自定义的 URP Shader。
可扩展性: URP 提供了 Render Features 和 Render Pass API,允许开发者自定义渲染流程,添加自定义效果和优化。
优化的性能: URP 经过优化,在各种平台上都能提供良好的性能表现。
URP 的应用场景:
移动游戏开发: URP 是移动游戏开发的首选渲染管线,因为它在性能和画面质量之间取得了最佳平衡。
VR/AR 开发: VR/AR 应用对性能要求极高,URP 的高性能特性使其成为 VR/AR 开发的理想选择。
低端到中端 PC 和主机游戏: 对于预算有限或者追求流畅帧率的游戏,URP 也是一个不错的选择。
快速原型开发: URP 易于上手和配置,非常适合快速原型开发和迭代。
教育和学习: URP 的结构相对简单,更易于学习和理解 SRP 的原理和自定义方法。
URP 代码实践:自定义 Render Feature 和 Render Pass
为了更好地理解 URP 的可编程性,我们来创建一个简单的自定义 Render Feature 和 Render Pass,实现一个简单的颜色调整效果。
1. 创建 Render Pass 脚本 ColorAdjustRenderPass.cs:
using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; public class ColorAdjustRenderPass : ScriptableRenderPass { private Material colorAdjustMaterial; private Color colorTint = Color.white; private RenderTargetIdentifier source; private RenderTargetIdentifier destination; private string tag; public ColorAdjustRenderPass(string tag) { this.tag = tag; // 创建材质,使用内置的 URP Post-processing Shader 中的 Color Grading 效果 colorAdjustMaterial = new Material(Shader.Find("Universal Render Pipeline/Post-Processing/ColorGrading")); } // 配置 Render Pass,例如设置渲染目标、清除标志等 public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) { // 获取渲染纹理描述符 RenderTextureDescriptor descriptor = cameraTextureDescriptor; // 不需要深度纹理 descriptor.depthBufferBits = 0; // 创建临时渲染纹理,用于中间处理 cmd.GetTemporaryRT(Shader.PropertyToID("_TempColorAdjustTexture"), descriptor, FilterMode.Bilinear); destination = new RenderTargetIdentifier("_TempColorAdjustTexture"); } // 设置 Render Pass 需要的参数 public void SetTarget(RenderTargetIdentifier source) { this.source = source; } public void SetColorTint(Color color) { this.colorTint = color; if (colorAdjustMaterial != null) { colorAdjustMaterial.SetColor("_ColorFilter", colorTint); // 使用 Color Filter 属性进行颜色调整 } } // 执行 Render Pass 的渲染逻辑 public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { if (colorAdjustMaterial == null) return; CommandBuffer cmd = CommandBufferPool.Get(tag); cmd.Clear(); // 将源纹理 Blit 到临时纹理,并应用颜色调整材质 Blit(cmd, source, destination, colorAdjustMaterial, 0); // Pass 0 对应 Color Grading 效果 // 将临时纹理 Blit 回到渲染目标 Blit(cmd, destination, source); context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); } // 在 Render Pass 执行完毕后清理资源,例如释放临时渲染纹理 public override void FrameCleanup(CommandBuffer cmd) { cmd.ReleaseTemporaryRT(Shader.PropertyToID("_TempColorAdjustTexture")); } }
2. 创建 Render Feature 脚本 ColorAdjustRenderFeature.cs:
using UnityEngine; using UnityEngine.Rendering.Universal; public class ColorAdjustRenderFeature : ScriptableRendererFeature { public Color colorTint = Color.white; private ColorAdjustRenderPass colorAdjustPass; // 在 Render Feature 创建时调用,用于创建 Render Pass 实例 public override void Create() { colorAdjustPass = new ColorAdjustRenderPass("Color Adjust Pass"); colorAdjustPass.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing; // 在后处理之后执行 } // 在每次渲染帧之前调用,用于配置 Render Pass public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { if (colorAdjustPass == null) return; // 设置 Render Pass 的渲染目标为当前渲染管线的颜色目标 colorAdjustPass.SetTarget(renderer.cameraColorTarget); // 设置颜色调整参数 colorAdjustPass.SetColorTint(colorTint); // 将 Render Pass 添加到渲染队列中 renderer.EnqueuePass(colorAdjustPass); } }
3. 创建 URP Asset 和 Renderer Data:
如果你的项目还没有使用 URP,需要先导入 URP 包 (Window -> Package Manager -> Universal RP)。
在 Project 窗口中右键单击,选择 Create -> Rendering -> URP Asset (with Universal Renderer) 创建 URP Asset 和 Universal Renderer Data。
将创建的 URP Asset 应用到 Graphics Settings (Edit -> Project Settings -> Graphics) 中的 Scriptable Render Pipeline Settings。
4. 将 Render Feature 添加到 Renderer Data:
在 Project 窗口中选中创建的 Universal Renderer Data 资源。
在 Inspector 窗口中,点击 Add Renderer Feature 按钮,选择 Color Adjust Render Feature。
在 Inspector 窗口中,可以调整 Color Tint 属性来控制颜色调整效果。
运行效果:
运行场景,你会发现整个画面颜色被 Color Tint 属性指定的颜色所调整。你可以尝试修改 Color Tint 颜色,观察画面变化。
代码解释:
ColorAdjustRenderPass.cs 定义了一个自定义的 Render Pass,它使用内置的 Universal Render Pipeline/Post-Processing/ColorGrading Shader 中的 Color Grading 效果来实现颜色调整。Execute 函数中使用了 Blit 命令将源纹理 Blit 到目标纹理,并应用了材质。
ColorAdjustRenderFeature.cs 定义了一个 Render Feature,它创建并管理 ColorAdjustRenderPass 实例,并将该 Pass 添加到 URP 渲染管线中。AddRenderPasses 函数在每帧渲染前被调用,用于配置 Render Pass 的参数和渲染目标。
通过将 Render Feature 添加到 Universal Renderer Data 中,并将 Renderer Data 应用到 URP Asset,我们就成功地将自定义的颜色调整效果集成到了 URP 渲染管线中。
URP 渲染流程图 (简化版):
这个简化的流程图展示了 URP 的主要渲染阶段,我们的自定义 Render Feature ColorAdjustRenderFeature 被插入到了 Post-Processing 阶段之后。
高清渲染管线 (High Definition Render Pipeline, HDRP) 旨在为高端平台(例如高性能 PC 和主机)提供极致的画面质量和照片级真实感。HDRP 提供了先进的渲染技术和功能,可以实现电影级别的视觉效果。然而,HDRP 对硬件性能要求较高,不适合移动设备和低端平台。
HDRP 的主要特点:
延迟渲染和前向渲染路径 (Deferred and Forward Rendering Paths): HDRP 支持延迟渲染和前向渲染两种路径。延迟渲染可以处理大量光源,并实现高质量的光照效果,但对显存带宽要求较高。前向渲染则更适合处理透明物体和某些特殊效果。HDRP 允许开发者根据需求选择合适的渲染路径。
基于物理的渲染 (Physically Based Rendering, PBR) 高级实现: HDRP 提供了更高级的 PBR 实现,包括更精确的光照模型、材质模型和环境光照。
体积光照和雾效 (Volumetric Lighting and Fog): HDRP 支持高质量的体积光照和雾效,可以营造更逼真的大气效果。
屏幕空间反射 (Screen Space Reflection, SSR) 和光线追踪反射 (Ray Tracing Reflection): HDRP 提供了 SSR 和光线追踪反射两种反射技术,可以实现高质量的反射效果。光线追踪反射需要支持光线追踪的硬件。
光线追踪阴影 (Ray Tracing Shadows): HDRP 支持光线追踪阴影,可以生成更精确、柔和的阴影效果。
全局光照 (Global Illumination, GI): HDRP 提供了多种全局光照解决方案,包括屏幕空间全局光照 (SSGI) 和光线追踪全局光照 (RTGI),可以实现更真实的光照反弹效果。
高级后处理效果 (Advanced Post-Processing Effects): HDRP 提供了更丰富的后处理效果,例如胶片颗粒、色差、运动模糊等,可以增强画面表现力。
Shader Graph 高级功能: HDRP 的 Shader Graph 提供了更多高级节点和功能,可以创建更复杂的 HDRP Shader。
可扩展性: HDRP 也提供了 Render Features 和 Render Pass API,允许开发者自定义渲染流程,但 HDRP 的管线结构更为复杂。
HDRP 的应用场景:
高端 PC 和主机游戏开发: HDRP 是开发具有照片级真实感的高端游戏的首选渲染管线。
电影和动画制作: HDRP 的高质量渲染效果使其也适用于电影和动画制作领域。
建筑可视化和工业设计: HDRP 可以用于创建逼真的建筑可视化和工业设计演示。
需要极致画面质量的应用: 任何对画面质量有极高要求的项目都可以考虑使用 HDRP。
HDRP 代码实践:自定义 Render Pass (概念示例)
由于 HDRP 的管线结构比 URP 复杂得多,自定义 Render Pass 的过程也更加复杂。这里我们提供一个概念性的代码示例,展示 HDRP 中自定义 Render Pass 的基本思路。请注意,HDRP 的 API 相对复杂,需要更深入的学习和实践才能熟练掌握。
using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; public class HDRPCustomRenderPass : CustomPass { public Material customMaterial; // 自定义材质 protected override void Execute(CustomPassContext ctx) { if (customMaterial == null) return; // 获取渲染命令缓冲区 CommandBuffer cmd = ctx.cmd; // 设置渲染目标 (例如,渲染到颜色缓冲区) RTHandle colorBuffer = ctx.cameraColorBuffer; if (colorBuffer == null) return; // 确保颜色缓冲区有效 // 设置渲染状态 (例如,剔除、深度测试等) RenderStateBlock renderStateBlock = new RenderStateBlock(RenderStateMask.Raster | RenderStateMask.Depth); renderStateBlock.rasterState = new RasterState() { cullMode = CullMode.Back }; renderStateBlock.depthState = new DepthState() { writeEnabled = false, compareFunction = CompareFunction.LessEqual }; // 绘制全屏 Quad,应用自定义材质 // 注意:HDRP 中通常使用 HDUtils.DrawFullScreen 绘制 HDUtils.DrawFullScreen(cmd, customMaterial, colorBuffer, null, renderStateBlock, shaderPassId: 0); } protected override void Cleanup() { // 释放资源 (如果需要) } }
代码解释 (概念性):
HDRPCustomRenderPass.cs 继承自 CustomPass,这是 HDRP 中自定义渲染通道的基类。
Execute 函数是 Render Pass 的执行入口。
CustomPassContext ctx 提供了访问渲染上下文的接口,例如命令缓冲区、渲染目标等。
ctx.cmd 获取当前的命令缓冲区,用于执行渲染命令。
ctx.cameraColorBuffer 获取当前的相机颜色缓冲区,可以作为渲染目标。
HDUtils.DrawFullScreen 是 HDRP 中用于绘制全屏 Quad 的工具函数,方便应用后处理效果或自定义渲染。
RenderStateBlock 用于设置渲染状态,例如剔除模式、深度测试等。
HDRP 渲染流程图 (简化版):
这个简化的流程图展示了 HDRP 的主要渲染阶段,可以看到 HDRP 比 URP 多了 Depth Prepass 和 GBuffer Pass 等阶段,以及更复杂的光照和后处理流程。
URP 和 HDRP 代表了 Unity 渲染管线的两个主要方向,它们各有优势和适用场景。在选择 SRP 时,需要根据项目的具体需求进行权衡:
| 特性 | URP (通用渲染管线) | HDRP (高清渲染管线) |
|---|---|---|
| 目标平台 | 移动设备、Web、VR/AR、低端到中端 PC/主机 | 高端 PC、主机 |
| 画面质量 | 良好,可满足大部分项目需求 | 极致,照片级真实感 |
| 性能 | 高效,性能优化良好 | 性能要求高,需要高性能硬件支持 |
| 渲染路径 | 前向渲染为主 | 延迟渲染和前向渲染 |
| 光照模型 | PBR (单 Pass 光照) | 高级 PBR (更精确的光照模型、体积光照、光线追踪) |
| 反射 | 屏幕空间反射 (SSR) | 屏幕空间反射 (SSR) 和光线追踪反射 (RT Reflection) |
| 阴影 | 阴影贴图 | 阴影贴图和光线追踪阴影 (RT Shadow) |
| 全局光照 | 屏幕空间全局光照 (SSGI) | 屏幕空间全局光照 (SSGI) 和光线追踪全局光照 (RTGI) |
| 后处理 | 基础后处理效果 | 高级后处理效果 (胶片颗粒、色差、运动模糊等) |
| Shader Graph | URP Shader Graph | HDRP Shader Graph (更多高级节点和功能) |
| 可扩展性/自定义 | 良好,相对简单 | 复杂,但功能强大 |
| 易用性/学习曲线 | 简单易用,学习曲线平缓 | 复杂,学习曲线陡峭 |
| 项目复杂度 | 适合中小规模项目,快速迭代 | 适合大型项目,追求极致画面质量 |
| 资源消耗 | 较低 | 较高 (显存、计算资源) |
选择建议:
如果你的项目目标平台主要是移动设备、Web、VR/AR 或低端到中端 PC/主机,并且注重性能和效率,URP 是更好的选择。 URP 提供了良好的画面质量,同时保持了高性能和跨平台兼容性。
如果你的项目目标平台是高端 PC 或主机,并且追求极致的画面质量和照片级真实感,HDRP 是更好的选择。 HDRP 提供了最先进的渲染技术和功能,可以实现电影级别的视觉效果,但需要高性能硬件支持。
总结:
SRP 的出现是 Unity 渲染技术发展的重要里程碑,它赋予开发者更强大的渲染控制能力和定制灵活性。URP 和 HDRP 作为 Unity 官方提供的两种 SRP,分别面向不同的应用场景和目标平台。理解 SRP 的核心概念,掌握 URP 和 HDRP 的特性和使用方法,将有助于开发者构建更高效、更具表现力的 Unity 项目。通过自定义 Render Features 和 Render Passes,我们可以进一步扩展和优化渲染管线,实现各种自定义的渲染效果和性能优化。 深入学习和实践 SRP 技术,将成为现代 Unity 开发者必备的技能之一。