URP中基于ShaderFeature和ComputeShader的OverDraw工具
URP中基于ShaderFeature和ComputeShader的OverDraw工具
00 前言
01 处理方法
目前采用的方式是使用context.DrawRenderers方法中的drawSettings.overrideMaterial = _material;, 进行替代渲染. 核心方法见下方代码:
1
2
3
4
5
6
7
private void DrawRenderers(ScriptableRenderContext context, ref RenderingData renderingData)
{
var sortFlags = _isOpaque ? renderingData.cameraData.defaultOpaqueSortFlags : SortingCriteria.CommonTransparent;
var drawSettings = CreateDrawingSettings(_tagIdList, ref renderingData, sortFlags);
drawSettings.overrideMaterial = _material;
context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref _filteringSettings);
}
*事实上, 如果是自己的工程的话, 仿照URP的多Pass进行渲染会更可控和准确, 后续会尝试采用这个方案.
02 QA
x00 Q: URP中如何用脚本改变摄像机的Renderer
A: 使用camera的GetUniversalAdditionalCameraData()方法得到UniversalAdditionalCameraData对象, 然后调用其SetRenderer(int index)方法即可, 但unity2019没有根据名称获取index的方法, 只能每次去设置. 参考网页, 另动态切换Universal Render Pipeline Asset的方法
1
2
3
4
5
6
7
public static void SyncAddProperties(this Camera camera, Camera otherCamera, OverdrawCameraConfig config)
{
camera.GetUniversalAdditionalCameraData().SetRenderer(config.rendererIndex);
camera.GetUniversalAdditionalCameraData().renderPostProcessing = config.renderPostProcessing;
camera.GetUniversalAdditionalCameraData().renderType = config.cameraRenderType;
camera.GetUniversalAdditionalCameraData().renderShadows = false;
}
x01 Q: RenderTexture的释放该调用什么API
A: 一般来说, 如果不是需要长期存储的RenderTexture(以下简称”RT”), 尽量使用RenderTexture.GetTemporary(RenderTextureDescriptor descriptor)类似的方法来获取, 相对应的, 释放时不能直接使用RenderTexture.Release(), 而是要使用RenderTexture.ReleaseTemporary(RenderTexture rt)来进行资源释放. 参考网页.
x02 Q: CommandBuffer.GetTemporaryRT与RenderTexture.GetTemporary有什么异同
A: 参考网页, 即如果需要在多个CommandBuffer之间传递RT, 那么请使用RenderTexture.GetTemporary, 比如bloom后处理, 一般的后处理使用CommandBuffer.GetTemporaryRT即可.
CommandBuffer.GetTemporaryRT获取的RT会在Graphics.ExecuteCommandBuffer或者CameraEvent渲染完成后被回收,这就可能导致在不同CameraEvent获取RT时,取得之前创建的RT,覆盖原有的效果。如果是持续化显示,通过RenderTexture.GetTemporary接口可以避免这类问题。
x03 Q: 在EditorWindow类中如何显示List与数组?
A: 必须的代码见下, 参考网页0, 参考网页1, U3D编辑器扩展_虚拟喵的博客-CSDN博客
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class OverdrawWindow : EditorWindow
{
//...
[SerializeField] private List<Camera> _cams;
private SerializedObject _serializedObject;
private SerializedProperty _camsProperty;
//...
[MenuItem("Tools/Overdraw Window")]
//...
static void ShowWindow()
{
GetWindow<OverdrawWindow>().Show();
}
//...
//声明一个List所在类的SerializedObject, 因为这里直接把List存在了OverdrawWindow类中, 所以是this.
//然后使用_serializedObject.FindProperty(name)的方式得到SerializedProperty
private void OnEnable()
{
_serializedObject = new SerializedObject(this);
_camsProperty = _serializedObject.FindProperty("_cams");
}
//...
private void OnGUI()
{
//...
DisplayCurCameras();
//...
Repaint();
}
//...
private void DisplayCurCameras()
{
//通过EditorGUILayout.PropertyField(SerializedProperty prop)的Api来在EditorWindow面板上显示List
EditorGUILayout.PropertyField(_camsProperty);
}
}
x04 Q: 当打开MSAA后, 在framdebugger中会出现大量的MSAA的渲染过程, 如何解决?
A: 参考以下网页, 后续对管线进行优化
【精选】大型项目中 MSAA 的方案参考_a multisampled texture being bound to a non-multis-CSDN博客
x05 Q: 报错日志:Non matching Profiler.EndSample (BeginSample and EndSample count must match)
A: unity的Profiler报错 - 知乎 (zhihu.com), 实际上并没有真正解决在”实际”工程中遇到的报错, 临时把这段注释掉了, 代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CommandBuffer cmd = CommandBufferPool.Get(_profilerTag);
//注释掉了以下这句代码
//using (new ProfilingScope(cmd, _profilingSampler))
{
var desc = renderingData.cameraData.cameraTargetDescriptor;
desc.enableRandomWrite = true;
desc.graphicsFormat = GraphicsFormat.R32_SFloat;
//刷新数据
// OverdrawData.Descriptor = desc;
// OverdrawData.rendTextureDic[renderingData.cameraData.camera] = OverdrawData.OverdrawTexture;
OverdrawData.RefreshDataRendTexture(camera,desc);
cmd.Blit(_source, OverdrawData.rendTextureDic[camera]);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
04 小石头
x00 异步截图工具
x01 How to resolve this error with Unity’s AsyncGPUReadback?
x02 Fast Pixel Reading (Part 2): AsyncGPUReadback
x03 喷涂、绘制与填充 - KuanMi
x04 How to use compute shaders to compute enclosed regions within a texture
x05 How to use compute shaders to compute enclosed regions within a texture
x06 运行时控制RendererFeature
x07 tkonexhh/LookingShader (github.com)
x08 Overdraw概念、指标和分析工具 - (built-in方案)
参考网页
Overdraw概念、指标和分析工具 - 知乎 (zhihu.com)
[URP]RenderFeature+ComputeShader计算OverDraw - 知乎 (zhihu.com)
ina-amagami/OverdrawForURP: Scene Overdraw in Universal Render Pipeline. (github.com)
Rendering.FilteringSettings - Unity 脚本 API
Rendering.DrawingSettings - Unity 脚本 API
Unity3D:URP下输出深度图以及自定义ScriptableRenderer - 知乎 (zhihu.com)
phi-lira/CustomScriptableRenderer (github.com)
How to make a readonly property in inspector? - Questions & Answers - Unity Discussions
初识Compute Shader - 知乎 (zhihu.com)
【Unity】Compute Shader的基础介绍与使用 - 知乎 (zhihu.com)
Unity Compute Shader入门初探 - 简书 (jianshu.com)
Compute Shader中的Parallel Reduction和Parallel Scan - 知乎 (zhihu.com)
How can we access thread group and global variables from threads in compute shader? - Unity Forum
Nordeus/Unite2017 (github.com)
ken48/UnityOverdrawMonitor: Overdraw profiler for Unity, shows fill rate (github.com)
URP延迟渲染+Native Renderpass踩坑记录 - 知乎 (zhihu.com)
从零实现Unity通用渲染管线(URP)二:DrawObjectPass - 知乎 (zhihu.com)
How to get a data from compute shader in custom pass. - Unity Forum
Unity - Scripting API: AsyncGPUReadbackRequest (unity3d.com)