之前为客户公司做一个和RenderFeature有关的功能,研究了一下Render的做法。
URP的渲染设置
首先简单说一下URP的渲染设置的几个步骤,对之后的理解有必要,知道可以跳过。
右键create,菜单你可以直接创建几个和URP有关的asset,我们需要搞清楚他们的关系
1点击第一个PipelineAsset,自动创建两个东西,分别叫URPAsset和URPAsset_Renderer,且第二个是作为第一个参数的,他两分别对应菜单栏目的PipelineAsset,ForwardRender。(这真的挺怪异的,分开创建,命名也不一样)。我们只要记住这两个东西是必须同时使用的,而且一个PipelineAsset可以对应多个ForwardRender(一般不用多个),他们都是和渲染设置有关。
2继续创建一个PostProcessData,填入URPAsset_Renderer。
3最后将PipelineAsset填入ProjectSetting-Quality-Rendering,URP设置就算完成。
包含关系是:PipelineAsset<-ForwardRender<-PostProcessData
URPAsset用来控制URP渲染任务所有设置的对象。包括渲染列表质量光照阴影后处理的设置。
URPAsset和URP_Render都是渲染设置,RenderFeature添加在URP_Render。
目前,URP中,只能配置一个ForwardRendererData(deferRender暂不支持),默认情况下的URP就是单pass前向渲染。
What is RenderFeature,?Why use it?
默认情况下的URP就是单pass前向渲染。如果想要多pass,当然可以重写管线,但是非常不灵活,URP在此处提供革命性的功能-RenderFeature,你可以在渲染所有阶段(RenderPassEvent)插入commandbuffer,给原有管线打补丁而不是重写。
commandbuffer cmd命令缓冲区可保存渲染命令列表(“设置渲染目标、绘制网格等等”),使用 ScriptableRenderContext 向 GPU 调度和提交状态更新和绘制命令,ScriptableRenderContext配合cmd使用。
RenderFeature主要用在后处理效果上,但是他的功能远远不止实现后处理,可以实现许多特殊的渲染效果,如果描边,剪影等等。
RenderFeature本质就是一个C#脚本,继承一个特定的接口 ScriptableRendererFeature,如此你就可以实现贴图分配,给shader赋值等操作,计算的实现还是在shader中,然后你可以手动的添加或者光比RenderFeature。在URPAssetRenderer中。
客户要求
客户要求的CharacterLayer在靠近相机时渲染为半透明,并且因为Character有多个材质构成,且shader在一直改动,所以不能依赖shader。故采用renderfeature方案。
思路:将角色层,单独渲染到一张角色RT,经过裁剪RT之后,手动blend背景层和角色层。
第一版问题:第一版用角色RT的colorbuffer的a通道做裁剪,角色RT默认a通道是0,只有当角色a通道不为0时才做裁剪。但是角色的贴图绘制时使用了A通道,导致绘制出的角色RT一部分a通道为0,而且这个贴图a部分归零没有起作用,需要和角色shaderTA沟通。
主要问题来源:shader由第三方外包团队制作,合同到期,新的TA的shader方案暂时没有到位。
解决:使用使用stencil裁剪代替alpha裁剪。使用stencil代替上面的alpha通道,暂时避开使用colorBuffer。
第二版问题:遮挡关系出现问题:当半透明时人物和相机之间出现物体,遮挡关系会错位。
经过检查发现,原版角色shader会单独绘制depthbuffer,然后在和之前的混合,而不是在之前的基础上绘制,这么做的目的是为了方便开启描边特效。但是新代码打断了之后depth融合过程,造成没有角色shader渲染出来的人物没有正常通过depthtest。
暂时解决:加入开关,只有到角色非常靠经相机,且角色相机中间没有遮挡的时候,开启透明混合。
长期解决:等待新的shader方案到位,和新TA讨论colorbuffer,depthbuffer,stencilbuffer的分配问题。
客户新增要求:开放API,修改gameobjectLayerMask改为rendererLayerMask。
开放API,可以单独额外渲染传入GameObject为透明。据社区反应rendererLayerMask尚未开放,目前无法分离两种LayerMask。
以上内容更新时间2021年4月
补充:模板缓冲区和Alpha缓冲器,都是非常有用的设计。
模板缓冲区:与深度缓冲区类似,通过设置模板缓冲每个像素的值,我们可以在渲染的时候只渲染后写模板缓存对应的值(大于,小于或者等于模板值),从而在后续的其他绘制可以通过配置模板缓存的参数来决定是否丢弃该片元和如何操作对应该片段对应的模板缓存值。
模板缓冲区可以为屏幕上的每个像素点保存一个无符号的整数值,在渲染过程中,可以用这个值与一个预先设定的参考值相比较,根据比较的结果来决定是否更新相应的像素点的颜色值。模板测试发生在透明度测试之后,深度测试之前,如果模板测试通过,则相应的像素点更新,否则不更新。