Dots下给程序化生成的网格加上Lod

1 篇文章 0 订阅

近段时间研究dots terrain时有个想法是给程序动态生成的mesh加上lod。网上搜了下基本国内没发现几篇讲这个的文章。官网论坛上倒是有几篇帖子。于是这里一篇记录贴。

首先来看下如果不是实时生成的网格在dots下LOD是怎么回事。我们做个试验,新建一个空的gameobject作为父entity,加上Lod Group组件和convertToEntityscirpt,然后再给这个gameobje增加3个child,分别是一个方块一个全球和一个椭圆。运行一下看看Entity debugger里面的信息。可以看见在转化生成的4个Entity中,父entity上挂接了个MeshLodGroupComponent和一个LodGroupWorldReferencePoint的组件。这个MeshLodGroupComponent用两个float4保存了8个LodDistance的参数,而另一个point组件显然是用于地址的引用。

针对3个child Entity,三个entity的组件类型完全一样,与Lod相关的组件有:MeshLodCompoent,这个也是一个定义性质的组件,包含一个对父entity的字段。

RootLODRange,最大最小参数。

LODRange,这个层级的lod对应的最大最小距离

其他组件和一个不使用lod转化的mesh entity 一样。那问题来了,这些组件似乎都没有控制entity的显示?仔细观察发现,在HybridChunkInfo中,有个visible的值。不显示的这个字段的值都被设置为0。

弄清楚dots 下LOD的数据结构有哪些后 我们尝试通过代码来给4个entity加上这些组件。不过部分组件比如LODRange不能公共访问,并不能手动添加。于是尝试给父Entity加上MeshLodGroupComponent组件,给childEntity加上MeshLodComponent组件。写个脚本测试一下:

using Unity.Entities;
using Unity.Mathematics;
using Unity.Rendering;
using Unity.Transforms;
using UnityEngine;
using UnityEngine.Rendering;

[DisallowMultipleComponent]
public class TestLod : MonoBehaviour, IConvertGameObjectToEntity
{
    public Mesh lod0;
    public Mesh lod1;
    public Mesh lod2;
    public Material material;

    public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    {
        var lodGroupData = new MeshLODGroupComponent();
        lodGroupData.LocalReferencePoint = float3.zero;

        var lodDistances0 = new float4(float.PositiveInfinity);
        var lodDistances1 = new float4(float.PositiveInfinity);

        lodDistances0 = new float4(2 , 4 ,6 , 8);

        lodGroupData.LODDistances0 = lodDistances0;
        lodGroupData.LODDistances1 = lodDistances1;

        dstManager.AddComponentData(entity , lodGroupData);

        var entityLod0 = CreateRenderMeshEntity(lod0 , material , dstManager);
        var entityLod1 = CreateRenderMeshEntity(lod1 , material , dstManager);
        var entityLod2 = CreateRenderMeshEntity(lod2 , material , dstManager);

        dstManager.AddComponentData(entityLod0 , new MeshLODComponent { Group = entity , LODMask = 1 << 0 });
        dstManager.AddComponentData(entityLod1 , new MeshLODComponent { Group = entity , LODMask = 1 << 1 });
        dstManager.AddComponentData(entityLod2 , new MeshLODComponent { Group = entity , LODMask = 1 << 2 });

    }

    public static Entity CreateRenderMeshEntity (Mesh mesh , Material material , EntityManager dstManager)
    {
        var desc = new RenderMeshDescription(
            mesh ,
            material ,
            shadowCastingMode: ShadowCastingMode.On ,
            receiveShadows: true
            );

        var prefab = dstManager.CreateEntity();

        RenderMeshUtility.AddComponents(
            prefab ,
            dstManager ,
            desc);

        dstManager.AddComponentData(prefab , new LocalToWorld { Value = new float4x4(quaternion.identity , float3.zero) });

        return prefab;
    }
}

运行发现其他不能公开访问的组件都被加上去了,并且LOD功能显示正常。

但是从上面的分析似乎也发现了个局限性,似乎没法获取当前的LOD层级?要了解当前在哪个LOD层级,需要遍历各个子entity的HybridChunkInfo的CullingData.Visible字段。这个似乎不是一个有效率的做法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值