Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice
  2. Ever participated in one our Game Jams? Want pointers on your project? Our Evangelists will be available on Friday to give feedback. Come share your games with us!
    Dismiss Notice

GPU Instancing with different textures?

Discussion in 'Shaders' started by FadiObaji, Jun 24, 2020.

  1. FadiObaji

    FadiObaji

    Joined:
    Nov 24, 2017
    Posts:
    18
    I'm making use of GPU Instancing in my 2D game and it really reduces draw calls significantly when using the same Material and same sprite (texture) on all batched gameObjects.

    I'm changing colors using materialPropertyBlock and everything works fine.

    But is there a way to do that with different sprites (textures) on batched gameObjects' material?


    What if I used a Sprite atlas to gather all sprites together, will that make GPU Instancing possible with different sprites?
     
  2. flyer19

    flyer19

    Joined:
    Aug 26, 2016
    Posts:
    32
    try add sprite uv in materialPropertyBlock
     
  3. FadiObaji

    FadiObaji

    Joined:
    Nov 24, 2017
    Posts:
    18
    You mean _BaseColor, i added color as per-instance property, i'm talking about Texture. You can't add per-instance Texture property because GPU Instancing gather all objects that use the same Material and the same Texture.
     
  4. Samuel_Herb

    Samuel_Herb

    Joined:
    Jun 23, 2020
    Posts:
    6
    If your sprites are all packed into an atlas, you should be able to have a per instance float4 that defines what part of the atlas each sprite uses. I think that's what flyer19 was getting at.
     
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    8,798
    There are kind of a few questions being asked here:

    Can you have instanced Sprite Renderers that use different sprites within an atlas and still instance together?
    No. Unity's Sprite Renderer only supports sprite color and flipping to be instanced properties, as that's all that's built into the default sprite shader.

    Can you have instanced meshes that use different textures and still instance together?
    No. This isn't something GPUs can do. You can setup numerical values to be instanced, because the way instanced values work is by putting them all in an array, and GPUs only support arrays of numerical values. They cannot do arrays of textures.*

    Can you have instanced meshes that use a different sprites within an atlas and still instance together?
    Yes!
    With the caveats of the sprite atlas must have rectangular bounds for each sprite, so no tight packing, and you'll need to write your own custom instanced shader and c# scripts that can handle the UV offset & scale as well as potentially individual mesh transform scale if your have a variety of sprite sizes.

    To do this you can either render them manually using Graphics.DrawMeshInstanced and setup the relevant data arrays yourself, or by using regular MeshRenderer components, and using a script that modifies material properties via a MaterialPropertyBlock to set the texture offset and scale to adjust the UVs to the specific sprite you want that quad to display, as well as expose the render order and render layer properties on the mesh renderer component (which it has, but just doesn't expose or serialize like Sprite Renderer does).


    * DirectX 12 and Vulkan have support for bindless textures, which effectively allow for "arrays" of textures, but I don't think you can use those with Unity at the moment. There is also the Texture2DArray texture type, which is a "single texture" as far as the GPU is concerned, but it has multiple layers. It's effectively a single 3D texture without support for blending between layers. This is different than an array of textures.
     
  6. Binary42

    Binary42

    Joined:
    Aug 15, 2013
    Posts:
    164
    Sorry that i still have to ask in spite of your very good answer, but im struggling for quite some days now with this problem and atlases come with some drawbacks.
    Is instancing with a Texture2DArray supposed to work?
     
  7. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    8,798
    Instancing absolutely works with a Texture2DArray. But the same limitations exist. Ever instance needs to be using the same texture (again, a Texture2DArray is a single texture as far as the GPU is concerned) to instance together, but you can use an instanced property to select the layer index so each instance can be visually a "different texture". It also means you need a custom shader that supports this.
     
  8. Binary42

    Binary42

    Joined:
    Aug 15, 2013
    Posts:
    164
    @bgolus Thanks a lot for for your great support across the board!
     
unityunity