Search Unity

Question How to properly access instanceID in HDRP shader code

Discussion in 'High Definition Render Pipeline' started by carcasanchez, Feb 28, 2020.

  1. carcasanchez

    carcasanchez

    Joined:
    Jul 15, 2018
    Posts:
    177
    Lately, I have been trying to build a Instancing Indirect system for HDRP. Despite the difficulties of working with shader code in SRP, I managed to draw whatever mesh I want.
    The problem is: only one instance is drawn. (however, my suspect is that all the instances are drawing in the same position).
    Before moving to use Structured buffers to set the positions, I use a simple hack of setting the instance position to (InstanceID, 0, 0), to give a little offset between them.
    To access the instanceID, have:
    Code (CSharp):
    1. // Vertex Graph Inputs
    2.                     struct VertexDescriptionInputs
    3.                     {
    4.                         uint instanceID : SV_InstanceID;
    5.                         float3 ObjectSpaceNormal; // optional
    6.                         float3 ObjectSpaceTangent; // optional
    7.                         float3 AbsoluteWorldSpacePosition; // optional
    8.                     };
    (Note this is a Shadergraph generated code)

    Still, only one instance is drawn.
    Later, I figured that my shaderCode is missing #define UNITY_INSTANCING_ENABLED. I turn it on and... nothing draws at all.
    (yes, I have #pragma multi_compile_instancing)
    I have found in some places of the code things like instanceID : INSTANCEID_SEMANTIC;, but I tried to use those and still, the same result.
    My suspect is that, enabling instancing, something is being redefined and wrecks everything.

    I have searched the web, and found that everyone uses different approaches.
    Can anyone tell me how this works, and how I get out of this mess?
     
  2. fct509

    fct509

    Joined:
    Aug 15, 2018
    Posts:
    108
    I just started looking into this myself, and from what I've seen in the documentation for HDRP, it might be possible to do this by hand-writing HLSL code for a custom post-process that's build onto of the post-processing system that's built into HDRP.

    I haven't had a chance to try this yet, because I found it just before calling it quits for the day.

    Edit:
    It took some really hacky code, but I was able to create a Renderer Shader for the included Renderers Custom Pass to get what I think are the system generated values: VertexID, PrimitiveID, and InstanceID.

    I had to define my own vertex and fragment shaders. On top of that, I had to copy some of the code for processing the input of the vertex shader. The really tricky part was outputting what I found.

    It turns out that there's a method for converting a uint32 into a R11B11G10-float3. This method makes use of a bit field extraction method that takes in the original bits (the uint32), the bit offset, and the number of bits to pull, and it will return a uint32 that has the bits you asked for at the very start. So, a uint32 containing the value 256 can be broken down into two uint32s that contain 255 and 1. Instead of going for r11b11g10, I went for rgb24, which is just the first 24 bits of the uint, so my value range is 0 to 16,777,215. I could try to go for rgba32 (0 to 4,294,967,295), but then I would also need to alter the alpha blending to do an overwrite blend for every pixel. I'll probably need to do that.

    Now, my test scene didn't make use of any instancing because the person that created it was an artist that exported the thing in such a way that every instance of a mesh created a duplicate mesh. Nvidia really, really needs a technical artist to clean up their ORCA project. Since each mesh was "unique", all my instance ids were either one or zero. This resulted in a black screen, which is what I would expect to see when there is zero mesh instancing going on.

    I'm not 100% sure if this is working correctly, because we're talking about displaying data that the human eye isn't really able to properly make out. In my test scene, the colors were ranging from black to red, black to green, and combinations of those three colors. I never saw a 100% green or 100% yellow, so the values in my test scene probably stayed well below 65,535, but would often hit above 255. I saw quite a few shades of orange, but I didn't see anything unexpected.

    Also, I think I'm going to have to save to OpenEXR images because I don't want to lose data by having the image converted over to a gamma color-space. These values are linear, so saving them to a linear color-space would be optimal.
     
    Last edited: Jun 5, 2021