先创建一个类,这个就是关于渲染管线Asset的用于储存渲染管线
using UnityEngine;
using UnityEngine.Rendering;
[CreateAssetMenu(menuName = "Rendering/Custom Render Pipeline")]
public class CustomRenderPipelineAsset : RenderPipelineAsset {
[SerializeField]
bool useDynamicBatching = true,useGPUInstancing = true,useSRPBatcher = true;
protected override RenderPipeline CreatePipeline()
{
return new CustomRenderPipeline(useDynamicBatching,useGPUInstancing,useSRPBatcher);
}
}
就是这样一个类,非常的简单,其中有三个参数,三个参数是用于控制批处理,然后定义一个构造方法,带上三个参数
然后我们再创建一个渲染管线,
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
//这几行不必多说
public class CustomRenderPipeline : RenderPipeline
{
CameraRenderer renderer = new CameraRenderer();
//创建一个渲染器,就是关于Camera的渲染器
bool useDynamicBatching,useGPUInstancing;
public CustomRenderPipeline(bool useDynamicBatching,bool useGPUInstancing,bool useSRPBatcher)
{
this.useDynamicBatching = useDynamicBatching;
this.useGPUInstancing = useGPUInstancing;
GraphicsSettings.useScriptableRenderPipelineBatching = useSRPBatcher;
}
//然后自定义渲染管线设置,让我们的渲染管线拥有关于三个use变量的三种功能
protected override void Render(
ScriptableRenderContext context,Camera[] cameras)
{
foreach(Camera camera in cameras)
{
renderer.Render(context,camera,useDynamicBatching,useGPUInstancing);
}
}
//创建一个render方法,来设置每个camera,这也是必须的
}
这个渲染管线就很多内容,一个一个看,现在看内部
现在来到我们的camerarender
using UnityEngine;
using UnityEngine.Rendering;
public partial class CameraRenderer
{
ScriptableRenderContext context;
//上下文
Camera camera;
//相机
const string bufferName = "Render Camera";
CullingResults cullingResults;
//指出是哪种阴影pass
static ShaderTagId unlitShaderTagId = new ShaderTagId("SRPDefaultUnlit");
CommandBuffer buffer = new CommandBuffer
{
name = bufferName
};
//创建一个buffer,让buffer的name就等于先前的buffername
public void Render(ScriptableRenderContext context, Camera camera,bool useDynamicBatching,bool useGPUInstancing)
{
this.context = context;
this.camera = camera;
//先设置上下文和相机
PrepareBuffer();
PrepareForSceneWindow();
//准备buffer和scenewindow的设置
if (!Cull())
{
return;
}
//如果被cull了就返回
Setup();
//设定
DrawVisibleGeometry(useDynamicBatching,useGPUInstancing);
//画出能看的间的Geometry
DrawUnsupportedShader();
//draw不支持的shader
DrawGizmos();
//
Submit();
}
void DrawVisibleGeometry(bool useDynamicBatching,bool useGPUInstancing)
{
var sortingSettings = new SortingSettings(camera)//相机是传递正交还是透视
{
criteria = SortingCriteria.CommonOpaque
};
var drawingSettings = new DrawingSettings(unlitShaderTagId, sortingSettings){//unlitshadertagid指出支持哪一种阴影
enableDynamicBatching = useDynamicBatching,
enableInstancing = useGPUInstancing
};
var filteringSettings = new FilteringSettings(RenderQueueRange.opaque);//设置渲染排序条件,现在这句是只有不透明的
context.DrawRenderers(cullingResults, ref drawingSettings, ref filteringSettings);
context.DrawSkybox(camera);
//然后渲染透明的
sortingSettings.criteria = SortingCriteria.CommonTransparent;
drawingSettings.sortingSettings = sortingSettings;
filteringSettings.renderQueueRange = RenderQueueRange.transparent;
context.DrawRenderers(cullingResults, ref drawingSettings, ref filteringSettings);
}
void Submit()
{
buffer.EndSample(SampleName);
ExecuteBuffer();
context.Submit();
}
void Setup()
{
context.SetupCameraProperties(camera);
CameraClearFlags flags = camera.clearFlags;
buffer.BeginSample(SampleName);
buffer.ClearRenderTarget(flags<=CameraClearFlags.Depth, flags <= CameraClearFlags.Color, flags ==CameraClearFlags.Color?camera.backgroundColor.linear: Color.clear);//��һ��������ʾʲôʱ�������ֵ������ѡ������ʱ�����һ��ʱ�ڶ�����ʾʲôʱ�������ɫ���壬����ѡ��ּ����ɫ��Ⱦ�������,��������ʾʲô������ɫ����Ϊ��������ʹ�õ���ɫģ�������Եģ�����ѡ��ת��Ϊ����
ExecuteBuffer();
context.SetupCameraProperties(camera);
}
void ExecuteBuffer()
{
context.ExecuteCommandBuffer(buffer);
buffer.Clear();
}
//跟踪多个相机和矩阵,然后设定cullingResult,成功就储存在字段中,失败就犯乎false
bool Cull()
{
if (camera.TryGetCullingParameters(out ScriptableCullingParameters p))
{
cullingResults = context.Cull(ref p);
return true;
}
return false;
}
}
然后是只在编辑器中存在的
using UnityEditor;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.Rendering;
partial class CameraRenderer
{
partial void DrawGizmos();
partial void DrawUnsupportedShader();
partial void PrepareForSceneWindow();
partial void PrepareBuffer();
#if UNITY_EDITOR
string SampleName { get; set; }
static Material errorMaterial;
//这个是旧的shader
static ShaderTagId[] legacyShaderTagIds =
{
new ShaderTagId("Always"),
new ShaderTagId("ForwardBase"),
new ShaderTagId("PrepassBase"),
new ShaderTagId("Vertex"),
new ShaderTagId("VertexLMRGBM"),
new ShaderTagId("VertexLM")
};
//这个是画一些GIZMOS的
partial void DrawGizmos()
{
if(Handles.ShouldRenderGizmos())
{
context.DrawGizmos(camera, GizmoSubset.PreImageEffects);
context.DrawGizmos(camera,GizmoSubset.PostImageEffects);
}
}
//这个方法就是绘制一些不受支持的material,然后基于他们相同的报错红
partial void DrawUnsupportedShader()
{
if(errorMaterial == null)
{
errorMaterial = new Material(Shader.Find("Hidden/InternalErrorShader"));
}
var drawingSettings = new DrawingSettings(
legacyShaderTagIds[0], new SortingSettings(camera))
{ overrideMaterial = errorMaterial};
for(int i = 1; i < legacyShaderTagIds.Length; i++)
{
drawingSettings.SetShaderPassName(i, legacyShaderTagIds[i]);
}
var filteringSettings = FilteringSettings.defaultValue;
context.DrawRenderers(cullingResults,ref drawingSettings,ref filteringSettings);
}
//这个是绘制UI
partial void PrepareForSceneWindow()
{
if(camera.cameraType == CameraType.SceneView)
{
ScriptableRenderContext.EmitWorldGeometryForSceneView(camera);
}
}
//这个是让缓冲区名称对应于相机的名称这样我们就可以清楚的辨别把缓冲区属于哪一个相机
partial void PrepareBuffer()
{
Profiler.BeginSample("Editor Only");
buffer.name = SampleName =camera.name;
Profiler.EndSample();
}
#else
const string SampleName = bufferName;
#endif
}