OpenGL MVP矩阵计算错误

时间:2016-06-07 08:26:30

标签: c opengl matrix perspectivecamera

我一直在关注一些OpenGL教程,而我的MVP矩阵计算似乎并没有像他们应该的那样工作。我怀疑我的某个功能中某处出现了错误,但我似乎无法确定它。我将不胜感激,因为我仍然是3D矩阵变换领域的初学者。

我作为MVP计算的一部分使用的函数:

float ToRadians(float Degrees)
{
    float Result = Degrees * (PI32 / 180.0f);

    return (Result);
}

mat4 Rotate(float Angle, vec3 Axis)
{
    // Creates an identity matrix
    mat4 Result = Mat4d(1.0f);

    float SinTheta = sinf(ToRadians(Angle));
    float CosTheta = cosf(ToRadians(Angle));

    Result.Elements[0][0] = (Axis.X * Axis.X * (1.0f - CosTheta)) + CosTheta;
    Result.Elements[0][1] = (Axis.X * Axis.Y * (1.0f - CosTheta)) - (Axis.Z * SinTheta);
    Result.Elements[0][2] = (Axis.X * Axis.Z * (1.0f - CosTheta)) + (Axis.Y * SinTheta);

    Result.Elements[1][0] = (Axis.Y * Axis.X * (1.0f - CosTheta)) + (Axis.Z * SinTheta);
    Result.Elements[1][1] = (Axis.Y * Axis.Y * (1.0f - CosTheta)) + CosTheta;
    Result.Elements[1][2] = (Axis.Y * Axis.Z * (1.0f - CosTheta)) - (Axis.X * SinTheta);

    Result.Elements[2][0] = (Axis.Z * Axis.X * (1.0f - CosTheta)) - (Axis.Y * SinTheta);
    Result.Elements[2][1] = (Axis.Z * Axis.Y * (1.0f - CosTheta)) + (Axis.X * SinTheta);
    Result.Elements[2][2] = (Axis.Z * Axis.Z * (1.0f - CosTheta)) + CosTheta;

    return (Result);
}

mat4 Translate(vec3 Translation)
{
    mat4 Result = Mat4d(1.0f);

    Result.Elements[3][0] = Translation.X;
    Result.Elements[3][1] = Translation.Y;
    Result.Elements[3][2] = Translation.Z;

    return (Result);
}

mat4 Perspective(float FOV, float AspectRatio, float Near, float Far)
{
    mat4 Result = Mat4d(1.0f);

    float TanThetaOver2 = tanf(FOV * (PI32 / 360.0f));

    Result.Elements[0][0] = 1.0f / TanThetaOver2;
    Result.Elements[1][1] = AspectRatio / TanThetaOver2;
    Result.Elements[2][3] = -1.0f;
    Result.Elements[2][2] = (Near + Far) / (Near - Far);
    Result.Elements[3][2] = (2.0f * Near * Far) / (Near - Far);
    Result.Elements[3][3] = 0.0f;

    return (Result);
}

我的主体的相关部分:

//  Model matrix
mat4 MatModel = Rotate(-45.0f, Vec3(1.0f, 0.0f, 0.0f));
//  View matrix
mat4 MatView = Translate(Vec3(0.0f, 0.0f, -3.0f));
//  Projection matrix
mat4 MatProjection = Perspective(45.0f,
                                 (GLfloat) 1024 / (GLfloat) 768,
                                 0.1f, 100.0f);

GLuint LocModel = glGetUniformLocation(ShaderProgramID, "Model");
GLuint LocView = glGetUniformLocation(ShaderProgramID, "View");
GLuint LocProjection = glGetUniformLocation(ShaderProgramID, "Projection");

glUniformMatrix4fv(LocModel, 1, GL_TRUE, (GLfloat*) MatModel.Elements);
glUniformMatrix4fv(LocView, 1, GL_TRUE, (GLfloat*) MatView.Elements);
glUniformMatrix4fv(LocProjection, 1, GL_TRUE, (GLfloat*) MatProjection.Elements);

//  Bind VAO and draw from EBO
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);

这是我的顶点着色器:

#version 330 core

layout (location = 0) in vec3 Position;
layout (location = 1) in vec2 CTexCoord;

out vec2 STexCoord;

uniform mat4 Model;
uniform mat4 View;
uniform mat4 Projection;

void main()
{
    gl_Position = Projection * View * Model * vec4(Position, 1.0f);
    STexCoord = CTexCoord;
}

在着色器中,没有Projection和View矩阵,旋转看起来很好,但是当添加View矩阵时,事情看起来很奇怪。通过添加Projection矩阵,不会渲染任何内容。

用于比较的图片:

Model / rotation matrix only applied

Model / rotation and View / translation matrices applied (does this look normal?)

应用完整的MVP矩阵后,除背景外不会显示任何内容。 (对不起,现在不能发布超过2个链接...)

提前致谢! :)

1 个答案:

答案 0 :(得分:0)

您对glUniformMatrix的调用设置转换为GL_TRUE,这意味着矩阵是行主要的。这意味着OpenGL期望矩阵每行中的元素在内存中相邻。您正在视图矩阵中设置翻译元素,如下所示:

Result.Elements[3][0] = Translation.X;
Result.Elements[3][1] = Translation.Y;
Result.Elements[3][2] = Translation.Z;

由于您告诉OpenGL您的矩阵是行主要的,这意味着Elements中的第一个下标是行,而Elements中的最后一个下标是列。这意味着您要将第4列中的第1列到第3列设置为平移。这会影响gl_Position的w分量,你会变得很奇怪。我可以看到你为你的投影矩阵做了同样的错误。基于此,我假设您将mat4设为专栏。如果是这种情况,我建议将glUniformMatrix中的转置参数更改为GL_FALSE。如果不是,您应该在翻译和投影建筑中交换行/列:

mat4 Translate(vec3 Translation)
{
   mat4 Result = Mat4d(1.0f);

   Result.Elements[0][3] = Translation.X;
   Result.Elements[1][3] = Translation.Y;
   Result.Elements[2][3] = Translation.Z;

   return (Result);
}