I'm trying to migrate my OpenGL rendering pipeline from fixed-point to modern OpenGL. My fixed-point 3D pipeline works well for years. Now when I switch to GLSL, the final projection and object orientation looks like "totally mirrored or swapped". I have excluded all other reasons (like fail to set matrix uniforms, etc.) since I can see the 3D scene is rendered from time to time by randomly dragging my mouse to pan the camera. So the question is narrowed down to the following:
- The function that generates view matrix (my function getViewMat(pos, lookat, upaxis))
- The function that generates perspective projection matrix (my function getPerspectiveMat(fov, aspect, nearZ, farZ))
Since these two functions generate correct view / projection matrix before for fixed-point pipeline, now I'm wondering whether / how I can modify them to make the generated matrices work for shader pipeline?
There are few stack overflow threads suggests that for shader pipeline, we need to manually flip Z value for projection matrix, but how about the view matrix? Many thanks for any suggestions.
Update: Soure code
/*
Matrix4f has class members "float m00, m01, m02, m03, m10, m11, ..., m33" representing
a row-dominant 4x4 matrix, when passed to GLSL, I have remembered to transpose them
*/
void Matrix4f::_getPerspectiveByFov(float fov, float aspectRatio, float nearZ, float farZ, int matrixType)
{
float halfFov = MathUtil::degToRad(fov) * 0.5f;
float width, height;
//We use the small side out of width and height as the base size, then calculate the other side by aspect ratio.
float _tanFOV = (float)tan(halfFov);
if(aspectRatio < 1.f)//width is smaller
{
width = 2.f * nearZ * _tanFOV;
height = width / aspectRatio;
}
else //height is smaller
{
height = 2.f * nearZ * _tanFOV;
width = height * aspectRatio;
}
/*
Formula from OpenGL reference, see function "glFrustum".
|w 0 0 0|
|0 h 0 0|
|0 0 -C D|
|0 0 1 0|
w = 2.f * nearZ / width
h = 2.f * nearZ / height
C = -(farZ + nearZ) / (farZ - nearZ)
D = -2.f * farZ * nearZ / (farZ - nearZ);
*/
float w = 2.f * nearZ / width; // Is equal to: [ 1.f / tan(fov*0.5f) ]
float h = 2.f * nearZ / height; // Is equal to: [ 1.f / tan(fov*0.5f) / aspectRatio ]
float C = -(farZ + nearZ) / (farZ - nearZ);
float D = -2.f * farZ * nearZ / (farZ - nearZ);
//-----------------------
m00 = w;
m01 = 0.f;
m02 = 0.f;
m03 = 0.f;
m10 = 0.f;
m11 = h;
m12 = 0.f;
m13 = 0.f;
m20 = 0.f;
m21 = 0.f;
m22 = -C;
m23 = D;
m30 = 0.f;
m31 = 0.f;
m32 = 1.f;
m33 = 0.f;
}
void Matrix4f::_getLookAt(Vector3f& pos, Vector3f& lookat, Vector3f& upAxis)
{
//Note _forward, _right, _up are working vector of type Vector3f
_up.set(upAxis);
_forward.sub(lookat, pos);
_forward.normalize();
_right.cross(_up, _forward);
_right.normalize();
_up.cross(_forward, _right);
_up.normalize();
m00 = _right.x;
m10 = _right.y;
m20 = _right.z;
m01 = _up.x;
m11 = _up.y;
m21 = _up.z;
m02 = _forward.x;
m12 = _forward.y;
m22 = _forward.z;
// Locate the camera
m03 = pos.x;
m13 = pos.y;
m23 = pos.z;
m30 = 0.f;
m31 = 0.f;
m32 = 0.f;
m33 = 1.f;
}