Author: Nang Lanhai (Http://blog.csdn.net/you_lan_hai)
The difference between DirectX 3D and OpenGL coordinate system brings us a lot of trouble and makes the novice of cross-platform programming confused. Recently in a cross-platform game, carefully looking at the matrix of the two, found that there is no big difference, the D3D left-handed matrix passed to OpenGL shader can work perfectly.
Let's talk about some conceptual differences:
(1) Different coordinate systems
D3D left-hand coordinate system, OpenGL right-hand coordinate
(2) different row order of matrices
D3D Line first, OpenGL column first. These two differences directly lead to the inverse of the coordinate transformation order and the matrix multiplication order. If it is scaled first, then rotated, and finally translated, the corresponding matrix is S, R, T, then the final matrix of D3D is M = S * r * T,opengl m = T * R * S
(3) the Z-value range of the reduction space is different
D3D is [0, 1],opengl is [-1, 1]
On the surface, the two matrices differ greatly, but they are not.
1. Hand coordinate system
For a graphics device, the device coordinate system is left-handed, that is, the z-axis is pointing to the screen, and the greater the Z value indicates the farther away from the line of sight. Therefore, OpenGL's right-hand system, when it enters the cut space, is converted to a left-handed system. This means that within the rendering pipeline, the coordinate system is uniform. Whether it is the left-hand coordinate system matrix or the right-hand coordinate system matrix, as long as the transition to the cut space point is the left-hand system.
2. Matrix row Order
The row matrix and the column matrix, logically one is another transpose, but in the physical storage structure is exactly the same. such as a translation transformation (x, Y, z):
It is important to note that matrix multiplication does not care whether the matrix is a row or column matrix, and is multiplied by the row of the first matrix by the column of the second matrix. For the column matrix, this is the bad place, in order to ensure the validity of the multiplication meaning, the coordinate transformation order is the same as the matrix multiplication order exactly opposite.
Also note that in shader, OpenGL's matrix multiplication rules are different from D3D. Rule by matrix multiplication (first matrix row * Second matrix column):
D3D matrix multiplication: Ma (0 1 2 3) * MB (0 4 8 12)
OpenGL matrix multiplication: Ma (0 4 8) * MB (0 1 2 3)
Therefore, for OpenGL shader, the transformation order and matrix multiplication order are still reversed. If we can transpose the matrix of incoming OpenGL shader, then the shader matrix multiplication of OpenGL will be exactly the same as D3D shader.
3. Modify the projection matrix
Since OpenGL's cut-space Z-value range is [-1, 1] Unlike D3D's [0, 1], we cannot simply use the D3D projection matrix and must redefine the D3D projection matrix.
void Matrix::p erspectiveProjectionLH2 (float FoV, float aspectratio,
float nearplane, float farplane)
{
Float h = (1.0f/tanf (FOV * 0.5f));
float w = h/aspectratio;
float A = (Farplane + nearplane)/(Farplane-nearplane);
Float B = -2.0f * Farplane * Nearplane/(Farplane-nearplane);
M[0][0] = W; M[0][1] = 0; M[0][2] = 0; M[0][3] = 0;
M[1][0] = 0; M[1][1] = h; M[1][2] = 0; M[1][3] = 0;
M[2][0] = 0; M[2][1] = 0; M[2][2] = A; M[2][3] = 1;
M[3][0] = 0; M[3][1] = 0; M[3][2] = b; M[3][3] = 0;
}
4. Summary
It is convenient to use the left-handed transform to unify two platforms. Summarize the steps to modify the OpenGL rendering pipeline:
(1) in the C + + layer Unified use left-handed coordinate system transformation;
(2) Modify the projection matrix to fit the z-coordinate range of the cut space [-1, 1];
(3) When the matrix is passed into the shader, the Matrix's transpose matrix is introduced;
(4) In the shader layer, the uniform use of left-handed coordinate system transformation.
If you do not want to modify the transformations in the shader, just do (1) and (2) suffice.
5. Read more
Derivation of projection matrix http://blog.csdn.net/popy007/article/details/4091967
Bridging the gap between OpenGL and D3D http://www.cppblog.com/topjackhjj/articles/157038.html