Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Replicating Matrix4x4.TRS() function on the gpu?

Discussion in 'Shaders' started by JSmithIR, Aug 13, 2023.

  1. JSmithIR

    JSmithIR

    Joined:
    Apr 13, 2023
    Posts:
    84
    Hello, I need to replicate the math of this function
    https://docs.unity3d.com/ScriptReference/Matrix4x4.TRS.html

    on the gpu. It needs to take in a float3 (For scale), float3 (translation), and float4 (quaternion rotation) and build a float4x4 matrix that can be multiplied with a vertex position (i.e, mul(MYMATRIX, v.vertex) to get the intended transformation.

    I looked at the source code for "matrix4x4.cs" from this page: https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Math/Matrix4x4.cs

    which seems to be the math I must reproduce in hlsl. However, my implementation below does not work:

    Code (CSharp):
    1. float4x4 Scale(float3 vec)
    2. {
    3.     float4x4 m;
    4.     m._m00 = vec.x; m._m01 = 0.0; m._m02 = 0.0; m._m03 = 0.0;
    5.     m._m10 = 0.0; m._m11 = vec.y; m._m12 = 0.0; m._m13 = 0.0;
    6.     m._m20 = 0.0; m._m21 = 0.0; m._m22 = vec.z; m._m23 = 0.0;
    7.     m._m30 = 0.0; m._m31 = 0.0; m._m32 = 0.0; m._m33 = 1.0;
    8.     return m;
    9. }
    10.  
    11. // Creates a translation matrix.
    12. float4x4 Translate(float3 vec)
    13. {
    14.     float4x4 m;
    15.     m._m00 = 1.0; m._m01 = 0.0; m._m02 = 0.0; m._m03 = vec.x;
    16.     m._m10 = 0.0; m._m11 = 1.0; m._m12 = 0.0; m._m13 = vec.y;
    17.     m._m20 = 0.0; m._m21 = 0.0; m._m22 = 1.0; m._m23 = vec.z;
    18.     m._m30 = 0.0; m._m31 = 0.0; m._m32 = 0.0; m._m33 = 1.0;
    19.     return m;
    20. }
    21.  
    22. // Creates a rotation matrix. Note: Assumes unit quaternion
    23. float4x4 Rotate(float4 q)
    24. {
    25.     // Precalculate coordinate products
    26.     float x = q.x * 2.0;
    27.     float y = q.y * 2.0;
    28.     float z = q.z * 2.0;
    29.     float xx = q.x * x;
    30.     float yy = q.y * y;
    31.     float zz = q.z * z;
    32.     float xy = q.x * y;
    33.     float xz = q.x * z;
    34.     float yz = q.y * z;
    35.     float wx = q.w * x;
    36.     float wy = q.w * y;
    37.     float wz = q.w * z;
    38.  
    39.     // Calculate 3x3 matrix from orthonormal basis
    40.     float4x4 m;
    41.     m._m00 = 1.0f - (yy + zz); m._m10 = xy + wz; m._m20 = xz - wy; m._m30 = 0.0;
    42.     m._m01 = xy - wz; m._m11 = 1.0f - (xx + zz); m._m21 = yz + wx; m._m31 = 0.0;
    43.     m._m02 = xz + wy; m._m12 = yz - wx; m._m22 = 1.0f - (xx + yy); m._m32 = 0.0;
    44.     m._m03 = 0.0; m._m13 = 0.0; m._m23 = 0.0; m._m33 = 1.0;
    45.     return m;
    46. }
    47.  
    48. float4x4 TRS(float4x4 s, float4x4 r, float4x4 t)
    49. {
    50.     float4x4 final = mul(t, mul(s, r));
    51.     return final;
    52. }
    For the last method there, I tried every combination for ordering t, r, and s. So that is not where the issue lies. Can anyone provide some pointers?
     
  2. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    1,869
    If you manually make three matrices with each of rotate45, translate 1,2,3, scale 4,5,6, and then look at the resulting matrices, you will see that the "interesting" terms of these three operations do not overlap at all. Just construct the matrix with the appropriate terms and the appropriate values. Study lines 348 to 391 of the source code, and see how you could do the results of all three in a very similar function.
     
  3. JSmithIR

    JSmithIR

    Joined:
    Apr 13, 2023
    Posts:
    84
    I do not know how to do that. I mean, the function Matrix4x4.TRS takes an input of two vector3 and a quaternion and does some math to make the final matrix4x4. I just want to find that source code so I can translate it into HLSL
     
  4. JSmithIR

    JSmithIR

    Joined:
    Apr 13, 2023
    Posts:
    84
  5. Rukhanka

    Rukhanka

    Joined:
    Dec 14, 2022
    Posts:
    177
    Code (CSharp):
    1.  
    2. float4x4 QuatToMatrix(float4 q)
    3. {
    4.     float4x4 rotMat = float4x4
    5.     (
    6.         float4(1 - 2 * q.y * q.y - 2 * q.z * q.z, 2 * q.x * q.y + 2 * q.w * q.z, 2 * q.x * q.z - 2 * q.w * q.y, 0),
    7.         float4(2 * q.x * q.y - 2 * q.w * q.z, 1 - 2 * q.x * q.x - 2 * q.z * q.z, 2 * q.y * q.z + 2 * q.w * q.x, 0),
    8.         float4(2 * q.x * q.z + 2 * q.w * q.y, 2 * q.y * q.z - 2 * q.w * q.x, 1 - 2 * q.x * q.x - 2 * q.y * q.y, 0),
    9.         float4(0, 0, 0, 1)
    10.     );
    11.     return rotMat;
    12. }
    13.  
    14. float4x4 MakeTRSMatrix(float3 pos, float4 rotQuat, float3 scale)
    15. {
    16.     float4x4 rotPart = QuatToMatrix(rotQuat);
    17.     float4x4 trPart = float4x4(float4(scale.x, 0, 0, 0), float4(0, scale.y, 0, 0), float4(0, 0, scale.z, 0), float4(pos, 1));
    18.     return mul(rotPart, trPart);
    19. }
    20.  
     
    JSmithIR likes this.
  6. JSmithIR

    JSmithIR

    Joined:
    Apr 13, 2023
    Posts:
    84
    Thanks for this, going to try it out and will let you know!
     
  7. JSmithIR

    JSmithIR

    Joined:
    Apr 13, 2023
    Posts:
    84
    @Rukhanka hmmm we are close but this does not give quite the same results as Matrix.TRS() on the CPU. For example, when using the exact same vectors (or floats on the gpu) for translation, rotation, and scale, I get these two different matrices (printed to console at runtime):


    From Matrix4x4.TRS():

    0.96297 0.00000 -0.26963 -0.54868
    0.00000 1.00000 0.00000 0.00000
    0.26963 0.00000 0.96297 0.40844
    0.00000 0.00000 0.00000 1.00000


    From the proposed hlsl functions:


    0.96297 0.00000 0.26963 0.00000
    0.00000 1.00000 0.00000 0.00000
    -0.26963 0.00000 0.96297 0.00000
    -0.54868 0.00000 0.40844 1.00000


    So they are similar for sure, but for some reason the top right and bottom left are interchanged, two values in the bottom right are interchanged, and there are some signs reversed... anyone know why this is?
     
  8. Rukhanka

    Rukhanka

    Joined:
    Dec 14, 2022
    Posts:
    177
  9. JSmithIR

    JSmithIR

    Joined:
    Apr 13, 2023
    Posts:
    84
    @Rukhanka Thank you man I really appreciate you. Works like a charm. Made my day