Unity3D LWRP轻量级渲染之构建SRP管线

LWRP 轻量级渲染

根据官方给出的PPT以及大致的说明
LWRP 是精简并且优化过的渲染管线、主要聚焦性能、针对移动平台
所以开坑 LWRP,至于HDRP这个主要用于高性能的主机和PC上,目前不做端游,暂不考虑


  • 高性能和高一致性的PBR
  • 新的Shader库
  • 一次渲染多个实时光
  • 可插入 Scriptable Render Passes 的 API

Unity Test Version: 2019.3.0.f1


而 Scriptable Render Passes 是由C#代码来完成渲染管线的编写。在Unity 高版本中(笔者 Unity2019 3.0.f1)通过Editor -> Project Setting -> Graphices [ Scriptable Render Pipeline Settings ] 来设置我们自定义的管线配置。

示意图:

image.png

那么 Scriptable Render Pipeline Settings 需要指定什么文件?

在Unity中,官方的配置都是基于 ScriptableObject可序列化的配置,我们先尝试写下代码。

[ExecuteInEditMode]
public class BasePipelineAsset_test : RenderPipelineAsset
{
#if UNITY_EDITOR
    [UnityEditor.MenuItem("RenderPipeline/Create BasePipelineAsset")]
    public static void CreateBasePipelineAsset()
    {
        var instances = ScriptableObject.CreateInstance<BasePipelineAsset_test>();
        UnityEditor.AssetDatabase.CreateAsset(instances, "Assets/Pipelines/BasePiplineAsset.asset");
    }
#endif

    protected override RenderPipeline CreatePipeline()
    {
        return null;
    }
//这是一份自定义的序列化管线配置。
}

到此我们可以通过菜单 RenderPipeline => Create BasePipelineAsset创建一个管线配置,之后把创建 OK 的配置拖入 Scriptable Render Pipeline Settings 中,为此管线配置创建完成,然后看看Scene 和 Game 视图。

image.png

全黑!别担心,这是没问题的,因为此时我们还没开始渲染任何东西。

到了这一步,我们主相机没用了吗?然而并不是!我们看接下来的代码!

首先我们抽象一个基类:

public abstract class BasicRenderPipeline : RenderPipeline
{
    protected CommandBuffer command;

    [SerializeField] protected Color m_ClearColor;
    public BasicRenderPipeline()
    {
        command = new CommandBuffer();
    }
    public BasicRenderPipeline(Color clear) : this()
    {
        this.m_ClearColor = clear;
    }

    protected override void Render(ScriptableRenderContext context, Camera[] cameras)
    {
        foreach (Camera c in cameras)
        {
            this.Render(context, c);
        }
    }
    protected abstract void Render(ScriptableRenderContext context, Camera camera);
}

然后我们通过继承来创建一个管道:

public class MainPipeline : BasicRenderPipeline
{
    public MainPipeline(Color clear) : base(clear){ }

    protected override void Render(ScriptableRenderContext context, Camera camera)
    {
        command.Clear();
        command.ClearRenderTarget(true, true, this.m_ClearColor);
        context.ExecuteCommandBuffer(command);
        context.Submit();
    }
}

这样若后续有多条管道,我们都可以通过继承的方式来完成,渲染主要写在基类抽象出来的Render函数。

最后在 BasePipelineAsset_test 类中 CreatePipeline 函数中返回我们编写的管道 MainPipeline

[ExecuteInEditMode]
public class BasePipelineAsset_test : RenderPipelineAsset
{
#if UNITY_EDITOR
    [UnityEditor.MenuItem("RenderPipeline/Create BasePipelineAsset")]
    public static void CreateBasePipelineAsset()
    {
        var instances = ScriptableObject.CreateInstance<BasePipelineAsset_test>();
        UnityEditor.AssetDatabase.CreateAsset(instances, "Assets/Pipelines/BasePiplineAsset.asset");
    }
#endif

    protected override RenderPipeline CreatePipeline()
    {
        return new MainPipeline(Color.grey);
    }

}

这条管道仅仅是清空了颜色(灰色做基色),返回Unity,我们就可以看的效果了,但是有个问题,就是当屏幕的分辨率不是常规像什么16:9之类,会出现部分颜色无法清空。

异常图一:

图一

我们可以看的Scene视图是已经清空了的,但是Game视图,scale 约趋近 1 颜色清理较为 '干净'。

异常图二:

图二

当我们尝试缩放屏幕就会发现问题了,这个问题解决起来也很简单。

在管道渲染的函数中指定设置相机的属性,若不指定,估计我们的相机也变得没有任何L用(作用应该会有,就是可以遍历我们的管道 = 。=)

修改后的代码:

public class MainPipeline : BasicRenderPipeline
{
    public MainPipeline(Color clear) : base(clear){ }

    protected override void Render(ScriptableRenderContext context, Camera camera)
    {
        command.Clear();
        context.SetupCameraProperties(camera);
        command.ClearRenderTarget(true, true, this.m_ClearColor);
        context.ExecuteCommandBuffer(command);
        context.Submit();
    }
}

OK,这样不管怎样缩放,相机的参数都起作用了

猜你喜欢

转载自blog.csdn.net/mango9126/article/details/108876540