#|Unity - 可编程渲染管线(Scriptable Render Pipeline)

目录

  • 开始
    SRP解决了什么问题
    SRP Asset
    SRP Instance
    SRP Context
  • SRP 中的渲染
    Culling
    Drawing
  • SRP 中的 XR
  • 摄像机组件
    Free Camera
    Camera Switcher
可编程渲染管线解决了什么问题? 可编程渲染管线是一个可以通过代码控制渲染的方式的管线。
问题 传统Unity提供了一系列的内置管线供我们使用。包括前向渲染和延迟渲染。这些渲染方式是传统渲染黑盒子的缺点:
  • 它们只能按照他们本身设计的程序执行
  • 它们很一般,它们需要做每一件事,而不能掌控任何流程
  • 它们不可配置。只能在预设的位置注入一些指令
  • 拓展性和可修改性有限,内部较小的修改可能导致外部较大的变化
  • 由于改变破坏项目的行为产生Unity无法修复的Bug
解决 SRP Core API 解决了上面描述的问题。其将渲染流程从原来的黑盒转向可控制、预制件、可编程的方向。
SRP Asset SRP Asset本身是一个ScriptableObject,我们可以对其进行保存和版本控制。在GraphicsSetting中进行设置,Unity会使用SRP提供的渲染设置。SRP Asset提供了配置渲染管线的接口,当Unity实现第一次渲染的时候,其会调用InternalCreatePipelineCreatePipeline,Asset会返回一个SRP Instance。
ScriptableObject : 这是一个用于存储数据的容器。通常为了避免复制数据而占用存储空间使用。需要作为Asset存储在项目中,不能附加在游戏物体上,
[ExecuteInEditMode] public class BasicAssetPipe : RenderPipelineAsset { public Color clearColor = Color.green; #if UNITY_EDITOR // Call to create a simple pipeline [UnityEditor.MenuItem("SRP-Demo/01 - Create Basic Asset Pipeline")] static void CreateBasicAssetPipeline() { var instance = ScriptableObject.CreateInstance(); UnityEditor.AssetDatabase.CreateAsset(instance, "Assets/BasicAssetPipe.asset"); }#endifprotected override RenderPipeline CreatePipeline() { return new BasicPipeInstance(clearColor); } }

SRP Instance SRP Asset控制配置,但是SRP Instance是真正的渲染的切入点,渲染的逻辑都在SRP Instance中。SRP Instance中包括一个Render function,此方法包括两个变量:ScriptableRenderContext(Command Buffer用于排列渲染相关操作)、Camera(需要渲染的摄像机)。
public class BasicPipeInstance : RenderPipeline { private Color m_ClearColor = Color.black; public BasicPipeInstance(Color clearColor) { m_ClearColor = clearColor; }protected override void Render(ScriptableRenderContext context, Camera[] cameras) { // clear buffers to the configured color var cmd = new CommandBuffer(); cmd.ClearRenderTarget(true, true, m_ClearColor); context.ExecuteCommandBuffer(cmd); cmd.Release(); context.Submit(); } }

SRP使用Unity中的CommandBuffers提供相关操作,CommandBuffers中的顺序是根据context传入的数据排序。SRP渲染最后一步需要调用context.Submit()方法,这一步执行render context中相关指令。
SRP Context SRP渲染使用了延迟执行的方法。如果我们创建了一系列指令并执行它们。用于创建指令的的对象叫ScriptableRenderContext作为一个参数传给Render方法。
SRP中的Culling Culling包含:
  • 视锥剔除:只计算在摄像机近裁剪面和远裁剪面之间的游戏物体
  • 遮挡剔除:计算那些物体被遮挡了,并将被遮挡的物体进行剔除。
Unity开始渲染第一步是计算哪些可以渲染。这包括选择一个摄像机和进行剔除操作。提出操作返回一个被摄象机渲染的游戏物体和光照的列表。SRP将在之后的渲染管线中使用这些游戏物体。SRP提供了很多关于提出的相关API。
//Parameters controlling culling process in CullingResults ScriptableCullingParameters cullingParams; Camera.main.TryGetCullingParameters(out cullingParams); //doing culling for each camera CullingResults cullingResults = new CullingResults(); cullingResults = context.Cull(ref cullingParams);

SRP中的 Drawing 在SRP中draw需要在culling步骤完成之后进行。
在渲染管线中可配置的部分很多,有一些我们需要在工作之前进行确认:
  • 渲染管线的目标硬件
  • 想实现的特殊视觉效果
  • 项目的类型
比如2D横板过关和3D高画质PC第一人称游戏有很大的不同约束,在渲染管线中有很大的不同。以下是一些具体的选项:
  • HDR vs LDR
  • Linear vs Gamma
  • MSAA vs Post Process anti-aliasing
  • Physically-based Materials vs Simple Materials
  • Lighting vs No Lighting
  • Lighting technique
  • Shadowing technique
实例1:过滤:Render Buckets and Layers
无光照,渲染一些不透明的物体
游戏物体有很多的类别,Unity使用队列的方式对其渲染。这些队列来自Unity存放GameObjects的buckets。当SRP渲染场景的时候,可以指定buckets的范围。
在buckets,可以使用标准的Unity Layers进行过滤。
var opaqueRange = new FilteringSettings(); //FilteringSettings.renderQueueRange : Render objects whose material render queue in inside this range //这里的渲染队列在[0,GeometryLast]之间是为不透明对象,在[GeometryLast,5000]之间被视为半透明对象。 opaqueRange.renderQueueRange = new RenderQueueRange(0, (int)RenderQueue.GeometryLast); //layerMask - Only render objects in the given layer mask opaqueRange.layerMask = ~0;

实例2:绘制设置:物体如何被绘制出来的
通过前面的filtering和culling的过程,SRP决定了那些是需要渲染的对象,但是还需要进行如何绘制的设置.SRP提供了大量的可选择配置来渲染那些通过了过滤的游戏物体。用于配置的结构体叫做 DrawRenderSettings:允许我们进行配置:
  • Sorting - 渲染游戏物体的顺序,比如从前向后或从后向前
  • Per-Renderer flags - 那些内置的设置要Unity传给Shader,这包括像预置的光线探针、预置的光线贴图
  • Rendering flags - SRP batching的算法,像instancing 或者 non-instancing
  • Shader Pass - 当前渲染批次使用哪个Shader pass
//Setting for DrawRenderers.describes how to sort visible objects are sorted and which shader passes to use. //SortingSettings - This struct describes the methods to sort objects during rendering. var ds = new DrawingSettings(new ShaderTagId("Opaque"), new SortingSettings(Camera.main)); ds.enableInstancing = true; //what kind of per-object data to setup during rendering. pass lightprobe and lightmap data to each renderer ds.perObjectData = https://www.it610.com/article/PerObjectData.LightProbe | PerObjectData.Lightmaps;

创建一个DrawingSettings对象,并设置这个对象的一些属性。
在完成上面的两个步骤后就可以进行绘制了,将
Free Camera 添加一个Free Camera组件,可以让摄像机通过键盘和鼠标进行简单的的移动,在Play Mode下进行移动和旋转。
Camera Switcher 【#|Unity - 可编程渲染管线(Scriptable Render Pipeline)】Camera Switcher组件可以定义一系列相机,然后在Play Mode中通过Debug Window在这些相机之间进行切换。

    推荐阅读