不正确的外观矩阵

时间:2017-07-05 14:20:34

标签: c++ opengl matrix

我已经开始研究定向灯的阴影贴图,为此我需要一个lookAt矩阵,但是当我尝试从在线教程的示例构建时,它看起来像这样:

enter image description here

目前看起来像这样: https://media.giphy.com/media/QrMnqBBJZuATu/giphy.gif

我尝试了多种方法来构建它,但没有成功,我检查了规范化,交叉和翻译功能是否不正确但事实并非如此。我也试过从列主矩阵换到行主矩阵,但没有运气。有人能够指出我做错了吗?

Lookat矩阵构建:

中心向量=(0,0,0), 向上=(0,1,0)

Matrix4f Matrix4f::lookAt(const Vector3f& position, const Vector3f& center, const Vector3f& up) {
        Matrix4f out(1.0f); 

        Vector3f z = position.substract(center).normalize(); 


        Vector3f y = up;

        Vector3f x = y.cross(z).normalize();

        y = z.cross(x);

        out.mElements[0 * 4 + 0] = x.x;
        out.mElements[0 * 4 + 1] = x.y;
        out.mElements[0 * 4 + 2] = x.z;

        out.mElements[1 * 4 + 0] = y.x;
        out.mElements[1 * 4 + 1] = y.y;
        out.mElements[1 * 4 + 2] = y.z;

        out.mElements[2 * 4 + 0] = z.x;
        out.mElements[2 * 4 + 1] = z.y;
        out.mElements[2 * 4 + 2] = z.z;

        return (out * Matrix4f::translation(Vector3f(-position.x, -position.y, -position.z)));
    }
}

代码:https://stackoverflow.com/users/5577765/rabbid76

这就是我将矩阵传递给着色器的方法:

void Shader::setMat4(const char* name, const math::Matrix4f& matrix){
    glUniformMatrix4fv(getUniformLocation(name), 1, GL_TRUE, matrix.mElements);
}

在我计算了lookAt矩阵之后,我直接将它传递给顶点着色器到统一:view并计算出这样的点:

gl_Position = projection * view * model * vec4(vertexPosition, 1.0);

这就是我的矩阵乘法的工作原理:

Matrix4f Matrix4f::multiply(const Matrix4f& other) const {
    Matrix4f out;
    for (int y = 0; y < 4; y++) {
        for (int x = 0; x < 4; x++) {
            fl32 o = 0;
            for (int c = 0; c < 4; c++) {
                o += this->mElements[c + y * 4] * other.mElements[x + c * 4];                   }
            out.mElements[x + y * 4] = o;
        }
    }
    return out;
}

编辑:更新的图片 编辑:添加了更详细的说明

3 个答案:

答案 0 :(得分:3)

您需要在计算之前对s进行标准化。我不确定这是否是唯一的问题

答案 1 :(得分:2)

如果您的位置(positioncenter)和up矢量位于视口空间中,则视图矩阵的Z轴是反向视线和Y -Axis是向上矢量。请参阅以下代码:

Matrix4f Matrix4f::lookAt(const Vector3f& position, const Vector3f& center, const Vector3f& up)
{
    Matrix4f out(1.0f); // I suppose this initilizes a 4*4 identity matrix

    // Z-Axis is the line of sight
    Vector3f z = position.substract(center).normalize(); // inverse line of sight

    // Y-Axis is the up vector
    Vector3f y = up;

    // X-Axis is the cross product of Y-Axis and Z-Axis
    Vector3f x = y.cross(z).normalize();

    // orthonormalize the Y-Axis
    y = z.cross( x );

    out.mElements[0*4 + 0] = x.x;
    out.mElements[0*4 + 1] = x.y;
    out.mElements[0*4 + 2] = x.z;

    out.mElements[1*4 + 0] = y.x;
    out.mElements[1*4 + 1] = y.y;
    out.mElements[1*4 + 2] = y.z;

    out.mElements[2*4 + 0] = z.x;
    out.mElements[2*4 + 1] = z.y;
    out.mElements[2*4 + 2] = z.z;

    return (out * Matrix4f::translation(Vector3f(-position.x, -position.y, -position.z)));
}

答案 2 :(得分:1)

在尝试使外观矩阵工作数小时后,我放弃了构建外观矩阵的方法,而是使用三角函数I构建了一个基于相机位置和相机应该看的位置的外观矩阵。能够创造我正在寻找的结果。

我目前构建一个lookat矩阵的方法:

Matrix4f Matrix4f::lookAt(const Vector3f& position, const Vector3f& center) {
        Vector3f deltaVector = (position - center).normalize();

        fl32 yaw = (fl32)radToDeg(atan(deltaVector.x / deltaVector.z));
        fl32 pitch = (fl32)radToDeg(acos(Vector2f(deltaVector.x, deltaVector.z).magnitude()));

        if (deltaVector.z > 0)
            yaw = yaw - 180.0f;

        Matrix4f yRotation = Matrix4f::rotation(Vector3f(0.0f, 1.0f, 0.0f), -yaw);
        Matrix4f xRotation = Matrix4f::rotation(Vector3f(1.0f, 0.0f, 0.0f), pitch);

        Matrix4f translation = Matrix4f::translation(position);

        return (translation * (yRotation * xRotation));
    }