Search Unity

Sampler2D Instanced shader property ? Matrix[] ?

Discussion in 'Shaders' started by Cripple, Oct 31, 2016.

  1. Cripple

    Cripple

    Joined:
    Aug 16, 2012
    Posts:
    88
    Hi,

    I am currently updating my shaders to implement instancing.
    For that I need to have a CBUFFER property of type : Sampler2D (a texture).
    Each time I try to do this : "UNITY_DEFINE_INSTANCED_PROP(sampler2D, _BoneTransformsTexture)"
    It doesn't work... Is that even possible ?
    Same question with the array types : float4x4[] or float4[], can it be stored in the CBUFFER for instancing ?

    Thanks.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    7,160
    A cbuffer can hold a texture, but instanced cbuffers cannot. The problem is you can't have an array of textures, and instanced cbuffers work by storing data in an array and then using the instance ID as a look up index.

    What you'd need to do is use an array texture and then store an index value for that as an instanced property.
    https://docs.unity3d.com/ScriptReference/Texture2DArray.html

    Ideally Unity would just support this and automatically pack arrays of textures into an array texture, but there are a lot of "gotchas" with array textures.

    For a similar reason arrays of arrays is a problem. HLSL and GLSL are capable of multi-dimensional arrays, but every element of the array must be a uniform length, and the length must be defined. Technically speaking there's nothing preventing this from working apart from a lack of support built in to Unity's instancing stuff. It's plausible you could define your own UNITY_DEFINE_INSTANCED_PROP macros for arrays and it'd work, but I would guess Unity's internal instancing stuff would just skip instancing for materials with differing arrays.

    However if Unity's code doesn't get in the way something like this might work:

    #if defined(UNITY_SUPPORT_INSTANCING) && defined(INSTANCING_ON)
    UNITY_DEFINE_INSTANCED_PROP_ARRAY(type, name, size) type name[UNITY_INSTANCED_ARRAY_SIZE][size];
    #else
    UNITY_DEFINE_INSTANCED_PROP_ARRAY(type, name, size) type name[size];
    #endif


    Completely untested, but if it works the same UNITY_ACCESS_INSTANCED_PROP macro should work to get the data.
     
  3. Cripple

    Cripple

    Joined:
    Aug 16, 2012
    Posts:
    88
    Thanks for the answer, that explains quite a lot.
    I'll have to try something with Texture2DArrays then.
    I might just end up having to build an atlas though... I was hoping I could avoid that ^^ ...
     
  4. NathanJSmith

    NathanJSmith

    Joined:
    May 11, 2018
    Posts:
    49
    So if we can only set Texture2DArray, why the method MaterialPropertyBlock.SetTexture use the input type `Texture` instead of `Texture2DArray`? That method has 2 bad points: #1 It makes me cast from `Texture2DArray` to `Texture` to use it. #2 it make me think it's possible to edit `Texture` through MaterialPropertyBlock, but in the end, the shader doesn't support it. Does anyone know why the method has such misleading input type?

    Edit: correct: not set Texture2DArray but set the index of Texture2DArray. When I wrote the sentence above, I'm thinking about using MaterialPropertyBlock.GetTexture to get `Texture2DArray` so I can get the max index number of Texture2DArray.
     
    Last edited: Sep 19, 2018
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    7,160
    Because the MaterialPropertyBlock predates Unity’s instancing support by nearly a half a decade. Its use for setting instanced properties is it’s secondary purpose. It’s primary purpose is just to allow modifying material settings at runtime without needing to create a new material, and allow you to easily reset to the original material’s settings by clearing or removing the material property block. It also predates texture array support by the same time period. The original use for material property blocks, and one of the ways it’s still used today, is for setting the texture on sprites renderers.
     
    NathanJSmith likes this.
  6. NathanJSmith

    NathanJSmith

    Joined:
    May 11, 2018
    Posts:
    49
    Hi, sorry for bothering again. But I see that we can do this:
    Code (CSharp):
    1. MaterialPropertyBlock m_mpb;
    2. public Texture2D[] m_arrSkins;
    3.  
    4. //...
    5.  
    6.  
    7. //Loop this to draw
    8. Graphics.DrawMesh(
    9.                     m_mesh,
    10.                     Vector3.zero,
    11.                     m_rotation,
    12.                     m_crtMaterial,
    13.                     0,
    14.                     m_Camera,
    15.                     0,
    16.                     m_mpb);
    17.  
    18. //...
    19.  
    20. m_mpb.SetTexture("_MainTex",
    21.                 m_arrSkins[0]);
    22.                
    23. //Wait some time
    24.  
    25. m_mpb.SetTexture("_MainTex",
    26.                 m_arrSkins[1]);
    The shader's _MainTex doesn't need to UNITY_ACCESS_INSTANCED_PROP
    Code (CSharp):
    1.     Properties
    2.     {
    3.         _MainTex("Texture", 2D) = "white" {}
    4.     }
    5.     //...
    6.     sampler2D _MainTex;
    7.    
    8.     //...
    9.     void surf(Input IN, inout SurfaceOutput o)
    10.     {
    11.         o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;
    12.     }
    And it actually works, but I can't check that if this actually instance the _MainTex (like I expect) or it just creates other material in the background (which waste memory)?
     
  7. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    7,160
    This. Or rather you're just modifying the material's one texture property. There's nothing related to instancing here.

    Also, if what you mean by the //Wait some time line is you're waiting until the next frame, then of course this will work as, again, this has nothing to do with instancing. Instancing means drawing multiple copies of a mesh at once. Waiting a frame, or even just calling DrawMesh multiple times, means no instancing is occurring and you're just drawing the mesh multiple times normally.
     
  8. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,660
    Is there a solution to gpu Instancing texture yet?