AdamsLair / duality

a 2D Game Development Framework
https://adamslair.github.io/duality
MIT License
1.4k stars 289 forks source link

Matrices passed to the shader (via the ShaderParameterCollection) are transposed #748

Open greyepoxy opened 4 years ago

greyepoxy commented 4 years ago

Summary

When passing a matrix to the shader via the Camera or DrawDevice's shaderParameters the resulting matrix in the shader is a transposed version of the passed in matrix.

How to reproduce

Since debugging a shader is quite difficult, I am not sure how to demonstrate this. I ran into this when passing a matrix to the shader code but you can also see this behavior with the default duality view Matrix and shader code. Let me describe the flow,

  1. The view matrix is constructed as a combination of a Translation and Rotation here
  2. The view matrix is passed to the shader but also used as part of the full matrix in IsSphereInView
  3. The Vector4.Transform method treats the vector as a 1x4 row based matrix when multiplying it against the passed in 4x4 matrix. From a math perspective this is like putting the vector on the left (rowVector matrix), vs putting it on the right (matrix columnVector).
  4. Alternatively in the shader the multiplication is backwards and the vector is being used as a column vector. This works fine since the matrix has been transposed from the original and is actually how the glsl docs (search for transposed) recommend getting and using a transposed matrix.

Workaround

In the shader code to multiply against the original matrix put the vector on the right (instead of the left) when performing the multiplication.

  mat4 result = myPassedInMatrix * someVector;

This is pretty straight forward but still extremely confusing when trying to debug why your shader is broken.

Analysis

When the ShaderParameterCollection serializes the matrix it does it row by row, but when glsl creates a matrix it reads the data column by column.