srp第一講代碼註釋

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
using Conditional = System.Diagnostics.ConditionalAttribute;

public class MyPipeline : RenderPipeline
{
    CullResults cull;
    Material errorMaterial;
    //這個給commandbuffer一個名字,否則在FrameDebugger中處在的名字是默認的名字"Unnamed command buffer"
    CommandBuffer cameraBuffer = new CommandBuffer { name = "xxddxxxxxx" };

    int count = 0;
    public override void Render(ScriptableRenderContext renderContext, Camera[] cameras)
    {
        base.Render(renderContext, cameras);
        //string str = "xxx = " + count;
        //Debug.LogError(str);
        //AddLog(str);

        //count++;
        //str = "time frame count = " + Time.frameCount;
        //Debug.LogError(str);
        //AddLog(str);

        for (int i = 0; i < cameras.Length; ++i)
        {
            //str = "i=" + i + "  name=" + cameras[i].name + " type = " + cameras[i].cameraType;
            //Debug.LogError(str);
            //AddLog(str);
        }
        foreach (var camera in cameras)
        {
            Render(renderContext, camera);
        }
    }

    private static void AddLog(string str)
    {
        if (Log._instance != null)
        {
            Log._instance.SetContent(str);
        }
    }

    void Render(ScriptableRenderContext context, Camera camera)
    {
        //參考:https://catlikecoding.com/unity/tutorials/scriptable-render-pipeline/custom-pipeline/
        //註釋1:GetCullingParameters
        //參數:相機+out parameters
        //返回值:能否正確創建參數
        //功能:爲了得到剔除參數
        ScriptableCullingParameters cullingParameters;
        if (!CullResults.GetCullingParameters(camera, out cullingParameters))
        {
            return;
        }

        //註釋2:EmitWorldGeometryForSceneView
        //參數:相機
        //返回值:無
        //功能:讓UI在scene window下顯示出來(繪製)
        //調用順序:在Cull之前調用
#if UNITY_EDITOR
        if (camera.cameraType == CameraType.SceneView)
        {
            ScriptableRenderContext.EmitWorldGeometryForSceneView(camera);
        }
#endif

        //註釋3:Cull
        //參數:剔除參數,srp上下文,剔除結果
        //返回值:無
        //功能:得到可見的物體
        CullResults.Cull(ref cullingParameters, context, ref cull);

        //註釋4:SetupCameraProperties
        //參數:相機
        //返回值:無
        //功能:設置相機的屬性,vp矩陣
        context.SetupCameraProperties(camera);

        //註釋5:ClearRenderTarget
        //這裏是設置一個commandbuffer,在所有的繪製之前,要進行一次清除,防止受到
        //之前渲染結果的影響
        CameraClearFlags clearFlags = camera.clearFlags;
        cameraBuffer.ClearRenderTarget(
            (clearFlags & CameraClearFlags.Depth) != 0,
            (clearFlags & CameraClearFlags.Color) != 0,
            camera.backgroundColor
        );
        //cameraBuffer.ClearRenderTarget(true, true, Color.red); //這個是硬編碼,不如採取上面的根據相機的配置進行清除好

        //註釋5.1:如果這個放在ClearRenderTarget之前會有一個冗餘的節點,可以嘗試下。
        //添加一個命令:BeginSample
        cameraBuffer.BeginSample("xxddxxxxxx");

        //註釋6:BeginSample
        //參數:採樣的名字,任意取,但是和EndSample的名字要相同
        //返回值:無
        //功能:爲了在Frame Debugger中有層級的調試效果

        //註釋7:ExecuteCommandBuffer
        //new一個commandbuffer,註釋申請了資源用以存儲command
        //ExecuteCommandBuffer,不是立刻執行了command,而是拷貝資源到context中
        //見https://catlikecoding.com/unity/tutorials/scriptable-render-pipeline/custom-pipeline/
        //We can instruct the context to execute the buffer via its ExecuteCommandBuffer method. 
        //Once again, this doesn't immediately execute the commands, but copies them to the internal buffer of the context.
        context.ExecuteCommandBuffer(cameraBuffer);
        //buffer.Release();這個是釋放了,但是我們想重用一個buffer,則可以進行一次創建,然後Clear的方式。
        cameraBuffer.Clear();

        //註釋8:DrawRendererSettings
        //參數:要繪製的相機,要使用shader的哪個pass進行繪製
        //Tags { "RenderType"="Opaque" "LightMode"="SRPDefaultUnlit2"} 是LightMode的值
        var drawSettings = new DrawRendererSettings(camera, new ShaderPassName("SRPDefaultUnlit2"));
        drawSettings.sorting.flags = SortFlags.CommonOpaque;

        //註釋9:FilterRenderersSettings
        //參數:true,表示是否初始化;這裏傳入繪製的隊列爲不透明
        var filterSettings = new FilterRenderersSettings(true) { renderQueueRange = RenderQueueRange.opaque };

        //註釋10:DrawRenderers
        //參數:繪製的物件,繪製設置,過濾設置
        //返回值:無
        //功能:繪製要顯示的render,這個不是真正的繪製
        context.DrawRenderers(cull.visibleRenderers, ref drawSettings, filterSettings);

        //註釋11:繪製天空盒,天空也是不透明的,爲啥要在不透明物體之後繪製呢?
        //測了下,天空盒的renderqueue=1000,那麼即使在後面繪製,有序深度寫入,那麼能夠正確繪製
        //這裏爲啥要後繪製天空盒呢?我認爲是爲了防止overdraw的問題。
        //如果天空盒先繪製了,然後再繪製不透明物體,這樣被不透明物體這段的那部分,就又要重新繪製。
        //而如果是先繪製不透明物體,然後再繪製天空盒,天空盒的z大於不透明物體,所以被不透明物體遮擋的部分,就不用繪製了。
        context.DrawSkybox(camera);

        //註釋12:繪製透明物體
        drawSettings.sorting.flags = SortFlags.CommonTransparent;
        filterSettings.renderQueueRange = RenderQueueRange.transparent;
        context.DrawRenderers(cull.visibleRenderers, ref drawSettings, filterSettings);

        //註釋13:繪製默認管線的物體
        DrawDefaultPipeline(context, camera);

        //註釋14:加入一個名字用以結尾BeginSample
        cameraBuffer.EndSample("xxddxxxxxx");
        //註釋15:拷貝這個命令到context
        context.ExecuteCommandBuffer(cameraBuffer);
        //註釋16:清除這個命令
        cameraBuffer.Clear();

        //註釋17:最終繪製
        context.Submit();
    }

    //用以開發階段和編輯器階段(只有滿足這兩個條件中的一個就會編譯這段代碼)
    [Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
    void DrawDefaultPipeline(ScriptableRenderContext context, Camera camera)
    {
        if (errorMaterial == null)
        {
            Shader errorShader = Shader.Find("Hidden/InternalErrorShader");
            errorMaterial = new Material(errorShader)
            {
                hideFlags = HideFlags.HideAndDontSave
            };
        }

        var drawSettings = new DrawRendererSettings(camera, new ShaderPassName("ForwardBase"));
        drawSettings.SetShaderPassName(1, new ShaderPassName("PrepassBase"));
        drawSettings.SetShaderPassName(2, new ShaderPassName("Always"));
        drawSettings.SetShaderPassName(3, new ShaderPassName("Vertex"));
        drawSettings.SetShaderPassName(4, new ShaderPassName("VertexLMRGBM"));
        drawSettings.SetShaderPassName(5, new ShaderPassName("VertexLM"));
        drawSettings.SetOverrideMaterial(errorMaterial, 0);

        var filterSettings = new FilterRenderersSettings(true);

        context.DrawRenderers(cull.visibleRenderers, ref drawSettings, filterSettings);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章