Notifications
Article
项目升级到 Unity URP 的一些评测
Published 12 days ago
702
6
很久很久以前
欢迎在座的Unity大佬看看结论是否有错,随时可以打死我. 然后如果哪位大佬可以教我如何在文本内添加超链接,赶紧私信我
Untiy 推出SRP 已经接近一年了,其中官方宣称 LWRP 在2018年年底时已经处于 production ready 既随时可以做产品了,于是改名为URP, 不过 HDRP 还需要2019.4 的到来才能到达完整版。 不过在我看来 URP 还不能说是 production ready 还处于玩具过渡到产品阶段。而且有时候觉得Unity官方对于技术路线偶尔会出现不明确,左右摇摆的情况。比如Unity 2018 新出的Camera.AddCommandBuffer 来做自定义渲染, 这在 Unity 2019 被废除了,取而代之使用 Render Feature /ScriptableRenderPass 来实现,不过这东西也处于实验阶段。
SRP不做任何修改是否可以直接提高项目性能,答案是可以直接减少CPU给GPU准备阶段的性能大约10%左右。无法直接提升GPU的渲染性能,对于不使用任何光照的项目且处于Opengl ES2.0 这类低端机,基本没有任何GPU性能提升。
以目前使用的SRP 有大量Bug 举两个例子
1. [In order to call GetTransformInfoExpectUpToDate, RendererUpdateManager.UpdateAll must be called first.] 莫名的内置渲染错误,无法自己修改。
官方Issue链接
https://issuetracker.unity3d.com/issues/errors-message-at-editor-play?_ga=2.202176470.695125147.1571176891-1511937231.1511185188
2. 使用渲染指令Blit 后,会导致RenderTarget 无法自动恢复原始RenderTarget,需要手动还原SetRenderTarget,这个在之前的CommandBuffer 里都不曾遇到
在项目中期切换到SRP可以直接优化的地方
1.相机Culling优化

https://connect.unity.com/p/unityzhi-zuo-ren-zhuan-chang-unity-aaayou-xi-shen-du-you-hua-zhu-ti-yan-jiang
根据官方优化参考,使用SRP后,可以控制相机 Culling(裁剪)行为,对于项目中有自己实现基于投影器Projector的阴影相机可以复用主相机的 Culling结果, 对于UI上模型RT相机可以不做任何Culling
2.相机 Stack 优化
SRP废弃了多个相机的实现,无法再使用多个相机 (比如我们项目1个GamePlay, 1个HUD, 1个UI相机的。使用官方SRP模板,UI相机背景色会盖住场景内容),原因为
如果只使用1个相机,渲染结果可以直接写入BackBuffer
如果有多个相机,由于第二个相机需要第一个相机结果填充画布后再渲染,因此至少需要一张RenderTexture的临时缓冲,且还需要针对不同的Viewport做裁剪等等,写入backBuffer的时机也会延迟
官方文档废弃Camera Stack原因
https://docs.google.com/document/d/1GDePoHGMngJ-S0Da0Fi0Ky8jPxYkQD5AkVFnoxlknUY/edit
3.UI OverDraw 优化
使用同一个相机绘制UI后,可以考虑给UI添加模板测试,将UI挡住场景的部分,场景可以不被绘制到。

4.UI 批次合并(Opengl 3.0+ Unity2019.2+ with SRP Batcher)
对于场景特效类,基本都无缘SRP batcher 他对Cbuffer的容量有限制
对于UI如果全局自定义Shader可以使用 SRP Batcher 不过目前还是实验阶段。

最后来说下 Camera.AddCommandBuffer 这个功能在 Unity 2019 替换为 ScriptableRenderPass 后如何实现一个XRay
使用 CommandBuffer时仅仅需要 camera.AddCommandBuffer(CameraEvent.AfterForwardOpaque, m_XRayBuffer);
然后再XRayBuffer.drawRenderer(renderer, XrayMat)即可

在2019里 需要创建XrayRenderPassFeature 类来实现
public class XRayRenderPassFeature : ScriptableRendererFeature

ScriptableRendererFeature有2个接口要实现分为
Creata() 创建一个实现具体Xray Pass的接口
AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) 将创角的pass 添加进renderer 队列

在XRayRenderPassFeature 里实现一个 CustomRenderPass : ScriptableRenderPass 来编写具体Xray逻辑
Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) 准备阶段
Execute(ScriptableRenderContext context, ref RenderingData renderingData) 渲染阶段
FrameCleanup(CommandBuffer cmd) 清理阶段

基本实现都在Configure里
CommandBuffer xraycmd = CommandBufferPool.Get(m_profilerTag); xraycmd.DrawMesh(m_drawMesh, m_xrayTarget.transform.localToWorldMatrix, m_xrayMaterial); context.ExecuteCommandBuffer(xraycmd); CommandBufferPool.Release(xraycmd);

大致流程是,Renderer 会根据 pass 的 renderPassEvent 进行和内置其他pass 比如天空盒,点光,深度 等等其他pass 一起sort, 之后分别在渲染前,渲染,渲染后调用接口

补充一个以官方的SRP FPS Demo 基础来实现XRay
https://github.com/Unity-Technologies/UniversalRenderingExamples
1.在FpsSetup 预制体里添加刚刚创建的Feature
2.编写一个简单ZTest Greater的Shader 用来绘制被遮挡的部分
Shader "Unlit/XrayShader" { SubShader { Tags { "RenderType"="Opaque" "LightMode"="LightweightForward" } LOD 100 Pass { ZTest greater offset -1,-1 HLSLPROGRAM #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/core.hlsl" struct appdata { float4 vertex : POSITION; }; struct v2f { float4 vertex : SV_POSITION; }; v2f vert (appdata v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); return o; } float4 frag (v2f i) : SV_Target { return float4(1,0,0,1); } ENDHLSL } } }
3.在场景中放置一个示例Cube,取名为XRayTarget
最后运行游戏

最后 使用自定义 ScriptableRendererFeature 的话,还需要自己编写对应的Editor代码,比之前繁琐许多。

如果自己来编写SRP的话,RenderPassFeature 需要自己维护pass列表来实现, 也可以仅仅去实现自定义的ForwardRenderer,可以减少很多功能的重复造轮子。
dreamfairy
Technical Artist/GameEngineer - Writer
3
Comments
dreamfairy
4 days ago
Technical Artist/GameEngineer
xdedzl升级到2019.3后,使用URP时挂在相机上的OnPostRender和OnRenderImage都不执行,URP有什么替代方案了么?现在想用自己的material对最终渲染的图像做处理该怎么做呢?
使用render feature实现,或者抓出主渲染commandbuffer 把当前的camerataget blit出来
0
xdedzl
4 days ago
开发
升级到2019.3后,使用URP时挂在相机上的OnPostRender和OnRenderImage都不执行,URP有什么替代方案了么?现在想用自己的material对最终渲染的图像做处理该怎么做呢?
0
dreamfairy
4 days ago
Technical Artist/GameEngineer
ZQY第3段那句“SRP不做任何修改是否可以直接提高项目性能,答案是可以直接减少CPU给GPU准备阶段的性能大约10%左右。”减少性能是说性能反而降低了?还是说减少了开销😂
是减小了开销,提升10%性能,我语文不好 请多多理解哈
0
ZQY
8 days ago
None
第3段那句“SRP不做任何修改是否可以直接提高项目性能,答案是可以直接减少CPU给GPU准备阶段的性能大约10%左右。”减少性能是说性能反而降低了?还是说减少了开销😂
0
Unity3d名侦探
不错
0