Search Unity

Resolved Graphics.DrawMeshInstanced does not show correct PropertyBlock color values

Discussion in 'General Graphics' started by OndraPaska, Sep 9, 2020.

  1. OndraPaska

    OndraPaska

    Joined:
    Jul 5, 2014
    Posts:
    14
    I'm struggling to have DrawMeshInstanced show different colors according to MaterialPropertyBlock values.
    This is what my code looks like:

    Code (CSharp):
    1. public class GPUInstanceMaterialsTest : MonoBehaviour
    2. {
    3.     public Mesh Mesh;
    4.     public Material Mat;
    5.  
    6.     private Matrix4x4[] _matrices;
    7.     private Vector4[] _colors;
    8.     private MaterialPropertyBlock _block;
    9.     private int Count = 4;
    10.     public void Start()
    11.     {
    12.         _matrices = new Matrix4x4[Count];
    13.         for (int i = 0; i < _matrices.Length; i++)
    14.         {
    15.             _matrices[i] = Matrix4x4.TRS(new Vector3(i * 3, 1, 1), Random.rotation, Vector3.one);
    16.         }
    17.         _block = new MaterialPropertyBlock();
    18.         _colors = new Vector4[Count];
    19.         _colors[0] = new Vector4(1, 0, 0, 1);
    20.         _colors[1] = new Vector4(0, 1, 0, 1);
    21.         _colors[2] = new Vector4(0, 0, 1, 1);
    22.         _colors[3] = new Vector4(0, 0, 0, 1);
    23.         _block.SetVectorArray("_Color", _colors);
    24.     }
    25.    
    26.     void Update()
    27.     {
    28.         Graphics.DrawMeshInstanced(Mesh, 0, Mat, _matrices, Count, _block, ShadowCastingMode.Off, false);
    29.     }
    30. }
    I would expect to see four meshes, each with a different color. Instead they are all red (or whatever the first color is). Using the latest Unity LTS.

    This is my shader:

    Code (CSharp):
    1. Shader "Custom/MinimalInstancedShader"
    2. {
    3.     Properties
    4.     {
    5.         _Color("Color", Color) = (1, 1, 1, 1)
    6.     }
    7.  
    8.     SubShader
    9.     {
    10.         Pass
    11.         {
    12.             CGPROGRAM
    13.  
    14.             #pragma vertex vert
    15.             #pragma fragment frag
    16.             #pragma multi_compile_instancing
    17.  
    18.             #include "UnityCG.cginc"
    19.  
    20.             struct appdata
    21.             {
    22.                 float4 vertex : POSITION;
    23.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    24.             };
    25.  
    26.             struct v2f
    27.             {
    28.                 float4 vertex : SV_POSITION;
    29.             };
    30.  
    31.             UNITY_INSTANCING_BUFFER_START(Props)
    32.             UNITY_DEFINE_INSTANCED_PROP(float4, _Color)
    33.             UNITY_INSTANCING_BUFFER_END(Props)
    34.  
    35.             v2f vert(appdata v)
    36.             {
    37.                 v2f o;
    38.                 UNITY_SETUP_INSTANCE_ID(v);              
    39.                 o.vertex = UnityObjectToClipPos(v.vertex);
    40.                 return o;
    41.             }
    42.  
    43.             fixed4 frag(v2f i) : SV_Target
    44.             {
    45.                 float4 color = UNITY_ACCESS_INSTANCED_PROP(Props, _Color);
    46.                 return color;
    47.             }
    48.             ENDCG
    49.         }
    50.     }
    51. }
    Thanks for any pointers, this is very confusing!
     
    Petrroll likes this.
  2. OndraPaska

    OndraPaska

    Joined:
    Jul 5, 2014
    Posts:
    14
    Anyone?
     
  3. grizzly

    grizzly

    Joined:
    Dec 5, 2012
    Posts:
    357
    To access those properties in the fragment shader you must transfer the instance id.

    Your shader looks remarkably similar to the doc's example here, less the transfer stuff...
    Code (CSharp):
    1. Shader "SimplestInstancedShader"
    2. {
    3.     Properties
    4.     {
    5.         _Color ("Color", Color) = (1, 1, 1, 1)
    6.     }
    7.  
    8.     SubShader
    9.     {
    10.         Tags { "RenderType"="Opaque" }
    11.         LOD 100
    12.  
    13.         Pass
    14.         {
    15.             CGPROGRAM
    16.             #pragma vertex vert
    17.             #pragma fragment frag
    18.             #pragma multi_compile_instancing
    19.             #include "UnityCG.cginc"
    20.  
    21.             struct appdata
    22.             {
    23.                 float4 vertex : POSITION;
    24.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    25.             };
    26.  
    27.             struct v2f
    28.             {
    29.                 float4 vertex : SV_POSITION;
    30.                 UNITY_VERTEX_INPUT_INSTANCE_ID // necessary only if you want to access instanced properties in fragment Shader.
    31.             };
    32.  
    33.             UNITY_INSTANCING_BUFFER_START(Props)
    34.                 UNITY_DEFINE_INSTANCED_PROP(float4, _Color)
    35.             UNITY_INSTANCING_BUFFER_END(Props)
    36.        
    37.             v2f vert(appdata v)
    38.             {
    39.                 v2f o;
    40.  
    41.                 UNITY_SETUP_INSTANCE_ID(v);
    42.                 UNITY_TRANSFER_INSTANCE_ID(v, o); // necessary only if you want to access instanced properties in the fragment Shader.
    43.  
    44.                 o.vertex = UnityObjectToClipPos(v.vertex);
    45.                 return o;
    46.             }
    47.        
    48.             fixed4 frag(v2f i) : SV_Target
    49.             {
    50.                 UNITY_SETUP_INSTANCE_ID(i); // necessary only if any instanced properties are going to be accessed in the fragment Shader.
    51.                 return UNITY_ACCESS_INSTANCED_PROP(Props, _Color);
    52.             }
    53.             ENDCG
    54.         }
    55.     }
    56. }
     
  4. OndraPaska

    OndraPaska

    Joined:
    Jul 5, 2014
    Posts:
    14
    Thanks a lot, that worked!