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);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章