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。

 

posted on   wantnon  阅读(55)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决
历史上的今天:
2016-01-18 建了个百度贴吧:图形底层吧

导航

< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5
点击右上角即可分享
微信分享提示