星鸿阁

 找回密码
 立即注册
搜索
热搜: 活动 交友 动画
查看: 2605|回复: 0

URP的一些文章

[复制链接]

2254

主题

2764

帖子

9644

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
9644
发表于 2020-10-9 20:30:08 | 显示全部楼层 |阅读模式
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 ... 11937231.1511185188


2. 使用渲染指令Blit 后,会导致RenderTarget 无法自动恢复原始RenderTarget,需要手动还原SetRenderTarget,这个在之前的CommandBuffer 里都不曾遇到


在项目中期切换到SRP可以直接优化的地方


1.相机Culling优化


















https://connect.unity.com/p/unit ... ua-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 ... D5AkVFnoxlknUY/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,可以减少很多功能的重复造轮子。










回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|starfluidga

GMT+8, 2025-5-7 22:37 , Processed in 0.015358 second(s), 20 queries .

Made by Liga 星鸿阁

Copyright © 2020-2048, LigaStudio.

快速回复 返回顶部 返回列表