Search Unity

Per-instance material params support in Entities 0.2!

Discussion in 'Entity Component System' started by siggigg, Nov 23, 2019.

  1. SecondCobra

    SecondCobra

    Joined:
    Jan 25, 2017
    Posts:
    31
    Nice, thanks for alerting us :)

    I replicated this in URP quickly, so full example below:
    Just remember, to add the hybrid renderer now you have to select 'Add package from git URL' in the package manager and type: "com.unity.rendering.hybrid" (without quotes).

    I have the following script on an empty game object with the ConvertToEntity component.

    Code (CSharp):
    1.  
    2. using Unity.Entities;
    3. using Unity.Mathematics;
    4. using Unity.Rendering;
    5. using Unity.Transforms;
    6. using UnityEngine;
    7.  
    8. public class CreateItems : MonoBehaviour, IConvertGameObjectToEntity
    9. {
    10.     [Tooltip("Prefab used for test items")]
    11.     [SerializeField]
    12.     private GameObject itemTemplate;
    13.  
    14.     public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    15.     {
    16.         GameObjectConversionSettings settings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, null);
    17.         var prefabEntity = GameObjectConversionUtility.ConvertGameObjectHierarchy(itemTemplate, settings);
    18.  
    19.         float shade1 = 0.1f;
    20.         float shade2 = 0.5f;
    21.  
    22.         for (float x = -10f; x < 20f; x += 2.6f)
    23.         {
    24.             var item = dstManager.Instantiate(prefabEntity);
    25.  
    26.             Translation tr = new Translation
    27.             {
    28.                 Value = new float3(x, 0, 0)
    29.             };
    30.  
    31.             MaterialColor mc = new MaterialColor
    32.             {
    33.                 Value = new float4(shade1, shade2, 0, 1)
    34.             };
    35.  
    36.             dstManager.SetComponentData<Translation>(item, tr);
    37.             dstManager.SetComponentData<MaterialColor>(item, mc);
    38.  
    39.             shade1 = shade1 >= 1f ? 0.1f : shade1 + 0.1f;
    40.             shade2 = shade2 >= 1f ? 0.1f : shade2 + 0.1f;
    41.         }
    42.     }
    43. }
    With the shader, as for DerEros:
    upload_2020-9-17_21-58-43.png

    The prefab just has a material with this shader, otherwise it's just a standard cube. Just add prefab to script in inspector.

    Result:
    upload_2020-9-17_22-4-17.png

    Thanks again to DerEros!
     
  2. AlexHolderDev

    AlexHolderDev

    Joined:
    Jul 2, 2014
    Posts:
    35
  3. jdtec

    jdtec

    Joined:
    Oct 25, 2017
    Posts:
    302
    Thanks to all the above help posted so far. Incase it saves the next person a few minutes or so, I got it working with a text shader by reverse engineering from a shader graph made one to get the required defines I was missing.

    I needed to add these defines in:
    Code (CSharp):
    1. #if defined(UNITY_DOTS_INSTANCING_ENABLED)
    2.             // DOTS instancing definitions
    3.             UNITY_DOTS_INSTANCING_START(MaterialPropertyMetadata)
    4.                 UNITY_DOTS_INSTANCED_PROP(float, _FillValue)
    5.             UNITY_DOTS_INSTANCING_END(MaterialPropertyMetadata)
    6.             // DOTS instancing usage macros
    7.             #define _FillValue UNITY_ACCESS_DOTS_INSTANCED_PROP_FROM_MACRO(float, Metadata__FillValue)
    8.             #endif
     
  4. Thygrrr

    Thygrrr

    Joined:
    Sep 23, 2013
    Posts:
    700
    How would you instance a texture? Is that even possible? I thought it's one of the hallmarks of the SRP batcher, but...neill it have to be a shared component data?
     
  5. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,264
    You can instance a texture atlas or a texture array but you cannot instance a texture by itself.
     
  6. HigginDazs

    HigginDazs

    Joined:
    Jun 29, 2013
    Posts:
    2
    Is it possible at all to use this with the build-in render pipeline? Or are instance material params solely used with URP/HDRP? It’s unsettling to see 10,000 boids flying towards you while flapping at the exact same time...
     
  7. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,264
    No. It only works with Scriptable Render Pipelines. There is a separate workflow for built-in and surface shaders which is pretty easy if you've touched the Graphics API before, but there is no out-of-the-box solution currently.
     
  8. HigginDazs

    HigginDazs

    Joined:
    Jun 29, 2013
    Posts:
    2
    Well that’s a shame... is there any documentation that might get me started on that?
     
  9. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,684
    Sorry if you meant HRv2 case, but if you speaking about a built-in pipeline with HRv1 (which is only supported for built-in in opposite to v2 only for SRP) and MaterialPropertyAttribute (not MPB) then it's not entirely correct. Of course, we can use DrawMesh(Instanced(Indirect))\DrawProcedural and MaterialPropertyBlock or any own solution based on constant\structured buffers, but if you just want to use HRv1 and don't want to write your own solution you can use MaterialPropertyAttribute in ECS land and in shader use it like:
    upload_2021-3-29_17-35-35.png

    upload_2021-3-29_17-35-39.png

    As all used in MaterialPropertyAttribute shader properties will be compiled to CBUFFER with _Array postfix which elements you can access easily.
    upload_2021-3-29_17-50-51.png
    And one more thing is profiling performance with\without PerInstanceCullingTag, as in our case performance was much better without it, and we reduced 5ms of culling on CPU without noticeable cost on GPU for things like units, buildings and animals in our RTS. But again this is valid only for HRv1 with built-in and users should use it very carefully :)
     
    Last edited: Mar 29, 2021
    bb8_1 likes this.
  10. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,264
    Thanks @eizenhorn! I actually did not know HRv1 could work with surface shaders that way. HRv1 was always too slow to be usable beyond 10k entities for me, and I don't recall culling being the bottleneck. Instead it had something to do with HRv1 reflecting properties on the main thread and then doing something funky with initializing dynamic batches that was really slow. Graphics.DrawMeshInstancedProcedural was an order of magnitude faster for me.
     
    bb8_1 likes this.
  11. Guedez

    Guedez

    Joined:
    Jun 1, 2012
    Posts:
    827
    Sorry for massive necroing this thread, but can you elaborate how you did this?
    I am currently suck with BuiltIn Render Pipeline and would really love per instance data working.