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