Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Per-instance material params support in Entities 0.2!

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

  1. siggigg

    siggigg

    Joined:
    Apr 11, 2018
    Posts:
    247
    For some reason this was not in the release notes, but I've managed to get per-instance material params working in the 0.2 release. This is similar in function to the old material blocks.

    I've only tested this with HDRP so far.

    1. Create a new HDRP material (I used lit).
    2. Create a blackboard param, for example a Vector4 Color.
    3. Set the Reference field to something you can remember, I used "_Color"
    4. Check the "Hybrid Instanced (experimental)" checkbox on the blackboard variable!

    upload_2019-11-23_15-24-45.png

    5. Save your shader
    6. Create a material, and use the shader you created.
    7. Check "Enable GPU instancing" if you want to use that (doesnt seem to be necessary to make this work though).
    8. Set up a prefab with the material and spawn an entity with it in ECS.
    9. Create your own material param component, or you can use the included MaterialColor for example.

    Code (CSharp):
    1. [Serializable]
    2. [MaterialProperty("_Color", MaterialPropertyFormat.Float4)]
    3. public struct MaterialColor : IComponentData
    4. {
    5.     public float4 Value;
    6. }
    7.  
    8. [Serializable]
    9. [MaterialProperty("_Multi", MaterialPropertyFormat.Float)]
    10. public struct ColorMultiply : IComponentData
    11. {
    12.     public float Value;
    13. }
    Voila, ECS rendered meshes with materials that support per-instance params!

    Here as an example I set the color and a multiplier value (applied to the color of the upper cube).

    upload_2019-11-23_15-34-2.png
     
    Tony_Max, varnon, erenaydin and 32 others like this.
  2. Soaryn

    Soaryn

    Joined:
    Apr 17, 2015
    Posts:
    328
    It would seem that performance starts degrades after 8000 entities or so with 4 different color variants.
    UpdateDynamicRenderBatches takes about 25ms in build with 14,000 entities. 9ms were spent sorting (realistically waiting on a jobID from the looks of it) Comparing to the 200k cubes I had in an earlier instance without color variants, this would be a regression, but there is a chance I am using this system wrong.

    The scenario below: A spawner spawning in a cube with a EmissionComponent (Merely a MaterialColor component targeting a different shader component) and a velocity. The cube always heads forward and is spawned with a different rotation than the previous cube. @Joachim_Ante any thoughts on what to do to improve the system either on our side or Unity's?
    upload_2019-11-23_19-18-43.png
     
    deus0, GDevTeam, mr-gmg and 4 others like this.
  3. SubPixelPerfect

    SubPixelPerfect

    Joined:
    Oct 14, 2015
    Posts:
    224
    Just tested if it works with URP, and it isn't :(
     
  4. Soaryn

    Soaryn

    Joined:
    Apr 17, 2015
    Posts:
    328
    I believe everything for the moment is HDRP compliant, and URP will be at a later date. Trying to find the source of that as I remember reading that in the past couple posts.
     
  5. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Right now the only codepath we spent seriously optimising is static entities
    There is a bunch more work coming for making dynamic entities a lot faster.

    URP is not supported at the moment. Focus has been on HDRP. But it will come.
     
    deus0, Orimay, optimise and 8 others like this.
  6. Soaryn

    Soaryn

    Joined:
    Apr 17, 2015
    Posts:
    328
    I'm assuming static as in non-moving/changing entities. If so no worries :)

    If it is just referring to the MaterialProperty block concept, I am currently only able to get ~17k entities (non-dynamically colored) moving at a rough 60fps.

    For now I have other things that I have to look at with this update :D Namely burstable Command buffer and a few other additives. Just need to figure out how to go from a JSON string to a struct with a group of NativeStrings efficiently. :)
     
  7. GilCat

    GilCat

    Joined:
    Sep 21, 2013
    Posts:
    676
    Only Lit Master node of HDRP works right now.
     
  8. charleshendry

    charleshendry

    Joined:
    Jan 7, 2018
    Posts:
    95
    Just to confirm, is this also meant to work by modifying the MaterialColor component during runtime? @siggigg I think I've followed all your steps setting up the material. I create Entities at runtime, adding the MaterialColor component.
     
  9. siggigg

    siggigg

    Joined:
    Apr 11, 2018
    Posts:
    247
    Yes you can modify color or any other shader parameter at runtime. I have this driving health bar UIs in my game, sending a few parameters including fill percentage.
     
    GDevTeam likes this.
  10. Cell-i-Zenit

    Cell-i-Zenit

    Joined:
    Mar 11, 2016
    Posts:
    290
    Another question:

    so i just use this material and attach the component to an entity (and the rendermesh as shared component) and then it just works?
     
  11. siggigg

    siggigg

    Joined:
    Apr 11, 2018
    Posts:
    247
    As long as you follow my instructions then yes. You need to be using HDRP and you need to enable that flag in your shadergraph on the color parameter (and any other parameters you want to pass to the shader).
     
    Cell-i-Zenit likes this.
  12. charleshendry

    charleshendry

    Joined:
    Jan 7, 2018
    Posts:
    95
    Sorry - still can't get it working :confused:

    I created an HDRP shader based on Lit graph.
    upload_2019-12-7_20-18-37.png

    I create an HDRP material using this shader.
    upload_2019-12-7_20-20-4.png

    I then create Entities during runtime with a RenderMesh component using this material as well as a MaterialColor component, each one with random float4 values. All entities show a grey color. If I check the Entity Debugger, I can see the MaterialColor components with random float values.

    I'm using Unity 2020.1.0.a with Entities 0.3.0
     
    Last edited: Dec 7, 2019
  13. GilCat

    GilCat

    Joined:
    Sep 21, 2013
    Posts:
    676
    On Shader Graph did you connect the "_Color" property to the "_BaseColor" of Lit Master?
    Only that way you can make it work.
    Following that you can also create more properties to to other attributes of the Lit Master node giving you more per instance properties.
     
  14. charleshendry

    charleshendry

    Joined:
    Jan 7, 2018
    Posts:
    95
    Thanks @GilCat. That's it working now - hadn't used Shader Graph before
     
    siggigg likes this.
  15. Cell-i-Zenit

    Cell-i-Zenit

    Joined:
    Mar 11, 2016
    Posts:
    290
    Yes this works perferctly :)
     
  16. Sarkahn

    Sarkahn

    Joined:
    Jan 9, 2013
    Posts:
    440
    Really looking forward to when this works with URP, I love the simplicity of it. Better/more rendering solutions are badly needed in dots right now.
     
  17. tylo

    tylo

    Joined:
    Dec 7, 2009
    Posts:
    154
    Likewise. I am completely ignoring ECS until I don't have to write my own system to render entities with different material settings efficiently. I also don't want to use HDRP.
     
  18. JakHussain

    JakHussain

    Joined:
    Oct 20, 2016
    Posts:
    318
    I'm using entities 0.4.0 and in URP I see the hybrid instanced check mark but it doesn't seem to be working. Is this a bug?
     
  19. SubPixelPerfect

    SubPixelPerfect

    Joined:
    Oct 14, 2015
    Posts:
    224
    at the moment it works only for HDRP, see the reply from Joachim above
     
  20. Cell-i-Zenit

    Cell-i-Zenit

    Joined:
    Mar 11, 2016
    Posts:
    290
    Is it possible to have two or more properties inside a single component? Or do i need to create a component for each value that i want to submit?
     
  21. siggigg

    siggigg

    Joined:
    Apr 11, 2018
    Posts:
    247
    Afaik you need a separate component for each parameter, since the attribute goes on the struct itself.
     
  22. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,112
    is there a way to use LightMapData with MaterialPropertyblock ?
     
  23. JakHussain

    JakHussain

    Joined:
    Oct 20, 2016
    Posts:
    318
    As you can see above, dots no longer users material property blocks and instead binds values in component data to exposed shader graph values via an attribute on the component type.

    Secondly, what do you mean by light map data? What are you trying to do?
     
  24. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,112
    I'm trying to create my own hybred renderer cause the current one is not compatible with URP. So the one I'm trying to create is based on Graphics.DrawMeshInstanced.
    By lightmapdata I'm mean adding the Lightmap texture to materialpropertyblock like the normal gameobject renderer is doing
     
  25. andrew-lukasik

    andrew-lukasik

    Joined:
    Jan 31, 2013
    Posts:
    249
    Can't wait for this to also work in URP. Keep us updated please.
     
  26. T-Zee

    T-Zee

    Joined:
    Oct 23, 2017
    Posts:
    31
    wg-siggig likes this.
  27. GDevTeam

    GDevTeam

    Joined:
    Feb 14, 2014
    Posts:
    90
    This works. Thanks. But performance was down to 3 FPS for my project with 100k Entities. I ticked the Baked Emission box (Shader on Prefab in Project folder) and the FPS went back up mostly (lost 10 FPS or so). ;-/ Anyway suggestions to further optimize or is that the way it will just have to be on the performance side?

    (this was in the Editor, checking on build now. Build is back to the FPS I had before. Whewww. :))
     
  28. GDevTeam

    GDevTeam

    Joined:
    Feb 14, 2014
    Posts:
    90
    Can you show us how you would code a simple run-time color change? I don't know how to convert my (e.g. "#AAA9AD") string to a float4 so it works with the line of code below.

    I saw someone do this, EntityManager.AddComponentData(entity, new MaterialColor { Value = new float4(1,0,0,1) });.
     
    Last edited: May 13, 2020
  29. wg-siggig

    wg-siggig

    Joined:
    Mar 17, 2020
    Posts:
    36
    I'm surprised you work with color in that way instead of the Color type. What you need to do is parse that string into color values you can use. In this case the string is broken up into 3 colors, each represented by a hexadecimal value. R=AA B=A9 and G=AD. To do this you could write your own, or use Unity's ColorUtility.TryParseHtmlString() method.

    However I strongly suggest you change how you are storing color in your systems, since parsing this every frame is not cheap.
     
    Orimay and GDevTeam like this.
  30. GDevTeam

    GDevTeam

    Joined:
    Feb 14, 2014
    Posts:
    90
    Thanks. I have List<string> so the conversion. My brain is a bit fried today. I'd like to use a List that contains multiple types to resolve this issue. (NativeString64, int, floats, float4).
     
  31. SecondCobra

    SecondCobra

    Joined:
    Jan 25, 2017
    Posts:
    31
    Can I ask what shader you used as a base? Lit shader is not available in URP. I have tried the PBR and unlit shaders but with both I get : InvalidOperationException: Component "MaterialColor" cannot override material property "_Color" because it has already been overridden by component "MaterialColourComponent". Other than the shader, everything is set up as specified above.
     
  32. iamarugin

    iamarugin

    Joined:
    Dec 17, 2014
    Posts:
    880
    For Hybrid Renderer v1 I'm getting

    Shader error in 'Common/UnlitColorInstanced': invalid subscript '_Color_Array' at line 2184 (on d3d11)

    Compiling Fragment program with INSTANCING_ON
    Platform defines: UNITY_ENABLE_REFLECTION_BUFFERS UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING UNITY_ENABLE_DETAIL_NORMALMAP SHADER_API_DESKTOP UNITY_LIGHT_PROBE_PROXY_VOLUME UNITY_LIGHTMAP_FULL_HDR

    With hybrid rendering v1 (0.5.1) and HDRP 7.3.1 no matter what I am doing
    Shader is very simple:

     
    Last edited: May 30, 2020
  33. iamarugin

    iamarugin

    Joined:
    Dec 17, 2014
    Posts:
    880
    Looks like Shader Graph with Unlit Master node isn't working. Lit works, but to make the same effect with Lit I need to crank up Emissive value wich is not optimal.
     
  34. SecondCobra

    SecondCobra

    Joined:
    Jan 25, 2017
    Posts:
    31
    So I have my Unlit shader and a simple component (see below). After switching my prefab (from which my entities are instantiated) to use a material with this shader, I get the error "InvalidOperationException: Component "MaterialColor" cannot override material property "_Color" because it has already been overridden by component "MaterialColourComponent".
    This is without doing anything else, i.e. I'm not even trying to set the colour or add the component to the entity.
    upload_2020-6-3_17-43-8.png

    Code (CSharp):
    1.  
    2.     [Serializable]
    3.     [MaterialProperty("_Color", MaterialPropertyFormat.Float4)]
    4.     public struct MaterialColourComponent : IComponentData
    5.     {
    6.         public float4 Value;
    7.     }
    What am I doing wrong, as I seem to be following the instructions in the post?
    Thanks.
     

    Attached Files:

  35. iamarugin

    iamarugin

    Joined:
    Dec 17, 2014
    Posts:
    880
    Entities already have MaterialColor component which overrides _Color property.
     
    Tony_Max and wg-siggig like this.
  36. nicolasgramlich

    nicolasgramlich

    Joined:
    Sep 21, 2017
    Posts:
    231
    Besides what @iamarugin said:

    Either way, I think you'd still need to connect your property to the actual
    Color (3)
    input of the
    Unlit Master
    . Plus maybe give it a better human-readable name than
    Vector4
    :)
     
  37. SecondCobra

    SecondCobra

    Joined:
    Jan 25, 2017
    Posts:
    31
    Thanks, I had misread number 9 as 'create this material component'. Case of RTFM :( Thanks Nic and iamarugin, both these got it through. The actual color still isn't setting though.

    Color of the prefab material is green. The code below (in the Convert method of IConvertGameObjectToEntity) does not change it to red.

    Code (CSharp):
    1.  
    2.             em.AddComponent(item, typeof(MaterialColor));
    3.             MaterialColor mcc = new MaterialColor
    4.             {
    5.                 Value = new float4(1, 0, 0, 1)
    6.             };
    7.             em.SetComponentData<MaterialColor>(item, mcc);
     
  38. wg-siggig

    wg-siggig

    Joined:
    Mar 17, 2020
    Posts:
    36
    Did you follow the rest of the steps from my original post, including the "Enable GPU instancing" checkbox on the material?
     
  39. Hybridizer

    Hybridizer

    Joined:
    Feb 3, 2015
    Posts:
    18
    Very interested in this topic. However, how exactly do I apply a component such as MaterialColor? And are there differences or limitations with this process between the PureECS and ConvertToEntity workflows? I'm currently using ConvertToEntity and have a CTE Prefab spawn system set up, as well as a material that accepts instanced variables. How, and where, do I apply MaterialColor or similar components to the entities I spawn? Or, is this a feature currently only oriented at PureECS?
     
  40. SecondCobra

    SecondCobra

    Joined:
    Jan 25, 2017
    Posts:
    31
    The material is GPU Instanced.
    Just to clarify, this is using URP with a PBR shader. There doesn't seem to be a lit shader available under Create -> Shader. I tried unlit with the same result, i.e. the entities all stayed the original color.
    The only thing I haven't done from the original steps is the color multiplier. I don't understand where this gets set. While there is a MaterialColor in Unity.Rendering, there is not a ColorMultiply. Is it somewhere else? Do we have to create one ourselves? Should this plug into the shader somewhere? Could you please show your shader graph to explain?
     
  41. wg-siggig

    wg-siggig

    Joined:
    Mar 17, 2020
    Posts:
    36
    Hybrid supports Lit and Unlit in URP, see here: https://docs.unity3d.com/Packages/com.unity.rendering.hybrid@0.5/manual/index.html

    The ColorMultiply in my original examples was just to show how you can create your own parameters.

    Since I created my original post the framework also has built-in support for material overrides as assets.

    Maybe try following the steps in the documentation I list linked here above?

    One more thing, can you show me your shader graph? In the picture you posted above your exposed parameter isnt actually connected to color in your graph.
     
    Last edited: Jun 6, 2020
    Hybridizer likes this.
  42. SecondCobra

    SecondCobra

    Joined:
    Jan 25, 2017
    Posts:
    31
    Trying to create a lit shader in URP, where is Lit shader? Is there a different way of creating it?

    upload_2020-6-8_9-9-17.png

    The PBR graph shader I tried:
    upload_2020-6-8_9-11-52.png
     
  43. vectorized-runner

    vectorized-runner

    Joined:
    Jan 22, 2018
    Posts:
    396
    I also tried this in both HDRP and URP but I can't seem to make it work. I added MaterialProperty to all my entities and change it and runtime, but nothing changes they are still white. I made sure they are using the correct material etc... What am I missing here?
     
  44. Cell-i-Zenit

    Cell-i-Zenit

    Joined:
    Mar 11, 2016
    Posts:
    290
    1. see if the shader is correct, change the default values and see if they change appearance..
    2. rename _Color to something like _testABC and see if its not a name collision
     
  45. SecondCobra

    SecondCobra

    Joined:
    Jan 25, 2017
    Posts:
    31
    I got it working in HDRP but not URP. In HDRP I added the MaterialColor to a prefab that had a custom shader on the material (based on HDRP->Lit). In the Convert method (of IConvertToEntity), it creates two entities from the prefab and changes the color of the second:

    Code (CSharp):
    1. public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    2.     {
    3.         GameObjectConversionSettings settings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, null);
    4.         var prefabEntity = GameObjectConversionUtility.ConvertGameObjectHierarchy(prefab, settings);
    5.  
    6.         var item1 = dstManager.Instantiate(prefabEntity);
    7.         var item2 = dstManager.Instantiate(prefabEntity);
    8.  
    9.         Translation tr1 = new Translation
    10.         {
    11.             Value = new float3(1,1,1)
    12.         };
    13.  
    14.         Translation tr2 = new Translation
    15.         {
    16.             Value = new float3(-1,-1,-1)
    17.         };
    18.  
    19.         MaterialColor mcc = new MaterialColor
    20.         {
    21.             Value = new float4(1, 0, 0, 1)
    22.         };
    23.  
    24.         dstManager.SetComponentData<Translation>(item1, tr1);
    25.         dstManager.SetComponentData<Translation>(item2, tr2);
    26.         dstManager.SetComponentData<MaterialColor>(item2, mcc);
    27.     }
     
    Hybridizer and vectorized-runner like this.
  46. vectorized-runner

    vectorized-runner

    Joined:
    Jan 22, 2018
    Posts:
    396
    Thanks, I'll try this asap
     
  47. vectorized-runner

    vectorized-runner

    Joined:
    Jan 22, 2018
    Posts:
    396
    Okay I made it work in HDRP, my setup was correct but I was using a fresh scene which rendered my cubes black for some reason. If I use HDRP sample scene it works.
     
  48. vectorized-runner

    vectorized-runner

    Joined:
    Jan 22, 2018
    Posts:
    396
    I think it doesn't work in URP because the "DOTS Instancing" toggle does not exist in URP PBR graph.

    Screenshot_1.png Screenshot_2.png
     
  49. Fruei

    Fruei

    Joined:
    Nov 2, 2014
    Posts:
    3
    Hello, can you make that but with URP ?
    it´s posibble ? i was trying but when i update my Hybrid Renderer to preview.16-0.4.2, unity give me this error
    --------------------------------------------------------------
    Library\PackageCache\com.unity.rendering.hybrid@0.4.2-preview.16\Unity.Rendering.Hybrid\LodRequirementsUpdateSystem.cs(194,33): error CS7036: There is no argument given that corresponds to the required formal parameter 'dependency' of 'IJobForExtensions.ScheduleParallel<T>(T, int, int, JobHandle)'
    --------------------------------------------------------------
    Any idea ? May be its my unity version ? I´m using 2019.3.0f5

    I switch to that version of Hybrid Renderer because this Unity forum talks abot Hybrid Renderer V2
    https://docs.unity3d.com/Packages/c...23041-488480411.1592623041#hybrid-renderer-v1
     
  50. DerEros

    DerEros

    Joined:
    Sep 21, 2018
    Posts:
    1
    Hi,
    I'm quite new to Unity, DOTS/ECS and the whole RP topic. Thus, I'm very happy, that I can add some new information to this already quite informative thread. PBR Shader Graph now also supports DOTS instancing. And I was able to set a shader property via entity components the way siggigg describe it in his initial posting.

    Versions:
    Unity 2020.1.4f1
    URP 8.2.0
    Hybrid Renderer 0.8.0-preview.18

    upload_2020-9-11_20-4-55.png