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

标签 c++ opengl matrix

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

我有一个接口(interface) Drawable 和函数 virtual void Render(GLenum type) const = 0; 和一堆实现这个接口(interface)的类 (SphereCubeGridPlanePLYMeshOBJMesh)。

在我的 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();
}

我现在的问题如下:使用当前代码,我为每个对象使用相同的 ModelView 矩阵。如果我只想平移球体,或者只旋转平面而不改变顶点位置怎么办?在大型 OpenGL 程序中存储模型矩阵的最佳位置在哪里?将 protected 成员变量 glam::mat4 modelMatrix 放入 Drawable 接口(interface)怎么样?此外,是否应该拆分模型和 View 矩阵(例如,使用仅包含 View 矩阵的 Camera 类)?

最佳答案

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

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

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

Camera.cpp

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

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

然后您有一个模型实例,它有一个指向 Assets 的指针和一个唯一的变换矩阵。通过这种方式,您可以为特定 Assets 创建尽可能多的实例,每个实例都有自己独特的转换。

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

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

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));
}

关于c++ - 在 OpenGL 中存储模型矩阵的最佳位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26445174/

相关文章:

c++ - 在 C++ 中查找数组的最小值和第二小值

c++ - emscripten 和 boost 库 : how to compile existing project for webassembly?

c - Nehe在SDL2中的lesson02,正方形不是正方形

c++ - 替换 gluPerspective(使用 glFrustrum)

python - 使用 python 定位矩阵中的第 j-k 个元素

python - 在 Python 中优化两个矩阵的直方图距离度量

c++ - fetch_add with acq_rel 内存顺序

c++ - 如何获取系统调用的参数列表及其类型?

java - 一个 VBO 中有多个 Cube

matrix - MPI block 矩阵乘法