Search Unity

  1. We are migrating the Unity Forums to Unity Discussions. On July 12, the Unity Forums will become read-only.

    Please, do not make any changes to your username or email addresses at id.unity.com during this transition time.

    It's still possible to reply to existing private message conversations during the migration, but any new replies you post will be missing after the main migration is complete. We'll do our best to migrate these messages in a follow-up step.

    On July 15, Unity Discussions will become read-only until July 18, when the new design and the migrated forum contents will go live.


    Read our full announcement for more information and let us know if you have any questions.

Convert Shader to HD SRP

Discussion in 'Graphics Experimental Previews' started by Elecman, May 3, 2018.

  1. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,374
    I am having some trouble converting my unlit (emissive) billboard shader to the HD Scriptable Render Pipeline.

    The problem is with the new Camera Relative Rendering the HD SRP uses. See code below.

    Code (CSharp):
    1.         //Legacy pipeline version:
    2.         //output.pos = mul(UNITY_MATRIX_P, float4(UnityObjectToViewPos(input.center), 1.0f) + offset); //Place the vertex by moving it away from the center, rotate the billboard towards the camera.
    3.  
    4.         //HD SRP version, but it causes major rendering artifacts.
    5.         output.pos.xyz = TransformObjectToWorld(input.center.xyz);
    6.         output.pos = mul(UNITY_MATRIX_P, float4(output.pos.xyz, 1.0f) + offset); //Rotate billboard towards camera. Not sure how to convert this to SRP.
    7.         output.pos.xyz = GetCameraRelativePositionWS(output.pos.xyz);
    8.         output.pos = TransformWorldToHClip(output.pos.xyz);  
     
    Last edited: May 3, 2018
  2. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,374
    I fixed it now. This is the correct working version:

    Code (CSharp):
    1.         output.pos.xyz = TransformObjectToWorld(input.center.xyz + offset.xyz);
    2.         output.pos.xyz = GetCameraRelativePositionWS(output.pos.xyz);
    3.         output.pos = TransformWorldToHClip(output.pos.xyz);    
     
  3. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,374
    In Unity 2018.2.0f2 the Camera Relative Rendering seems to be broken. Commenting out line 2 in the code will at least render the lights, but they will not face the camera...
     
    Last edited: Aug 20, 2018
  4. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,374
    This seems to be the correct code, but I am awaiting confirmation that it is future proof:

    Code (CSharp):
    1. output.pos.xyz = TransformObjectToWorld(input.center.xyz);
    2. output.pos.xyz = TransformWorldToView(output.pos.xyz) + offset.xyz;
    3. output.pos = mul(UNITY_MATRIX_P, float4(output.pos.xyz, 1.0f));
     
    maromero and konsic like this.
  5. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,374
    This also works:
    Code (CSharp):
    1. positionWS = TransformObjectToWorld(input.center.xyz);
    2. output.pos.xyz = TransformWorldToView(positionWS) + offset.xyz;
    3. output.pos = TransformWViewToHClip(output.pos.xyz);
     
    Last edited: Nov 10, 2018
    maromero and miniduck like this.
  6. SebLagarde

    SebLagarde

    Unity Technologies

    Joined:
    Dec 30, 2015
    Posts:
    936
    Hi,

    Here is how camera relative is implemented, this can help you.

    We remove the translation part of the View Matrix on C# side
    and we add it the the object transform on hlsl side.

    The hlsl code that update the object transform is via the Macro UNITY_MATRIX_M

    float4x4 ApplyCameraTranslationToMatrix(float4x4 modelMatrix)
    {
    // To handle camera relative rendering we substract the camera position in the model matrix
    #if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
    modelMatrix._m03_m13_m23 -= _WorldSpaceCameraPos;
    #endif
    return modelMatrix;
    }

    #define UNITY_MATRIX_M ApplyCameraTranslationToMatrix(GetRawUnityObjectToWorld())

    So when using UNITY_MATRIX_M and UNITY_MATRIX_V you are all set. Note that the projection matrix have no impact.

    in our case we use TransformObjectToWorld and TransformWorldToHClip for all our operation

    float4x4 GetObjectToWorldMatrix()
    {
    return UNITY_MATRIX_M;
    }


    float3 TransformObjectToWorld(float3 positionOS)
    {
    return mul(GetObjectToWorldMatrix(), float4(positionOS, 1.0)).xyz;
    }

    See VertMesh.hlsl for correct use or camera relative rendering.

    We transform like this:

    // This return the camera relative position (if enable)
    float3 positionRWS = TransformObjectToWorld(input.positionOS);
    output.positionCS = TransformWorldToHClip(positionRWS);

    So indeed the equivalent of the above code if you split View and Projection matrice is:
    1. output.pos.xyz = TransformObjectToWorld(input.center.xyz);
    2. output.pos.xyz = TransformWorldToView(output.pos.xyz);
    3. output.pos = mul(UNITY_MATRIX_P, float4(output.pos.xyz, 1.0f));
    now you can include your extra transformation inside it, as you do
     
  7. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,374
    Thanks for the clarification.
     
    MadeFromPolygons likes this.