在OpenGL中存储模型矩阵的最佳位置?

时间:2014-10-18 22:26:10

标签: c++ opengl matrix

我目前正在重构我的OpenGL程序(曾经是一个巨大的文件)来使用C ++类。基本框架如下所示:

我有一个带有Drawable函数的接口virtual void Render(GLenum type) const = 0;和一堆实现此接口的类(SphereCubeGrid,{{1 }},PlanePLYMesh)。

在我的OBJMesh我设置一个包含多个这些对象的场景,每个对象都有自己的着色器程序。在设置统一缓冲对象和每个程序的单个制服后,我正在呼叫main.cpp

在我的每个帧的glutMainLoop()函数中,我要做的第一件事就是设置所有的转换矩阵,最后为场景中的每个对象调用上面提到的Display函数:

Render

我现在的问题如下:使用当前代码,我为每个对象使用相同的void Display() { // Clear framebuffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); modelViewMatrix = glm::mat4(1.0); projectionMatrix = glm::mat4(1.0); normalMatrix = glm::mat4(1.0); modelViewMatrix = glm::lookAt(glm::vec3(0.0, 0.0, mouse_translate_z), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0)); modelViewMatrix = glm::rotate(modelViewMatrix, -mouse_rotate_x, glm::vec3(1.0f, 0.0f, 0.0f)); modelViewMatrix = glm::rotate(modelViewMatrix, -mouse_rotate_y, glm::vec3(0.0f, 1.0f, 0.0f)); projectionMatrix = glm::perspective(45.0f, (GLfloat)WINDOW_WIDTH / (GLfloat)WINDOW_HEIGHT, 1.0f, 10000.f); // No non-uniform scaling (only use mat3(normalMatrix in shader)) normalMatrix = modelViewMatrix; glBindBuffer(GL_UNIFORM_BUFFER, ubo_global_matrices); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), glm::value_ptr(modelViewMatrix)); glBufferSubData(GL_UNIFORM_BUFFER, 1 * sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(projectionMatrix)); glBufferSubData(GL_UNIFORM_BUFFER, 2 * sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(normalMatrix)); glBindBuffer(GL_UNIFORM_BUFFER, 0); // ************************************************** // // **************** DRAWING COMMANDS **************** // // ************************************************** // // Grid if (grid->GetIsRendered()) { program_GRID_NxN->Use(); grid->Render(GL_LINES); program_GRID_NxN->UnUse(); } // Plane ... // Sphere ... // Swap front and back buffer and redraw scene glutSwapBuffers(); glutPostRedisplay(); } 矩阵。如果我只想翻译球体,或只旋转平面而不改变顶点位置怎么办?在大型OpenGL程序中存储模型矩阵的最佳位置在哪里?将受保护的成员变量ModelView放入glam::mat4 modelMatrix接口怎么样?此外,是否应拆分模型和视图矩阵(例如,使用仅包含视图矩阵的Drawable类)?

1 个答案:

答案 0 :(得分:4)

我的回答主要基于Tom Dalling's excellent tutorial,但有一些细微的变化。

首先,所有视图和投影矩阵操作都应该在Camera类中。通过调用matrix()方法,相机将提供获取视图和投影矩阵的便捷方式。

glm::mat4 Camera::matrix() const {
    return projection() * view();
}

<强> Camera.cpp

然后,对于此示例,您将拥有模型资产,其中包含渲染几何图形所需的所有内容。此资产应该是唯一的,并存储在 ResourceManager 或类似的东西中。

struct ModelAsset {
    Shader*  shader;
    Texture* texture;
    GLuint   vbo;
    GLuint   vao;
    GLenum   drawType;
    GLint    drawStart;
    GLint    drawCount;
};

然后你有一个模型实例,它有一个指向assest的指针加上一个唯一的转换矩阵。通过这种方式,您可以创建具有自己唯一转换的特定资产的任意数量的实例。

struct ModelInstance {
    ModelAsset* asset;
    glm::mat4 transform;
};

ModelInstance cube;
cube.asset = &asset; // An asset that you created somewhere else (e.g. ResourceManager)
cube.transform = glm::mat4(); // Your unique transformation for this instance

要渲染一个实例,您将视图和模型矩阵作为制服传递给着色器,着色器完成其余的工作。

shaders->setUniform("camera", camera.matrix());
shaders->setUniform("model", cube.transform);

最后,最好将所有实例分组到一个可调整大小的容器中。

std::vector<ModelInstance> instances;
instances.push_back(cube);
instances.push_back(sphere);
instances.push_back(pyramid);

for (ModelInstance i : instances) {
    i.transform = glm::rotate(i.transform, getTime(), glm::vec3(0.0f, 1.0f, 0.0f));
}