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,
The view matrix is constructed as a combination of a Translation and Rotation here
The view matrix is passed to the shader but also used as part of the full matrix in IsSphereInView
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).
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.
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,
IsSphereInView
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).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.
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.