Desc:
可编辑渲染管线,可以据此自定义修改管线内容,也可以学习渲染管线中实现
UniversalRenderPipelineAsset
渲染管线资源
继承自 RenderPipelineAsset 类
RenderPipelineAsset.CreatePipeline
RP 资产的主要目的是为 Unity 提供一种方法来获取负责渲染的管道对象实例.资产本身只是一个句柄和一个存储设置的地方
该函数返回一个管道对象实例
UniversalRenderPipeline
渲染管线实例
继承自 RenderPipeline
RenderPipeline.Render
此方法是可编写脚本的渲染管道 (SRP) 的入口点。此功能与内置渲染管道不兼容。
Unity 会自动调用此方法。在独立应用程序中,Unity 每帧调用一次此方法来渲染主视图,每帧调用一次Camera.Render。在 Unity 编辑器中,对于每个可见的场景视图或游戏视图,Unity 每帧调用一次此方法,如果场景摄像机预览可见,则每帧调用一次,对于每个摄像机每帧调用一次Camera.Render
URP实现
1 |
|
catlikecoding中记录的方法 Source
1 | static ShaderTagId unlitShaderTagId=new ShaderTagId("SRPDefaultUnlit"); |
设置Buffer信息
buffer.name=camera.name
绘制UI
//只在编辑器内需要
if(camera.cameraType==CameraType.SceneView){
//将UI显式添加到世界几何体中
ScriptableRenderContext.EmitWorldGeometryForSceneView(camera);
}
剔除
if(!Cull()){
return;
}
设置属性
//设置视图投影矩阵,将相机的位置和方向与相机的透视或正交投影结合一起(unity_MatrixVP)
Context.SetupCameraProperties(camera)
清除标志
//通过调整被渲染的第二个相机的清除标志来组合两个相机的结果
CameraClearFlags flags=camera.clearFlags;
//清除渲染目标,防止上一帧结果影响当前渲染目标
buffer.ClearRenderTarget(
flags<=CameraClearFlags.Delpth,
flags==CameraClearFlags.Color,
flags==CameraClearFlgas.Color?camera.backgroundColor.linear:Color.clear);//是否清除深度、是否清除颜色、用于清除的颜色(使用 Hidden/InternalClear 写入渲染目标的着色器,返回顶点色,实现在下面)
//注入分析器样本
buffer.BeginSample(bufferName)
ExecuteBuffer()
//某些任务(如绘制天空盒)可以通过专用方法发出,但其他命令必须通过单独的命令缓冲区间接发出
绘制(通过DrawRenderers使用剔除结果作为参数调用context完成,执行渲染哪些,提供 DrawingSettings、FilteringSettings)
var sortingSettings=new SortingSettings(camera){//camera用于确认是正交排序还是基于距离的排序
criteria=SortingCriteria.CommonOpaque//设置排序设置的属性,强制一个特定的绘制顺序
};
var drawingSetting=new DrawingSettings(unlitShaderTagId,sortingSettings);//指定允许哪些着色器通道
//指定允许哪些渲染队列
var filteringSettings=new FilteringSettings(RenderQueueRange.opaque);
绘制不透明物体
context.DrawRenderers(cullingResults,ref drawingSetting,ref filteringSettings);
//绘制天空盒(在透明之前是因为绘制透明物体不会写入深度,天空盒会覆盖透明结果)
context.DrawSkybox(camera);
绘制透明物体
sortingSettings.criteria=SortingCriteria.CommonTransparent;
drawingSetting.sortingSetting=sortingSettings;
filteringSettings.renderQueueRange=RenderQueueRange.Transparent;
context.DrawRenderers(cullingResults,ref drawingSetting,ref filteringSettings);
绘制错误的着色器
//只在编辑器内需要
#if UNITY_EDITOR
if(errorMaterial==null){
errorMaterial=new Material(Shader.Find(“Hidden/InternalErrorShader”));
}
drawingSettings=new DrawingSettings(legacyShaderTagIds[0],new SortingSettings(camera)){
overrideMaterial=errorMaterial
};
for (int i = 1; i < legacyShaderTagIds.Length; i++) {
drawingSettings.SetShaderPassName(i, legacyShaderTagIds[i]);
}
filteringSettings=FilteringSettings.defaultValue;
context.DrawRenderers(cullingResults,ref drawingSettings,filteringSettings);
#endif
绘制Gizmos
//只在编辑器内需要
#if UNITY_EDITOR
if(Handles.ShouldRenderGizmos()){
context.DrawGizmos(camera,GizmoSubset.PreImageEffects);
context.DrawGizmos(camera,GizmoSubset.PostImageEffects);
}
#endif
结束
buffer.EndSample(buffName)
ExecuteBuffer()
//提交排队的工作并执行
Content.submit()
执行
void ExecuteBuffer(){
//执行缓冲区
context.ExecuteCommandBuffer(buffer)
//清除命令
buffer.Clear()
}
剔除
//不会绘制每个对象,而是只渲染对于相机可见的对象。从场景中具有Renderer组件的所有对象开始,然后剔除在相机视锥体之外的对象
bool Cull(){
ScriptableCullingParameters p;
if(camera.TryGetCullingParameters(out p)){
cullingResults=context.Cull(ref p);
return true;
}
return false;
}
引用
Hidden/InternalClear.shader
1 | v2f vert (appdata_t v) |
Internal-ErrorShader.shader
1 | fixed4 frag (v2f i) : SV_Target |
后处理
如果您使用的是通用渲染管道 (URP) 或高清渲染管道 (HDRP),则可以使用
RenderPipelineManager.beginFrameRendering
在RenderPipeline.Render开始时调用自定义代码的委托
1 | void Start() |
RenderPipelineManager.beginCameraRendering
在 Unity 渲染单个相机之前调用自定义代码的委托
RenderPipelineManager.endCameraRendering
在 Unity 渲染单个相机后,您可以使用它来调用自定义代码的委托
RenderPipelineManager.endFrameRendering
可用于在RenderPipeline.Render末尾调用自定义代码的委托
编写自定义 SRP,您可以直接在此处添加代码,或者使用
在RenderPipeline.Render开始时调用自定义代码的委托
RenderPipeline.BeginFrameRendering
RenderPipeline.BeginCameraRendering
RenderPipeline.EndCameraRendering
RenderPipeline.EndFrameRendering
1 | override protected void Render(ScriptableRenderContext context, Camera[] cameras) |