OpenGL 形状仅在初始位置为 (0, 0, 0) 时绘制

OpenGL shape only draws when initial position is (0, 0, 0)

本文关键字:绘制 位置 OpenGL      更新时间:2023-10-16

我有一个从 OBJ 文件加载的多维数据集。当我设置它的位置(0,0,0)时,一切正常。多维数据集呈现,我的函数为其提供速度,在屏幕上移动多维数据集。但是,如果我在进入渲染和计算速度变化的 while 循环之前将立方体的位置更改为 (0, 0, 0) 以外的位置,则立方体永远不会渲染。这是我第一次尝试在每次渲染帧时重新加载我的顶点,我假设我在那里搞砸了一些东西 - 但我查看了其他代码并且无法弄清楚是什么。

这是我的主要功能:

int main()
{
#ifdef TESTING
    testing();
    exit(0);
#endif
    setupAndInitializeWindow(768, 480, "Final Project");
    TriangleTriangleCollision collisionDetector;
    Asset cube1("cube.obj", "vertexShader.txt", "fragmentShader.txt");
    cube1.position = glm::vec3(0.0, 2.0, 0.0);
    cube1.velocity = glm::vec3(0.0, -0.004, 0.0);
    MVP = projection * view * model;
    do{
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        moveAsset(cube1);
        renderAsset(cube1);
        glfwSwapBuffers(window);
        glfwPollEvents();
    } while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
        glfwWindowShouldClose(window) == 0);
    glfwTerminate();
    return 0;
}

我的移动资产函数:

void moveAsset(Asset &asset)
{
    double currentTime = glfwGetTime();
    asset.position.x += (asset.velocity.x * (currentTime - asset.lastTime));
    asset.position.y += (asset.velocity.y * (currentTime - asset.lastTime));
    asset.position.z += (asset.velocity.z * (currentTime - asset.lastTime));
    for (glm::vec3 &vertex : asset.vertices)
    {
        glm::vec4 transformedVector = glm::translate(glm::mat4(1.0f), asset.position) * glm::vec4(vertex.x, vertex.y, vertex.z, 1);
        vertex = glm::vec3(transformedVector.x, transformedVector.y, transformedVector.z);
    }
    asset.lastTime = glfwGetTime();
}
void renderAsset(Asset asset)
{   
    glUseProgram(asset.programID);
    GLuint MatrixID = glGetUniformLocation(asset.programID, "MVP");
    glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, asset.vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, asset.vertices.size() * sizeof(glm::vec3), &asset.vertices[0], GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
    glDrawArrays(GL_TRIANGLES, 0, asset.vertices.size());
    glDisableVertexAttribArray(0);
}

我的模型、视图和投影矩阵定义为:

glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view = glm::lookAt(glm::vec3(5, 5, 10),
                            glm::vec3(0, 0, 0),
                            glm::vec3(0, 1, 0));
glm::mat4 projection = glm::perspective(45.0f, (float) _windowWidth / _windowHeight, 0.1f, 100.0f);

最后,我的资产结构:

struct Asset
{
    Asset() { }
    Asset(std::string assetOBJFile, std::string vertexShader, std::string fragmentShader)
    {
        glGenVertexArrays(1, &vertexArrayID);
        glBindVertexArray(vertexArrayID);
        programID = LoadShaders(vertexShader.c_str(), fragmentShader.c_str());
        // Read our .obj file
        std::vector<glm::vec2> uvs;
        std::vector<glm::vec3> normals;
        loadOBJ(assetOBJFile.c_str(), vertices, uvs, normals);
        // Load it into a VBO
        glGenBuffers(1, &vertexbuffer);
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
        //velocity = glm::vec3(0.0, 1.0, 1.0);
        velocity = glm::vec3(0.0, 0.0, 0.0);
        position = glm::vec3(0.0, 0.0, 0.0);
        lastTime = glfwGetTime();
    }
    GLuint vertexArrayID;
    GLuint programID;
    GLuint vertexbuffer;
    std::vector<glm::vec3> faces;
    std::vector<glm::vec3> vertices;
    glm::vec3 velocity;
    double lastTime;
    glm::vec3 position;
};

看起来您在每次迭代中都将当前asset.position添加到顶点位置,替换之前的位置。从moveAsset()函数:

for (glm::vec3 &vertex : asset.vertices)
{
    glm::vec4 transformedVector = glm::translate(glm::mat4(1.0f), asset.position) *
                                  glm::vec4(vertex.x, vertex.y, vertex.z, 1);
    vertex = glm::vec3(transformedVector.x, transformedVector.y, transformedVector.z);
}
暂时

忽略速度,并假设您在 (0, 0, 0) 处有一个原始顶点,您将在第一次迭代时将其移动到asset.position。然后在第二次迭代中再次添加asset.position,将其置于 2 * asset.position .然后在第三次迭代中,再次将asset.position添加到此当前位置,从而产生3 * asset.position 。因此,经过n步,顶点将在n * asset.position左右。即使您的对象最初可能是可见的,它也会在您眨眼之前移出可见范围。

为了使原始策略正常工作,最直接的方法是有两个顶点列表。一个列表包含原始对象坐标,您永远不会更改该坐标。然后在绘制之前,构建第二个顶点列表,计算为原始顶点加上当前asset.position之和,并使用第二个列表进行渲染。

整个事情是...不是很开放。实际上没有必要修改 CPU 上的顶点坐标。可以将平移作为顶点着色器中应用的变换的一部分。您已经有一个模型矩阵。您可以简单地将平移asset.position放入模型矩阵中,然后重新计算 MVP 矩阵。您已经具有将新矩阵传递给 renderAsset() 函数中的着色器程序的glUniformMatix4fv()调用。