【问题标题】:Cube doesn't render as expected when rotated立方体在旋转时未按预期呈现
【发布时间】:2017-11-14 19:48:15
【问题描述】:

我正在使用 OpenGL 在 C++ 中开发一个应用程序。我的问题是,当我将一个立方体渲染到具有旋转的屏幕上时,它看起来不成比例(见图)。

我正在使用以下 NuGet 包:

当立方体旋转0度时:

当立方体旋转45度时:

当立方体旋转90度时:

当立方体旋转180度时:

当立方体旋转 360 度时:

以下代码是计算矩阵的地方:

glm::mat4 DrawnEntity::getMatrix() const
{
    glm::mat4 translate = glm::translate(glm::mat4(1.0f), position);
    glm::mat4 rotation = glm::toMat4(glm::quat(glm::radians(360.0f), 0, 1, 0));

    glm::mat4 matrix = translate * rotation;
    return matrix;
}

当实体被绘制时,这被称为:

void DrawnEntity::render()
{
    if (enabled)
        mesh->render(getMatrix());
}

随后称之为:

void Mesh::render(glm::mat4 matrix)
{
    glUseProgram(shaderID);
    vao->render(matrix);
}

vao 是一个 VertexArrayObject,这是函数:

void VertexArrayObject::render(glm::mat4 matrix)
{
    GLuint uModel = glGetUniformLocation(shaderID, "uModel");
    glUniformMatrix4fv(uModel, 1, GL_TRUE, &matrix[0][0]);
    glBindVertexArray(vao[0]);
    glDrawArrays(GL_TRIANGLES, 0, mesh->vertexCount());
    glBindVertexArray(0);
}

忽略旋转,似乎所有顶点都被正确加载。对于它的价值,这是生成多维数据集的类:

#include "CubeMesh.h"
#include "../VertexArrayObject.h"

CubeMesh::CubeMesh(GLuint shader)
{
    shaderID = shader;
    glUseProgram(shaderID);
    generateFaces();
    vao = new VertexArrayObject(this);
}

void CubeMesh::generateFaces()
{
    // Front face
    generateFace(glm::vec3(-0.5, 0.5, 0.5), glm::vec3(0.5, -0.5, 0.5));
    // Left face
    generateFace(glm::vec3(-0.5, -0.5, 0.5), glm::vec3(-0.5, 0.5, -0.5));
    // Back face
    generateFace2(glm::vec3(0.5, -0.5, -0.5), glm::vec3(-0.5, 0.5, -0.5));
    // Right face
    generateFace2(glm::vec3(0.5, -0.5, 0.5), glm::vec3(0.5, 0.5, -0.5));
}

void CubeMesh::generateFace(glm::vec3 point1, glm::vec3 point2)
{
    glm::vec3 tl = point1;
    glm::vec3 br = point2;
    glm::vec3 tr = glm::vec3(br.x, tl.y, br.z);
    glm::vec3 bl = glm::vec3(tl.x, br.y, tl.z);

    Vertex f1v1(glm::vec3(tl.x, tl.y, tl.z));
    Vertex f1v2(glm::vec3(bl.x, bl.y, bl.z));
    Vertex f1v3(glm::vec3(br.x, br.y, br.z));
    Triangle f1(f1v1, f1v2, f1v3);

    Vertex f2v1(glm::vec3(tr.x, tr.y, tr.z));
    Vertex f2v2(glm::vec3(tl.x, tl.y, tl.z));
    Vertex f2v3(glm::vec3(br.x, br.y, br.z));
    Triangle f2(f2v1, f2v2, f2v3);

    addData(f1);
    addData(f2);
}

void CubeMesh::generateFace2(glm::vec3 point1, glm::vec3 point2)
{
    glm::vec3 tl = point1;
    glm::vec3 br = point2;
    glm::vec3 tr = glm::vec3(br.x, tl.y, br.z);
    glm::vec3 bl = glm::vec3(tl.x, br.y, tl.z);

    Vertex f1v1(glm::vec3(tl.x, tl.y, tl.z));
    Vertex f1v2(glm::vec3(br.x, br.y, br.z));
    Vertex f1v3(glm::vec3(bl.x, bl.y, bl.z));
    Triangle f1(f1v1, f1v2, f1v3);

    Vertex f2v1(glm::vec3(tr.x, tr.y, tr.z));
    Vertex f2v2(glm::vec3(br.x, br.y, br.z));
    Vertex f2v3(glm::vec3(tl.x, tl.y, tl.z));
    Triangle f2(f2v1, f2v2, f2v3);

    addData(f1);
    addData(f2);
}

顶点着色器如下:

#version 430 core

uniform mat4 uModel;
uniform mat4 uView;
uniform mat4 uProjection;

in vec3 vPosition;
in vec3 vNormal;

out vec4 oColour;

void main(void)
{   
    oColour = vec4(vPosition, 1);
    gl_Position = vec4(vPosition, 1) * uModel * uView * uProjection;
}

uModel 是表示单个模型平移、旋转等的矩阵。uView 是相机的位置,uProjection 是投影矩阵。第一个被馈送到前面所示的 VertexArrayObject 中的着色器,而最后两个被馈送到相机对象中的着色器,如下所示:

void Camera::initialise()
{
    glUseProgram(shaderID);

    view = glm::translate(glm::mat4(1), position);

    int uView = glGetUniformLocation(shaderID, "uView");
    glUniformMatrix4fv(uView, 1, GL_TRUE, &view[0][0]);

    int uProjection = glGetUniformLocation(shaderID, "uProjection");
    glm::mat4 projection = glm::perspective(1.0, (double)1024 / (double)1024, 0.01, 10.0);
    glUniformMatrix4fv(uProjection, 1, GL_TRUE, &projection[0][0]);
}

模型的位置是0 0 0,相机的位置是0 0 -5。当 uModel 的位置发生变化时,立方体会在预期的位置渲染,但是随着旋转,它并没有发挥应有的作用。

任何人都可以看到我可能做错了什么吗?是否还有代码需要查看?

【问题讨论】:

  • 您构建view 矩阵的方式对我来说似乎有点可疑。通常,当您想要指定相机及其正在寻找的位置时,您会使用glm::lookAt。如果你用这个代码构造view 会发生什么:view = glm::lookAt(glm::vec3(0, 0, -5), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));?此外,虽然 1 Radian 对于您的透视矩阵来说是一个非常好的视野值(大约 57 度),但我不清楚这是一个有意的设计决定。
  • 遗憾的是,将视图更改为您提供的视图的唯一变化是立方体的颜色发生了变化(这只是因为片段着色器只是根据位置进行着色)。感谢您指出 FOV - 我没有意识到它是用弧度测量的。
  • 我想知道是否可以将此代码缩减到足以重现该问题?这里有很多事情要涉水。还是因为弧度问题你弄明白了?
  • 绝对将其修剪为minimal reproducible example。使用 GLFW 它应该很容易 this 作为基础。

标签: c++ opengl matrix glm-math


【解决方案1】:

我发现更改以下行:

glm::mat4 rotation = glm::toMat4(glm::quat(glm::radians(360.0f), 0, 1, 0));

到这里:

glm::mat4 rotation = glm::rotate(translate, (float)glm::radians(0.0), glm::vec3(0.0f, 1.0f, 0.0f));

解决了这个问题。我真的无法解释为什么第一个不起作用,因为我对 Quaternion 的了解不够多,无法对此发表评论。如果有人可以更好地解释它,请编辑我的答案。无论如何,这是我能找到的最佳解决方案。

【讨论】:

    猜你喜欢
    • 2018-09-28
    • 2022-11-10
    • 2015-03-19
    • 2017-02-23
    • 2018-10-01
    • 2014-09-29
    • 2017-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多