ue4.26 Assertion failed: MeshCommands.Num() == MeshCommandsCSM.Num() 解法
在ue4.26的pc端添加了自定义meshpass xxxPass,切到移动端后产生如下错误:
Assertion failed: MeshCommands.Num() == MeshCommandsCSM.Num()
VisibleMeshDrawCommands of BasePass and MobileBasePassCSM are expected to match.
为了看清楚状况,做一个最简场景进行复现,一个材质名为floor的绿色平面,一个材质名为cartoonTransp的球体,pc平台效果如下:
切换为移动平台后,触发asset fail断点如下:
查看断点数据,可见MeshCommands和MeshCommandsCSM元素数量分别为1和2。
进一步展开细看,可见MeshCommands中的1个元素为floor,MeshCommandsCSM中的两个元素为floor和cartoonTransp:
此种mesh command与阴影comand对不上的情况不会发生在pc端,因为由下面代码可见,pc端直接GenerateDynamicMeshDrawCommands,而移动端在GenerateDynamicMeshDrawCommands之前多一个MergeMobileBasePassMeshDrawCommands过程,在其中会asset两种command数量相等。
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 | void AnyThreadTask() { ... if (bMobileShadingBasePass) { MergeMobileBasePassMeshDrawCommands( ... Context.MeshDrawCommands, Context.MobileBasePassCSMMeshDrawCommands ); GenerateMobileBasePassDynamicMeshDrawCommands( ... Context.MeshDrawCommands, ... ); } else { GenerateDynamicMeshDrawCommands( ... Context.MeshDrawCommands, ... ); } ... } |
我们知道GenerateDynamicMeshDrawCommands是完成将meshbatch转为meshdrawcommand的过程,也就是说GenerateDynamicMeshDrawCommands之前还不存在meshdrawcommand,那MergeMobileBasePassMeshDrawCommands中的Context.MeshDrawCommands和Context.MobileBasePassCSMMeshDrawCommands是从哪来的呢?
其实这里的Context.MeshDrawCommands和Context.MobileBasePassCSMMeshDrawCommands根本不是FMeshDrawCommand类型,而是FVisibleMeshDrawCommand类型(书写时偷懒了)。
FVisibleMeshDrawCommand定义如下:
即首先SceneVisibility.cpp中由MeshBatch生成FVisibleMeshDrawCommand,然后是GenerateDynamicMeshDrawCommands由FVisibleMeshDrawCommand和MeshBatch生成FMeshDrawCommand。
由于在SceneVisibility.cpp中,我只让球体对xxxPass生成visibleMeshDrawCommand,所以球体对MobileBasePass不生成visibleMeshDrawCmmand,这是对的。
但由于SceneVisibility.cpp中默认有一句:
1 2 3 4 | if (ShadingPath == EShadingPath::Mobile) { DrawCommandPacket.AddCommandsForMesh(PrimitiveIndex, PrimitiveSceneInfo, StaticMeshRelevance, StaticMesh, Scene, bCanCache, EMeshPass::MobileBasePassCSM); } |
所以球体会对MobileBasePassCSM这个pass生成visibleMeshDrawCommand。于是产生不匹配。
解法就是让球体对MobileBasePassCSM不生成visibleMeshDrawCommand,即改为:
1 2 3 4 | SceneVisibility.cpp<br> <br> if (ShadingPath == EShadingPath::Mobile) { if (!StaticMesh.MaterialRenderProxy->GetMaterial(View.GetFeatureLevel())->GetShadingModels().HasOnlyShadingModel(EMaterialShadingModel::MSM_Toon_01_TR)) {<br> <br> DrawCommandPacket.AddCommandsForMesh(PrimitiveIndex, PrimitiveSceneInfo, StaticMeshRelevance, StaticMesh, Scene, bCanCache, EMeshPass::MobileBasePassCSM); } } |
再运行切移动端,就不会asset fail了,不过球体有影子但本身不可见,如下:
原因是我只在FDeferredShadingSceneRenderer::Render中调用了RenderxxxPass,但没在FMobileSceneRenderer::RenderDeferred中调用RenderxxxPass。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决
2016-01-18 建了个百度贴吧:图形底层吧