立方体在旋转时未按预期呈现

Posted

技术标签:

【中文标题】立方体在旋转时未按预期呈现【英文标题】: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 作为基础。 【参考方案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 的了解不够多,无法对此发表评论。如果有人可以更好地解释它,请编辑我的答案。无论如何,这是我能找到的最佳解决方案。

【讨论】:

以上是关于立方体在旋转时未按预期呈现的主要内容,如果未能解决你的问题,请参考以下文章

立方体没有按预期使用openGL出现

Firebase云功能Firestore触发onWrite在本地测试时未按预期运行

sec:authorize 在 Spring 启动应用程序中使用 Thymeleaf 时未按预期工作

unity中立方体在旋转过程中变形 在线等~急!

如何css制作3d旋转立方体效果?

Replace(Environment.NewLine, "<br/>") 在网页上显示文本时未按预期工作