Search Unity

Bug Graphics.DrawMeshInstanced applies MaterialPropertyBlock incorrectly

Discussion in 'Graphics for ECS' started by Opeth001, Feb 25, 2021.

  1. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    Hello everyone,
    I am creating an extension for HRv2 which supports non vulkan devices and for that I use the API DrawMeshInstanced and MaterialPropertyBlock.
    but the MaterialPropertyBlock always applies the first element of each Override property to all rendered entities.
    I tried to reproduce the bug with a simple script to make sure the issue was not with the HRv2 extension.

    note: im using the URP SimpleLit shader.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PropertiesTest : MonoBehaviour
    6. {
    7.  
    8.     public GameObject[] gameObjects;
    9.  
    10.     Vector4[] m_Float4ArrayBuffer = new Vector4[24];
    11.     Matrix4x4[] m_MatricesArray = new Matrix4x4[24];
    12.     Color color = Color.green;
    13.     Mesh mesh;
    14.     Material material;
    15.     MaterialPropertyBlock materialPropertyBlock;
    16.  
    17.     // Start is called before the first frame update
    18.     void Start()
    19.     {
    20.         if (gameObjects.Length == 0)
    21.             return;
    22.  
    23.         var firstElement = gameObjects[0];
    24.  
    25.         material = firstElement.GetComponent<MeshRenderer>().sharedMaterial;
    26.         mesh = firstElement.GetComponent<MeshFilter>().sharedMesh;
    27.  
    28.         materialPropertyBlock = new MaterialPropertyBlock();
    29.  
    30.         for (var i=0; i< gameObjects.Length; i++)
    31.         {
    32.             m_MatricesArray[i] = gameObjects[i].transform.localToWorldMatrix;
    33.             m_Float4ArrayBuffer[i] = color;
    34.         }
    35.  
    36.         m_Float4ArrayBuffer[0] = Color.red;
    37.         m_Float4ArrayBuffer[5] = Color.blue;
    38.  
    39.         materialPropertyBlock.SetVectorArray("_BaseColor", m_Float4ArrayBuffer);
    40.     }
    41.  
    42.     // Update is called once per frame
    43.     void Update()
    44.     {
    45.         Graphics.DrawMeshInstanced(mesh, 0,  material, m_MatricesArray, gameObjects.Length, materialPropertyBlock);
    46.  
    47.     }
    48. }
    49.  
    as you can see i have applied different colors to index 0 and 5, but everything is rendered with the first Color element (red).

     
  2. julian-moschuering

    julian-moschuering

    Joined:
    Apr 15, 2014
    Posts:
    529
    You defined _BaseColor as an instanced property in the shader?
     
  3. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    _BaseColor is defined as instanced property by default in URP SimpleLit shader. please correct me if im wrong
     
  4. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    If you change index 0 to different color, will all cubes be that color?
    Did you set materiał to instnced?
     
    Opeth001 likes this.
  5. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    yes all instanced cubes always get the first element in the Material Property Block.
    and yes the material has GPU instancing enabled.
     
  6. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    btw this problem is also present on all shaders created using the Shader Graph.
     
    Last edited: Mar 1, 2021
  7. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    Check if your shader graph inputs are present, in shader properties, on the top of shader. You can see that after shader compilation into code.
    Last time I used shader grap with draw mesh instannced, I had add few lines of code to 5he shade manually, after it was compiled.

    With latest ECS and Shader Graph, I moved however from draw mesh entairly. But I use it in whole game before then. Now is much easier for me to use it.
     
    Opeth001 likes this.
  8. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    The properties are properly setted but from the shader code i see that they are not getting them by instance using MaterialPropertyBlock macro.
    btw even the Official Hybrid Render v2 is not working correctly with Shader Graph shaders + Property Overrides.
     
  9. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    Because there a bits missing in shader scripts after conversion from shader graph. Need be added manually.
    There 2 or 3 places, few lines need be replaced.

    I am on mobile, so unable to pinpoint atm, which lines.
     
    Opeth001 likes this.
  10. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    Just looked quickly into shader.

    For simple color change, look for _Color keyword

    Code (CSharp):
    1. Properties
    2.     {
    3.         _Color("Color", Vector) = (1, 0, 0, 0)
    4.     }
    Code (CSharp):
    1. // --------------------------------------------------
    2.             // Graph
    3.      
    4.             // Graph Properties
    5.             CBUFFER_START(UnityPerMaterial)
    6.                 float4 _Color;
    7.             CBUFFER_END
    8.      
    9.             // Custom Added for DOTS inputs.
    10.             UNITY_INSTANCING_BUFFER_START(Props)
    11.                 UNITY_DEFINE_INSTANCED_PROP(float4, _Color)
    12.             UNITY_INSTANCING_BUFFER_END(Props)
    Code (CSharp):
    1. SurfaceDescription SurfaceDescriptionFunction(SurfaceDescriptionInputs IN)
    2.             {
    3.                 SurfaceDescription surface = (SurfaceDescription)0;
    4.  
    5.                 float4 _Property_C8F17703_Out_0 = UNITY_ACCESS_INSTANCED_PROP(Props, _Color);
    6.                 // float4 _Property_C8F17703_Out_0 = _Color; // This line is replaced
    Only first SurfaceDescriptionFunction need be modified
     
    Opeth001 likes this.
  11. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,117
    Thanks, this is exactly what i did :)
     
    Antypodish likes this.