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<BasicAssetPipe>();
        UnityEditor.AssetDatabase.CreateAsset(instance, "Assets/BasicAssetPipe.asset");
    }


#endif

    protected 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 = PerObjectData.LightProbe | PerObjectData.Lightmaps;

创建一个DrawingSettings对象,并设置这个对象的一些属性。

在完成上面的两个步骤后就可以进行绘制了,将

Free Camera

添加一个Free Camera组件,可以让摄像机通过键盘和鼠标进行简单的的移动,在Play Mode下进行移动和旋转。

Camera Switcher

Camera Switcher组件可以定义一系列相机,然后在Play Mode中通过Debug Window在这些相机之间进行切换。

你可能感兴趣的:(#,Unity开发之路)