Search Unity

How does DrawMeshInstanced handle MaterialPropertyBlock arrays?

Discussion in 'General Graphics' started by Buretto, Jul 23, 2020.

  1. Buretto

    Buretto

    Joined:
    Mar 23, 2015
    Posts:
    49
    Say I wanted to draw 1000 meshes that can have 100 different material property values. How could I do that? Would I be able to use MaterialPropertyBlock.SetVectorArray("propertyName", array), with the array having a length of 100? Or would the length have to be at least 1000?

    Maybe I'm confused but IIRC
    Graphics.DrawMeshInstanced
    draws each mesh with the corresponding MaterialPropertyBlock array values, e.g: the 5th mesh drawn would use matricesArray[5]and also "propertyName[5]" so to speak.

    Is that correct?

    If so, I'm wondering what would happen if for example you used
    Graphics.DrawMeshInstanced(mesh, subMeshIndex, material, matricesArray, properties, castShadows, receiveShadows, layer)
    with the matrices array having a length greater than a properties' array length. For example, the array in
    MaterialPropertyBlock.SetVectorArray("propertyName", array)
    has a length of 10, but the matricesArray has a length of 20, so what material properties would be used after the 10th mesh being drawn?
    Would it default to using the property value at the last index?
    I'm hoping to be able to repeatedly use values, so for in this example, the 11th mesh drawn would use propertyName[0], 12th mesh drawn would use propertyName[0].

    My project inhibits me from using compute buffers.
     
  2. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    3,023
    Hi!
    The docs (https://docs.unity3d.com/ScriptReference/Graphics.DrawMeshInstanced.html) say:

    "The transformation matrix of each instance of the mesh should be packed into the matrices array. You can specify the number of instances to draw, or by default it is the length of the matrices array. Other per-instance data, if required by the shader, should be provided by creating arrays on the MaterialPropertyBlock argument using SetFloatArray, SetVectorArray and SetMatrixArray."
    This means that to draw 1000 meshes, you have to provide 1000 matrices. The arrays in the MaterialPropertyBlock also have to have 1000 elements if they have per-instance data.
     
  3. Buretto

    Buretto

    Joined:
    Mar 23, 2015
    Posts:
    49
    I did some tests today.
    It turns out that when the property array size is less than the number of mesh drawn, all "excess" meshes drawn will default to using the property's serialized value. I don't think that's mentioned anywhere so maybe it will help someone later wondering the same.

    I'm unfamiliar with what happens under the hood with graphic instancing; is it necessary for the property arrays to have the same size as the number of meshes drawn (to continue using varying properties)? Like if there was an "repeat" option rather than default to the same value, would that end up being the same as just populating the array to the correct size in the first place? (i.e. under the hood it would have to create and fill an array to the correct size by referencing the shorter input array values).

    At this point I'm asking more out of curiosity.
     
  4. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    3,023
    Looking at the code it fills the remainder, if any, with default value. It's preferable to have it have correct size in the first place, though.