Search Unity

Trying to draw lots of meshes without using instancing

Discussion in 'General Graphics' started by WoompaDoop, Apr 10, 2020.

  1. WoompaDoop

    WoompaDoop

    Joined:
    Jul 28, 2015
    Posts:
    4
    I'm trying to draw thousands of planes in a scene, and in order to increase performance, I've been using DrawMeshInstanced(). However, I want the planes to have many different textures, so GPU instancing won't work as I've learned you can't modify ShaderGraph's material properties when it's being instanced.

    I tried using DrawMesh(), and the SRP Batcher does a great job of grouping nearly all of the draw calls, but calling DrawMesh() many, many times each frame is much less performant.

    I remember hearing somewhere that the SRP Batcher is (eventually) supposed to replace the need for traditional instancing, but is there a way now where I can efficiently draw the same mesh many times with either A: multiple materials or B: the same material with instanced properties? Is there a feature planned, or is that feature ECS?
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    All the examples using the SRP Batcher I’ve seen just have hundreds of game objects with normal renderer components on them. But also traditional instancing is still faster than the SRP Batcher for cases where instancing excels. This is probably a big reason why the hybrid DOTS renderer is heavily instancing based rather than leaning only on the SRP Batcher. Something like the Megacity demo required adding GPU instancing on top of the SRP Batcher’s improvements, but those features appear to still be in development.

    Until then you may want to look at texture arrays and hand modifying the Shader Graph generated code to add instancing support.
     
    WoompaDoop likes this.
  3. Neto_Kokku

    Neto_Kokku

    Joined:
    Feb 15, 2018
    Posts:
    1,751
    The SRP batcher reduces the work Unity does between draw calls, it doesn't eliminate them. If you have a thousand objects, you'll get a thousand draw calls (at least).
     
  4. Arycama

    Arycama

    Joined:
    May 25, 2014
    Posts:
    185
    You can use texture arrays or an atlas to draw all of the planes using instancing, but with different textures.

    Use a MaterialPropertyBlock for each instance, which tells it which "slice" of the texture array to use. Or if you're using an atlas, you can pass the ScaleOffset (As a Vector4) to each instance, telling it where to look.

    However, you'd probably be better off generating a single combined mesh for all of them (If they don't move) and setting the UV coordinates directly on the models.

    If they do move, unity's dynamic batching will probably do a good enough job combined with the above approach, of generating meshes through script and setting the UV coordinates directly on the mesh. (You can set Vector3 or Vector4 UV coordinates, so if you're using a TextureArray, you can encode the "Slice" as the Z component of the UV)

    Instancing is generally best when each model has thousands of vertices.
     
    WoompaDoop likes this.
  5. WoompaDoop

    WoompaDoop

    Joined:
    Jul 28, 2015
    Posts:
    4
    I didn't know you could do that until I read this! After trying to figure out how to do this, I've gotten it to work! Thank you so much, this is exactly what I needed.