C++ 相同网格的多个图像,没有重复的三角形传输

C++ 相同网格的多个图像,没有重复的三角形传输,c++,opengl,glfw,C++,Opengl,Glfw,我使用OpenGL、GLEW和GLFW拍摄同一网格的多幅图像。网格三角形不会在每个快照中更改,只有ModelViewMatrix会更改 以下是我的主循环的重要代码: for (int i = 0; i < number_of_images; i++) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* se

我使用OpenGL、GLEW和GLFW拍摄同一网格的多幅图像。网格三角形不会在每个快照中更改,只有ModelViewMatrix会更改

以下是我的主循环的重要代码:

for (int i = 0; i < number_of_images; i++) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    /* set GL_MODELVIEW matrix depending on i */
    glBegin(GL_TRIANGLES);
    for (Triangle &t : mesh) {
        for (Point &p : t) {
            glVertex3f(p.x, p.y, p.z);
        }
    }
    glReadPixels(/*...*/) // get picture and store it somewhere
    glfwSwapBuffers();
}
如您所见,我为要拍摄的每个快照设置/转移三角形顶点。是否有一种只需转移一次的解决方案?我的网格相当大,因此转移需要相当长的时间。

在2016年,您不能使用glBegin/glEnd。不可能。改用,;并使用自定义和/或着色器重新定位和修改顶点数据。使用这些技术,您将数据上传到GPU一次,然后您将能够通过各种变换绘制相同的网格

以下是您的代码的大致外观:

// 1. Initialization.
// Object handles:
GLuint vao;
GLuint verticesVbo;
// Generate and bind vertex array object.
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Generate a buffer object.
glGenBuffers(1, &verticesVbo);
// Enable vertex attribute number 0, which
// corresponds to vertex coordinates in older OpenGL versions.
const GLuint ATTRIBINDEX_VERTEX = 0;
glEnableVertexAttribArray(ATTRIBINDEX_VERTEX);
// Bind buffer object.
glBindBuffer(GL_ARRAY_BUFFER, verticesVbo);
// Mesh geometry. In your actual code you probably will generate
// or load these data instead of hard-coding.
// This is an example of a single triangle.
GLfloat vertices[] = {
    0.0f, 0.0f, -9.0f,
    0.0f, 0.1f, -9.0f,
    1.0f, 1.0f, -9.0f
};
// Determine vertex data format.
glVertexAttribPointer(ATTRIBINDEX_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0);
// Pass actual data to the GPU.
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*3*3, vertices, GL_STATIC_DRAW);
// Initialization complete - unbinding objects.
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);

// 2. Draw calls.
while(/* draw calls are needed */) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glBindVertexArray(vao);
    // Set transformation matrix and/or other
    // transformation parameters here using glUniform* calls.
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glBindVertexArray(0); // Unbinding just as an example in case if some other code will bind something else later.
}
顶点着色器可能如下所示:

layout(location=0) in vec3 vertex_pos;
uniform mat4 viewProjectionMatrix; // Assuming you set this before glDrawArrays.

void main(void) {
    gl_Position = viewProjectionMatrix * vec4(vertex_pos, 1.0f);
}
另请看一本优秀的现代加速图形书籍。

2016年,您不得使用glBegin/glEnd。不可能。改用,;并使用自定义和/或着色器重新定位和修改顶点数据。使用这些技术,您将数据上传到GPU一次,然后您将能够通过各种变换绘制相同的网格

以下是您的代码的大致外观:

// 1. Initialization.
// Object handles:
GLuint vao;
GLuint verticesVbo;
// Generate and bind vertex array object.
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Generate a buffer object.
glGenBuffers(1, &verticesVbo);
// Enable vertex attribute number 0, which
// corresponds to vertex coordinates in older OpenGL versions.
const GLuint ATTRIBINDEX_VERTEX = 0;
glEnableVertexAttribArray(ATTRIBINDEX_VERTEX);
// Bind buffer object.
glBindBuffer(GL_ARRAY_BUFFER, verticesVbo);
// Mesh geometry. In your actual code you probably will generate
// or load these data instead of hard-coding.
// This is an example of a single triangle.
GLfloat vertices[] = {
    0.0f, 0.0f, -9.0f,
    0.0f, 0.1f, -9.0f,
    1.0f, 1.0f, -9.0f
};
// Determine vertex data format.
glVertexAttribPointer(ATTRIBINDEX_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0);
// Pass actual data to the GPU.
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*3*3, vertices, GL_STATIC_DRAW);
// Initialization complete - unbinding objects.
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);

// 2. Draw calls.
while(/* draw calls are needed */) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glBindVertexArray(vao);
    // Set transformation matrix and/or other
    // transformation parameters here using glUniform* calls.
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glBindVertexArray(0); // Unbinding just as an example in case if some other code will bind something else later.
}
顶点着色器可能如下所示:

layout(location=0) in vec3 vertex_pos;
uniform mat4 viewProjectionMatrix; // Assuming you set this before glDrawArrays.

void main(void) {
    gl_Position = viewProjectionMatrix * vec4(vertex_pos, 1.0f);
}

另请看一本优秀的现代加速图形书籍。

@BDL已经评论说,您应该放弃立即模式绘图调用glBegin…glEnd,转而使用顶点数组绘图glDrawElements,glDrawArrays从顶点缓冲区对象VBO获取数据@Sergey在回答中提到了顶点数组对象,但这些实际上是VBO的状态容器

你必须了解一件非常重要的事情——你问问题的方式显然是你还没有意识到的——那就是OpenGL不处理网格、场景等。OpenGL只是一个绘图API。它画点…线…和三角形…一次一个…它们之间没有任何联系。就这样。因此,当显示同一事物的多个视图时,必须多次绘制。这是没办法的


最新版本的OpenGL支持多视口渲染,但它仍然需要一个几何体着色器将几何体乘以几块以进行绘制。

@BDL已经评论说,您应该放弃立即模式绘制调用glBegin…glEnd,并切换到顶点数组绘制gldrawerelements,GLDrawArray,用于从VBOs的顶点缓冲区对象获取数据@Sergey在回答中提到了顶点数组对象,但这些实际上是VBO的状态容器

你必须了解一件非常重要的事情——你问问题的方式显然是你还没有意识到的——那就是OpenGL不处理网格、场景等。OpenGL只是一个绘图API。它画点…线…和三角形…一次一个…它们之间没有任何联系。就这样。因此,当显示同一事物的多个视图时,必须多次绘制。这是没办法的


最新版本的OpenGL支持多视口渲染,但仍需要一个几何体着色器将几何体乘成若干块进行绘制。

将网格上载到顶点缓冲区对象。最后:不要使用固定功能管道,因为它已经过时了,请转到核心配置文件。在这里,您必须使用顶点缓冲区对象。您使用的是旧的OpenGL API。尝试使用现代API。我知道有很多关于旧OpenGL的书,很难理解,哪里是学习OpenGL的正确方法。将网格上传到顶点缓冲区对象。最后:不要使用固定功能管道,因为它已经过时了,请转到核心配置文件。在这里,您必须使用顶点缓冲区对象。您使用的是旧的OpenGL API。尝试使用现代API。我知道有很多关于旧OpenGL的书,很难理解,哪里是学习OpenGL的正确方法。非常感谢。我知道,我使用的是非常古老的OpenGL。你的帖子促使我转向现代风格。非常感谢。我知道,我使用的是非常古老的OpenGL。你的帖子促使我转向现代风格。