Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

Problem with DrawMeshInstance with HDRP or LWRP

Discussion in 'Graphics Experimental Previews' started by Renanmgs, Mar 18, 2019.

  1. Renanmgs

    Renanmgs

    Joined:
    May 16, 2016
    Posts:
    31
    Hy,
    Im trying to use DrawMeshInstancedIndirect with the new render pipeline, a got a nice result for my grass sistem using dinamic batching.
    Video:
    https://www.reddit.com/r/Unity3D/comments/b1ysgp/thanks_this_is_the_result_of_all_of_that_feedback/
    ,
    But is not so well performant, the CPU time is very high for this "little" amount of grass. So some friend suggested to use DrawMeshInstancedIndirect, but the exemple code in the forums are just for Legacy.
    So i thought you guys could help me a little cos im really lost.

    i tried to adapt a simple shader from shadergraph. I exported the master node to code, and it returned tha actual shader that unity uses, is a hude shader of 1800 lines.
    Then i tried to adapt it doing some of the things there are on the docs : docs.unity3d.com/560/Documentation/ScriptReference/Graphics.DrawMeshInstancedIndirect.html,

    This very very simple shadergraph structure:
    Generates this *.shader file: https://pastebin.com/kZC9bFrs. 1.8k lines.

    So to implement something from the docs that i've mentioned before, i need to focus on
    UNITY_PROCEDURAL_INSTANCING_ENABLED
    and
    #pragma multi_compile_instancing
    #pragma instancing_options procedural:setup

    The script works fine, only the positions are messed, something dont let the meshes go to the places where they are supposed to be, as you can see here:
    This happens with the normal shaders of HDRP, and the customized one that i modified (added some things from the exemples docs of DrawMeshInstancedIndirect.)

    I really liked how my scene looks, im impressed that i alone made everything (just the character from an asset). But im diving in the "performace wise" things, and for grass this really seems the way. Any other suggestion for good performace on thousand of grasses?

    I could reduce the Drawcalls a lot by dynamic batching, but the CPU time was the same, and then someone suggested DrawMeshInstancedIndirect.
     
  2. LennartJohansen

    LennartJohansen

    Joined:
    Dec 1, 2014
    Posts:
    2,394
    Hi.

    Instanced indirect setup function has to be done a bit differently on HD SRP since it renders in camera space to remove floating origin issues.

    Have a look at these nodes I made for the shader graph. These are for Vegetation Studios indirect implementation but you can change to yours.

    https://github.com/AwesomeTechnologies/VegetationStudioPro-ShaderGraphNodes

    Lennart
     
    steego, pachermann and Renanmgs like this.
  3. Renanmgs

    Renanmgs

    Joined:
    May 16, 2016
    Posts:
    31
    Wow, gonna try it out in some minutes! Gonna give some feedback soon !
     
  4. LennartJohansen

    LennartJohansen

    Joined:
    Dec 1, 2014
    Posts:
    2,394
    the important part is the 2 defines.

    Code (csharp):
    1.  
    2. #define unity_ObjectToWorld unity_ObjectToWorld
    3. #define unity_WorldToObject unity_WorldToObject
    4.  
    that gets around a problem with setting the matrix. This is needed on HD srp only
     
    oleg_v and Renanmgs like this.
  5. Renanmgs

    Renanmgs

    Joined:
    May 16, 2016
    Posts:
    31
    Well, just plugging the node dows not made the trick, instead, it turned my shader to pink.

    I made a video. We can see that it is rendering, but is not showing nothing anywhere.



    Even if i only plug the custom node, the shader stays pink and the same behaviour accours.
     
  6. Renanmgs

    Renanmgs

    Joined:
    May 16, 2016
    Posts:
    31
    And where im suposed to put this code? everywhere where i put it, it trows an warning and nothing happens. =C

     
  7. Renanmgs

    Renanmgs

    Joined:
    May 16, 2016
    Posts:
    31
    Even with a clean shader still not showing nothing but the CPU time goes crazy
     
  8. LennartJohansen

    LennartJohansen

    Joined:
    Dec 1, 2014
    Posts:
    2,394
    This has to go in your setup function where you set up the matrixes for rendering.

    The function you call with
    #pragma instancing_options procedural:setup

    But I think you missed a step here.

    In order for instanced indirect to work you need to set up a compute buffer on the CPU containing all the info you need to create the Object2World and World2Object matrixes in the setup function.

    This data you can access as a structured buffer there.

    Then you call the DrawMeshInstanceIndirect with a material that has this compute buffer assigned.
     
    Renanmgs likes this.
  9. Renanmgs

    Renanmgs

    Joined:
    May 16, 2016
    Posts:
    31
    I updated the shader:

    But the same behavior of a default shader happens, it renders all the meshes in the same place.

    Im using the code from the Docs:
    https://pastebin.com/meZpYbuR
     
  10. LennartJohansen

    LennartJohansen

    Joined:
    Dec 1, 2014
    Posts:
    2,394
    How does you c# code look? setting up the compute buffer and doing the render call?

    also could you post your setup function in the shader?
     
  11. Renanmgs

    Renanmgs

    Joined:
    May 16, 2016
    Posts:
    31
  12. Renanmgs

    Renanmgs

    Joined:
    May 16, 2016
    Posts:
    31
    And why the node is not working? any hint? Im suposed to do this manual editing if the node works?
     
  13. LennartJohansen

    LennartJohansen

    Joined:
    Dec 1, 2014
    Posts:
    2,394
    first the 2 define lines has to be inside the setup function. at the top.

    I did not check the math but you seem to assign the buffer and render as you shoud.

    Lennart
     
  14. Renanmgs

    Renanmgs

    Joined:
    May 16, 2016
    Posts:
    31
    Like this, right?
     
  15. LennartJohansen

    LennartJohansen

    Joined:
    Dec 1, 2014
    Posts:
    2,394
  16. Renanmgs

    Renanmgs

    Joined:
    May 16, 2016
    Posts:
    31
    Same =C
    I even tried to copy the shader code from your script, but the same happend as well.
     
  17. LennartJohansen

    LennartJohansen

    Joined:
    Dec 1, 2014
    Posts:
    2,394
    The shader code from my script will only work with the setup from Vegetation Studio Pro. It provides the pre created matrixes and control data in the compute buffer
     
  18. Renanmgs

    Renanmgs

    Joined:
    May 16, 2016
    Posts:
    31
    Dont seems to work anyway, editing your files, editing the shaders, etc =C, but i will keep trying
     
  19. Renanmgs

    Renanmgs

    Joined:
    May 16, 2016
    Posts:
    31
    Yeahhh babyy!!! I editted your solution and managed to work! Just need now to ajust the positions and Voilá!

    Many many thanks! Works wonderfully!
     
  20. aidan_unity879

    aidan_unity879

    Joined:
    Feb 14, 2019
    Posts:
    1
    Could you elaborate on how you fixed this?
     
    cdiggins-vimaec likes this.
  21. mephistonight

    mephistonight

    Joined:
    Dec 14, 2016
    Posts:
    75
    Hi Lennart,

    Thanks for sharing your custom node, that's really useful. Can I ask, what are you using the:

    Code (CSharp):
    1.            
    2. float4x4 InversePositionMatrix;
    3. float4 ControlData;
    4.  
    Data for in your shaders? Is it to do with LOD fading and occlusion culling?
     
  22. LennartJohansen

    LennartJohansen

    Joined:
    Dec 1, 2014
    Posts:
    2,394
    The Inverse matrix is needed if you have meshes that is not uniformly scaled.
    The control data I currently use 2 floats for compute shader calculated LODFade data and the last 2 for future use.
    Hard to redefine the struct later when there is a lot of shaders that has implemented it.

    Lennart
     
  23. fct509

    fct509

    Joined:
    Aug 15, 2018
    Posts:
    108
    As nice as it is to have:
    Code (CSharp):
    1. #define unity_ObjectToWorld unity_ObjectToWorld
    2. #define unity_WorldToObject unity_WorldToObject
    HDRP and URP are already using something to get that data (even if they call it something else). Recreating a variable that's no longer used and adding a C# script to fill it in can't be the best way to go. Wouldn't it be smoother to use the new versions of "unity_ObjectToWorld" and "unity_WorldToObject", whatever their names may be?
     
    LooperVFX likes this.
  24. beaugunderson

    beaugunderson

    Joined:
    Sep 3, 2020
    Posts:
    7
    When using HDRP, in ShareVariables.hlsl there are these defines:

    Code (CSharp):
    1. // To get instancing working, we must use UNITY_MATRIX_M / UNITY_MATRIX_I_M as UnityInstancing.hlsl redefine them
    2. #define unity_ObjectToWorld Use_Macro_UNITY_MATRIX_M_instead_of_unity_ObjectToWorld
    3. #define unity_WorldToObject Use_Macro_UNITY_MATRIX_I_M_instead_of_unity_WorldToObject
    So unity_ObjectToWorld can be replaced with UNITY_MATRIX_M and unity_WorldToObject with UNITY_MATRIX_I_M.