#Procedural Mesh and RenderMeshUtility

1 messages · Page 1 of 1 (latest)

fervent stone
#

Hello, Im trying to assign some procedurally generated meshes to some entities, so I can manipulate them in ECS.
Ive found RenderMeshUtility examples but my meshes arent rendering, and the MaterialMeshInfo component looks suspicious to me.

Can anyone help me out here?
Code

        var entityManager = world.EntityManager;
        var ecb = new EntityCommandBuffer(Allocator.Temp);
        foreach (Mesh proceduralMesh in fuzzMeshList)
        {
            // Create a RenderMeshDescription using the convenience constructor
            // with named parameters.
            var desc = new RenderMeshDescription(
                shadowCastingMode: ShadowCastingMode.Off,
                receiveShadows: false);

            // Create an array of mesh and material required for runtime rendering.
            var renderMeshArray = new RenderMeshArray(new Material[] { myGrassMaterial }, new Mesh[] { proceduralMesh });

            // Create empty base entity
            var prototype = entityManager.CreateEntity();
            ecb.AddComponent(prototype, new LocalTransform {Position = new float3(0f,0.1f,0f)});

            // Call AddComponents to populate base entity with the components required
            // by Entities Graphics
            RenderMeshUtility.AddComponents(
                prototype,
                entityManager,
                desc,
                renderMeshArray,
                MaterialMeshInfo.FromRenderMeshArrayIndices(0, 0));
            
            entityManager.AddComponentData(prototype, new LocalToWorld());  
        }
        
        ecb.Playback(entityManager);
        ecb.Dispose();```

Below is the inspector of one of these entities
#

If I just add a test sphere mesh to my subscene, and assign the same Material, the MaterialMeshInfo component DOES get an id, and the sphere renders. Do I have to register materials somewhere when assigning them procedurally like this?

robust stone
#

you don't need RenderMeshArray for runtime mesh usage

#

Create your mesh/materials procedurally and use
EntitiesGraphicsSystem.RegisterMaterial and EntitiesGraphicsSystem.RegisterMesh

#

which will return ids for you to use in your MaterialMeshInfo

fervent stone
#

Ahhh I see, thanks. I will give that a try now

robust stone
#

RenderMeshArray is just an efficient way to register mesh/materials from baking

#

you can just ignore this component at runtime (you dont need to add it to an entity either)

fervent stone
#

I cant seem to find the Register methods

#

Oh I have to find an instance

#

of the system

#

That did the trick. Thanks @robust stone youre a legend!

feral ledge
robust stone
#

from memory basically what it does is you use index N

#

and then set a length of Y

#

so it'll use mesh/material N to N+Y

#

you really have to look into the materialmeshinfo stuff and see how its encoded to understand

feral ledge
#

ok I will try to read sources again
I did it many times and always thought it depends on RenderMeshArray to allow you "range" for submesh

robust stone
#
    public struct MaterialMeshInfo : IComponentData, IEnableableComponent
    {
        public int Material;
        public int Mesh;

        /// <summary>
        /// The bit packed sub-mesh related data.
        /// </summary>
        SubMeshIndexInfo32 m_SubMeshIndexInfo;

        /// <summary>The sub-mesh ID. </summary>
        public ushort SubMesh
        {
            get => m_SubMeshIndexInfo.SubMesh;
            set => m_SubMeshIndexInfo.SubMesh = value;
        }

        /// <summary> The MaterialMeshIndex range. </summary>
        public RangeInt MaterialMeshIndexRange => m_SubMeshIndexInfo.MaterialMeshIndexRangeAsInt;

        /// <summary> True if the MaterialMeshInfo is using a MaterialMeshIndex range. </summary>
        public bool HasMaterialMeshIndexRange => m_SubMeshIndexInfo.HasMaterialMeshIndexRange;```
#

it's just stored in here

#

the rendermesharray just ensures the meshes are ordered in that array in the linear order

#

so they register in order

#

its been a while since i dived into this source though

feral ledge
#

yeah it looks like it could work
thanks! I will try

#

ok no I changed my mind

        /// <summary>
        /// Creates an instance of MaterialMeshInfo from a range of material/mesh/submesh index in the corresponding RenderMeshArray.
        /// </summary>
        /// <param name="rangeStart">The first index of the range in <see cref="RenderMeshArray.MaterialMeshIndices"/>.</param>
        /// <param name="rangeLength">The length of the range in <see cref="RenderMeshArray.MaterialMeshIndices"/>.</param>
        /// <returns></returns>
        public static MaterialMeshInfo FromMaterialMeshIndexRange(int rangeStart, int rangeLength)
            => new(0, 0, new SubMeshIndexInfo32((ushort)rangeStart, (byte)rangeLength));

        MaterialMeshInfo(int material, int mesh, SubMeshIndexInfo32 subMeshIndexInfo)
        {
            Material = material;
            Mesh = mesh;
            m_SubMeshIndexInfo = subMeshIndexInfo;
        }

look, this submesh indexes can point to one id only and if you try to avoid using rendermesharray you have no way to make many relations between meshes and materials
at least I can't figure it out

#

it designed to map indexes to rendermesharray which records has materialId and meshId both

robust stone
#

it only points to 1 index, and N indices after this

feral ledge
#

ant this indexes should be indexes of RenderMeshArray

robust stone
#

RenderMeshArray doesn't do anything at runtime

feral ledge
#

it stores ids for meshes and materials, no?

robust stone
#

it stores mesh/materials to register with the entities graphic systems

#

it's just an efficient way to register all your materials/meshes from baking

feral ledge
#

I can't point to material and mesh inside of one range of indexes

#

need to read sources of how graphics systems resolves this stuff

robust stone
#

i don't understand what problem you're having issues with

#

(for the record i'm not claiming this works, i avoid submeshes at all times)

feral ledge
#

look
some entity wants to have mesh with submeshes
the only way to store submeshes is one int (it can store length to have a range also)
it works fine when this int leads to RenderMeshArray to read meshId+materialId
but if I have no RenderMeshArray I have no way to connect submeshes with materials because it requires two ints
(one int id for material - we don't have it
one int for mesh/submesh - we have it)

#

I'm stupid or it's not enough

robust stone
#

i guess you do need to add a rendermesharray then

#

that's a huge pain

feral ledge
#

yeah it ruins chunks

robust stone
#

you'd need to do what baking does and merge them

#

but that's a huge pain as well

#

i guess the better approach is just to create the layout in baking and replace the materials with your runtime ones?

feral ledge
#
        {
            // When using an index range, just return the first mesh of the range
            if (materialMeshInfo.HasMaterialMeshIndexRange)
            {
                if (!MaterialMeshSubMeshes.IsCreated)
                    return BatchMeshID.Null;

                RangeInt range = materialMeshInfo.MaterialMeshIndexRange;
                Assert.IsTrue(range.length > 0);

                return MaterialMeshSubMeshes[range.start].Mesh;
            }
            else

internally graphics resolves meshes and materials as pairs with one index
but for registering during runtime I found only

        /// <summary>
        /// Registers a material with the Entities Graphics System.
        /// </summary>
        /// <param name="material">The material instance to register</param>
        /// <returns>Returns the batch material ID</returns>
        public BatchMaterialID RegisterMaterial(Material material) => m_BatchRendererGroup.RegisterMaterial(material);

        /// <summary>
        /// Registers a mesh with the Entities Graphics System.
        /// </summary>
        /// <param name="mesh">Mesh instance to register</param>
        /// <returns>Returns the batch mesh ID</returns>
        public BatchMeshID RegisterMesh(Mesh mesh) => m_BatchRendererGroup.RegisterMesh(mesh);

maybe there are some way to register pair of material+mesh 🤔

robust stone
#

if you add your meshes to the rendermesharray it'll register them for you won't it

feral ledge
#

yeah but since it's sharedcomp I don't want to add it

robust stone
#

oh but didn't we land on it's required for single entity submeshes

feral ledge
#

RegisterMaterialsAndMeshesSystem registers material+mesh as one index per pair but it process RenderMeshArray only and has no API to register something manually
so I think it's better for me to drop this idea and stay with 20%-30% more entities than I can have with using more than 1 submeshes per entity
I have a troubles on steamdeck with rendering, it crashes constantly and I want to reduce amount of entities
probably later they will introduce some api to register it properly
or some problems will be solved in entitiesgraphics or in vulkan api idk
anyway thanks for your help

robust stone
#

out of interest, what is causing the crashing?

feral ledge
# robust stone out of interest, what is causing the crashing?
Obtained 9 stack frames.
#0  0x007f508ae4c48f in ScriptableRenderLoopDrawSRPBatcher(ScriptableLoopObjectData const*, unsigned long, SharedRendererScene const&, DrawRenderersCommand const&, ShaderPassContext&, GfxDevice&, int, BatchRendererGroupMetadataCacheContext const*)
#1  0x007f508ae56966 in ScriptableRenderLoopJob(GfxDeviceAsyncCommand::ArgScratch*, GfxDeviceAsyncCommand::Arg const*)
#2  0x007f508b32ba6d in GfxDeviceVKBase::ExecuteAsyncSetup(GfxDeviceAsyncCommand*)
#3  0x007f508ae74333 in ujob_execute_job(ujob_control_t*, ujob_lane_t*, ujob_job_t*, ujob_handle_t, unsigned int)
#4  0x007f508ae731f3 in lane_guts(ujob_control_t*, ujob_lane_t*, int, int)
#5  0x007f508ae753a5 in worker_thread_routine(void*)
#6  0x007f508af8a6db in Thread::RunThreadWrapper(void*)
#7  0x007f5089aa955a in (Unknown)
#8  0x007f5089b26a5c in (Unknown)```
Like this one
I'm not sure how to debug properly this kind of crashes so my guess is I overflow memory somehow
robust stone
#

ah that is troubling

feral ledge
#

also I can't understand why the address is so low for this crash
like reading something from very beginning of the memory?