C++ 从固定函数迁移到GLSL OpenGL:我应该如何修改我的视图(注视)矩阵和透视矩阵?

C++ 从固定函数迁移到GLSL OpenGL:我应该如何修改我的视图(注视)矩阵和透视矩阵?,c++,opengl,glsl,shader,C++,Opengl,Glsl,Shader,我正在尝试将我的OpenGL渲染管道从定点迁移到现代OpenGL。我的定点3D管线多年来运行良好。现在,当我切换到GLSL时,最终投影和对象方向看起来像“完全镜像或交换”。我排除了所有其他原因(如未能设置矩阵制服等),因为我可以通过随机拖动鼠标平移相机不时看到3D场景的渲染。因此,问题缩小到以下几点: 生成视图矩阵的函数(my函数getViewMat(pos、lookat、upaxis)) 生成透视投影矩阵的函数(我的函数getPerspectiveMat(fov、aspect、nearZ、f

我正在尝试将我的OpenGL渲染管道从定点迁移到现代OpenGL。我的定点3D管线多年来运行良好。现在,当我切换到GLSL时,最终投影和对象方向看起来像“完全镜像或交换”。我排除了所有其他原因(如未能设置矩阵制服等),因为我可以通过随机拖动鼠标平移相机不时看到3D场景的渲染。因此,问题缩小到以下几点:

  • 生成视图矩阵的函数(my函数getViewMat(pos、lookat、upaxis))
  • 生成透视投影矩阵的函数(我的函数getPerspectiveMat(fov、aspect、nearZ、farZ))
由于这两个函数以前为定点管道生成正确的视图/投影矩阵,现在我想知道是否/如何修改它们,使生成的矩阵适用于着色器管道

很少有人建议,对于着色器管道,我们需要手动翻转投影矩阵的Z值,但是视图矩阵呢?非常感谢你的建议

更新: 资源代码

/*
    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;
}
/*
Matrix4f的类成员“float m00、m01、m02、m03、m10、m11、…、m33”表示
一个以行为主的4x4矩阵,当传递给GLSL时,我记得要转置它们
*/
void Matrix4f::_getPerspectiveByFov(浮点视野、浮点aspectRatio、浮点nearZ、浮点farZ、整数矩阵类型)
{
浮球半视场=MathUtil::degToRad(视场)*0.5f;
浮动宽度、高度;
//我们使用宽度和高度之外的小边作为基础尺寸,然后通过纵横比计算另一侧。
浮球_tanFOV=(浮球)tan(半浮球);
if(aspectRatio<1.f)//宽度较小
{
宽度=2.f*nearZ*u tanFOV;
高度=宽度/纵横比;
}
否则//高度会更小
{
高度=2.f*nearZ*_tanFOV;
宽度=高度*纵横比;
}
/*
来自OpenGL参考的公式,请参见函数“glFrustum”。
|w 0 0 0|
|0小时0小时|
|0-cd|
|0      0       1       0|
w=2.f*近Z/宽度
h=2.f*近Z/高度
C=-(法尔兹+尼尔兹)/(法尔兹-尼尔兹)
D=-2.f*farZ*nearZ/(farZ-nearZ);
*/
float w=2.f*nearZ/width;//等于:[1.f/tan(视野*0.5f)]
float h=2.f*nearZ/height;//等于:[1.f/tan(视野*0.5f)/aspectRatio]
浮点数C=-(法尔兹+近兹)/(法尔兹-近兹);
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;
}
无效矩阵4f::_getLookAt(向量3f&pos、向量3f&lookat、向量3f&upAxis)
{
//注(前),(右),(上)是向量3f型的工作向量
_向上。设置(向上轴);
_前方潜艇(了望,位置);
_forward.normalize();
_对。交叉(向上,向前);
_对,normalize();
_向上。交叉(向前,向右);
_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;
//找到摄像机的位置
m03=位置x;
m13=位置y;
m23=位置z;
m30=0.f;
m31=0.f;
m32=0.f;
m33=1.f;
}

没有看到你在顶点着色器中做什么,我们只能猜测。但是,您可以在新OpenGL中使用与旧OpenGL中相同的矩阵。您可能没有的唯一矩阵是
glu透视图
,因此您可以自己实现它(以防您不再有glu.h)。我是这样做的:

void glPerspective(double fovy,double aspect,double zNear,double zFar)
    {
    double per[16],f;
    for (int i=0;i<16;i++) per[i]=0.0;
    // original gluProjection
//  f=divide(1.0,tan(0.5*fovy*deg))
//  per[ 0]=f/aspect;
//  per[ 5]=f;
    // corrected gluProjection
    f=divide(1.0,tan(0.5*fovy*deg*aspect));
    per[ 0]=f;
    per[ 5]=f*aspect;
    // z range
    per[10]=divide(zFar+zNear,zNear-zFar);
    per[11]=-1.0;
    per[14]=divide(2.0*zFar*zNear,zNear-zFar);
    glLoadMatrixd(per);
//  zNear=divide(-per[11],per[10]);     // get znear from perspective projection matrix
    }
然后在你想要的位置将它们输入矩阵

现在,如果您的
lookat
是目标对象的位置,则

Z = normalize(camera_position-lookat)
Y = up
X = cross(Y,Z)

不确定
X
应该是+还是-只要尝试一下,如果场景被镜像,那么就否定它。

感谢您的输入,添加所有源代码有点困难,我将尝试修改我的问题。1。我的4x4矩阵是行占优矩阵,我在发送到着色器(如果我忘记了,渲染结果是黑屏)2时对它们进行了转置。当我在着色器中乘以矩阵时,我这样做了:mat4 mat_vm=mat_view*mat_model;mat4 mat_pvm=mat_项目*mat_vm;按照其他帖子的建议,在计算投影矩阵后,我对z值求反:m02*-1,-m12*-1,-m22*-1,m32*-1,就像你建议的那样。但我开始看到黑屏,直到我随机否定视图矩阵中的一些值,使其出现。但是我不知道调整视图矩阵的正确方法?没有看到你在顶点着色器中做什么,我们只能猜测…虽然在看到你的答案之前我已经解决了我的问题,但是你的信息非常有用,谢谢!我的问题是,在My lookat()函数中生成的pos lookat axis矩阵是摄影机的世界变换矩阵,我应该使用其逆矩阵作为“视图”矩阵传入顶点着色器。
Z = normalize(camera_position-lookat)
Y = up
X = cross(Y,Z)