Home Technical Talk

3ds max - Auto Separate Mesh Into Material IDs?

polycounter lvl 19
Offline / Send Message
TorQue[MoD] polycounter lvl 19

I've got a lot of single meshes that are using multiple material IDs within the same mesh and it's tanking performance in Unreal. I was going to separate them into separate meshes to help reduce the draw calls, but some of the meshes have upwards of 34 material IDs. Doing this manually will take a long time so does anyone know of a script or other way to automate this?

Thanks!

Replies

  • poopipe
    Options
    Offline / Send Message
    poopipe grand marshal polycounter

    That won't reduce the number of drawcalls and will probably make your problems worse by increasing the number of actors on screen.

    Reducing the number of materials and unique meshes will reduce the number of drawcalls



    why do you believe this is tanking performance?

  • TorQue[MoD]
    Options
    Offline / Send Message
    TorQue[MoD] polycounter lvl 19

    Are you sure about that? I thought if a mesh has multiple material IDs then it has to be redrawn for each unique material essentially increasing the draw count by the number of unique materials? I'm pretty sure that's the argument for why it's always more performant to use a single texture atlas than multiple materials on a single mesh. Or obviously, the other option is to use modular geo and materials which will also reduce draw call with mesh instancing and by having only one material ID per mesh. I'm just trying to go with the least time-consuming option.

    The models in question are a set of building models that I purchased on the marketplace, but they're not optimized. They tank FPS down to somewhere between 30 - 40 down from 80 - 100, and when testing them in an empty scene with stat scenerendering, their draw calls are between 43 and 69 each, whereas a similar building that was optimized properly is only 30. Also, each mesh is around 250K tris so the extra weight of the poly count certainly doesn't help since the engine has to render the entire building all the time as it's one piece. Breaking it into multiple pieces would mean that not every poly has to be drawn all the time since the ones occluded will be culled.

    Finally, having more actors on screen isn't really a problem with modern GPUs. I'm not targeting mobile.

  • poopipe
    Options
    Offline / Send Message
    poopipe grand marshal polycounter

    you're not drawing the whole mesh multiple times - the GPU only really knows about groups of triangles that have a given material on.


    Unreal doesn't (naturally) batch materials across actors so even if you were to atlas all 100 materials into a single texture set you would still be paying 1 draw call per separate mesh actor.

    Since about 4.26 UE supports dynamic mesh instancing (its automatic) but my understanding is that it only works with identical static meshes at the same lod level - to support lods you need to explicitly generate Hierarchical Instanced Static Meshes (same/similar to the foliage rendering system)


    Anyway - for these. If the buildings share materials with each other you might want to consider using HLODs. This generates clusters that get progressively larger with distance and collapses the geometry within the clusters into a single mesh giving you one drawcall per material per cluster - it won't help you up close but that's usually not where the problems arise. Doing this comes with a memory cost since it must generate a mesh for each collapsed cluster. I believe the lods can be streamed, It's quick to try out and it's non-destructive so no harm in giving it a go.

    If they don't share materials you're kinda screwed and will need to weigh up whether you want to atlas within each building or try to make them actually share stuff. if you have material instances with color tints and stuff they should batch with each other (not 100% on that - its technically possible, not sure whether unreal handles it properly)


    The numbers you're describing would make me nervous on ps4/xbone - for the current gen/pc I'd be less worried but also angry at the bad assets

  • Klunk
    Options
    Offline / Send Message
    Klunk ngon master

    separating the mesh by id would be pointless as that's what happens anyway either by the exporter or by Unreal. You'll have to look elsewhere for optimizations.

  • TorQue[MoD]
    Options
    Offline / Send Message
    TorQue[MoD] polycounter lvl 19

    From what I've read about optimization, that doesn't make sense. If you have a single mesh at 100K polys with 1 material, vs a single mesh at 100K polys with 5 materials, the one with 5 cost 5x more to render. At least that's what I've read on these very forums. If you break that mesh into 5 pieces, it's still 100K polys, but won't cost as much to render since it's not being re-drawn 5X. I guess the easy way to settle the debate is to make a test. I'll do that soon and post my results.

  • TorQue[MoD]
    Options
    Offline / Send Message
    TorQue[MoD] polycounter lvl 19

    Okay, so I did a test. A simple cube, tesselated to 3 million tris, 3 different versions; Mesh with a single atlas material, mesh with 6 materials ids, and 6 separate meshes with their own material. The mesh with 1 material is only 3 draw calls, whereas the mesh with 6 unique materials is 13 draw calls so this is much more expensive. You are correct that there's no effect on the draw calls between the mesh with 6 material ids vs 6 meshes with 6 materials. Both have 13 draw calls. However, as I said, the other benefit of splitting the mesh is culling. So I think I'll still want to separate the mesh into pieces.

    Which, brings me back to my original question; does anyone know a faster method for separating a mesh into Material IDs?

  • TorQue[MoD]
    Options
    Offline / Send Message
    TorQue[MoD] polycounter lvl 19

    Thanks for the info. Yeah, I honestly think what the author did is built the buildings using procedural assets and then joined them together into a single static mesh for whatever reason. Super frustrating. I already mentioned it to them, but they're not likely to go back and re-design them. If I split them up into pieces, wouldn't the culling help reduce the draw calls? I guess at that point then, I don't need to worry about separating by material id though, I could just split them into arbitrary pieces. The reason I can't make a texture atlas for the buildings is that he's using tiling materials on them. Unless there's some software that I'm not aware of that will automatically render out a textured mesh into an atlas, then I think I'm screwed. Maybe I'll just re-do the textures entirely. Hmmm.

  • poopipe
    Options
    Offline / Send Message
    poopipe grand marshal polycounter

    unreal can make your atlas (merge actors) but you're looking at big textures or shit resolution (or both)


    breaking the assets up will allow you to frustrum and distance cull with more granularity - this is good because they allow you to ditch an asset early. the flip side of that is that you will need to spend more time in occlusion culling what's within the view frustrum which is a relatively slow process.

    Assuming 3PS/FPS viewpont I'd bust the buildings up into pieces, share as many materials as possible, try to reconstruct the buildings with as much mesh re-use as possible and HLOD everything.

    Systems like precomputed visibility volumes could help a lot with making the culling stage faster provided you're not building something open with long view distances

    There's no one size fits all solution for this sort of thing and in a lot of cases you're very much at the mercy of how the assets you're using were constructed.

  • TorQue[MoD]
    Options
    Offline / Send Message
    TorQue[MoD] polycounter lvl 19

    I thought Merge Actors just made them into a single mesh with multiple material ids. I'll look into that. Might work to split the building into pieces and then merge actors just to get everything onto one texture. Though how does it handle tiling materials? Probably not well.

    I'm rendering a city - well a few city blocks, so fairly open with long view distances. I'd imagine the buildings will block each other though so that should help with occlusion. I just started seeing about re-building the buildings using the modular pieces they included in the asset pack. It's a lot of work which is frustrating since the point of buying the pack was to save time, but it will give the best performance.

  • Klunk
    Options
    Offline / Send Message
    Klunk ngon master

    From what I've read about optimization, that doesn't make sense. If you have a single mesh at 100K polys with 1 material, vs a single mesh at 100K polys with 5 materials, the one with 5 cost 5x more to render. At least that's what I've read on these very forums. If you break that mesh into 5 pieces, it's still 100K polys, but won't cost as much to render since it's not being re-drawn 5X. I guess the easy way to settle the debate is to make a test. I'll do that soon and post my results.


    all i'm saying is if the mesh has 5 separate materials associated with it ie 5 material ID's the exporter will split the mesh any way so doing it manually or by script before hand is pointless.

  • TorQue[MoD]
    Options
    Offline / Send Message
    TorQue[MoD] polycounter lvl 19

    It imports as a single mesh inside Unreal though. What I was hoping to do is split the mesh into separate pieces.

  • poopipe
    Options
    Offline / Send Message
    poopipe grand marshal polycounter

    by the time it hits the GPU it's broken up by material regardless of how it's displayed to you in editor,


    makes no difference

  • TorQue[MoD]
    Options
    Offline / Send Message
    TorQue[MoD] polycounter lvl 19

    Oh okay. Then I guess just splitting the meshes up arbitrarily is the best way I can affect culling. Thanks for the help :)

Sign In or Register to comment.