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第一讲代码注释
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.