多个对象绘图(OpenGL)

Rev*_*orn 14 c++ opengl console-application

问题是我无法弄清楚如何正确绘制两个对象,因为我没有绘制另一个对象.

这是主要代码:

GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
GLuint VertexArrayID2;
glGenVertexArrays(1, &VertexArrayID2);
glBindVertexArray(VertexArrayID2);

GLuint programID = LoadShaders( "SimpleVertexShader.vertexshader", "SimpleFragmentShader.fragmentshader" );

GLuint MatrixID = glGetUniformLocation(programID, "MVP");
GLuint MatrixID2 = glGetUniformLocation(programID, "MVP2");

glm::mat4 Projection = glm::perspective(45.0f, 5.0f / 4.0f, 0.1f, 100.0f);
glm::mat4 View       = glm::lookAt(
    glm::vec3(4*2,3*2,8*2),
    glm::vec3(0,0,0),
    glm::vec3(0,1,0)
);
glm::mat4 Model      = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 0.0f));
glm::mat4 MVP        = Projection * View * Model;

glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);

glm::mat4 Model2      = glm::translate(glm::mat4(1.0f), glm::vec3(-5.0f, 0.0f, 0.0f));
glm::mat4 MVP2        = Projection * View * Model2;

glUniformMatrix4fv(MatrixID2, 1, GL_FALSE, &MVP2[0][0]);

static const GLfloat g_vertex_buffer_data[] = {
    -1.0f,-1.0f,-1.0f,
    -1.0f,-1.0f, 1.0f,
             (plenty of floats) 
     1.0f,-1.0f, 1.0f
};

static const GLfloat g_vertex_buffer_data2[] = { 
    -1.0f, -1.0f, 3.0f,
     (plenty of floats)
     0.0f,  1.0f, 2.0f,
};


GLuint vertexbuffer; 
glGenBuffers(1, &vertexbuffer); 
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); 
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);

GLuint vertexbuffer2;
glGenBuffers(1, &vertexbuffer2);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer2);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data2), g_vertex_buffer_data2, GL_STATIC_DRAW);

do{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glUseProgram(programID);

    glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
    glUniformMatrix4fv(MatrixID2, 1, GL_FALSE, &MVP2[0][0]);

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,(void*)0);

    glDrawArrays(GL_TRIANGLES, 0, 12*3);        

    glEnableVertexAttribArray(2);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer2);
    glVertexAttribPointer(2,3,GL_FLOAT,GL_FALSE,0,(void*)0);

    glDrawArrays(GL_TRIANGLES, 0, 4*3);

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(2);

    glfwSwapBuffers(window);
    glfwPollEvents();

  }
Run Code Online (Sandbox Code Playgroud)

着色器:

layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 2) in vec3 vertexPosition_modelspace2;

uniform mat4 MVP;
uniform mat4 MVP2;

void main(){

gl_Position =  MVP * vec4(vertexPosition_modelspace,1);
gl_Position =  MVP2 * vec4(vertexPosition_modelspace2,1);
}
Run Code Online (Sandbox Code Playgroud)

我注意到只绘制了最后一个对象,所以问题是'gl_Position'会覆盖它的值,但是我应该怎么弄清楚呢?

der*_*ass 15

gl_Position =  MVP * vec4(vertexPosition_modelspace,1);
gl_Position =  MVP2 * vec4(vertexPosition_modelspace2,1);
Run Code Online (Sandbox Code Playgroud)

这不是图形管道的工作方式.您无法同时绘制两个对象.只是最后一次写入gl_Position将有效,并且您的第一个对象将被完全忽略.在最基本的变体中,您想要绘制两个完全独立的对象,并且您将需要两个绘制调用 - 就像在代码中一样.

但是,这样做时,您不需要两个不同的顶点属性.您的着色器只处理垂直,在您的情况下只有verexPosition_modelspace属性.因此,您可以将该属性用于要绘制的所有对象.如果属性意味着相同的事物,则为不同的对象使用不同的属性是没有意义的.

我们来看看您的绘图代码:

glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,(void*)0);
Run Code Online (Sandbox Code Playgroud)

在这里,您设置顶点attibute 0以指向第一个缓冲区的顶点数据,并启用atttribute数组.因此数据不会被用作源vertexPosition_modelspace.

glDrawArrays(GL_TRIANGLES, 0, 12*3);        
Run Code Online (Sandbox Code Playgroud)

现在你绘制对象.但正如我们已经看到的那样,你的着色器只是真正使用vertexPosition_modelspace2,你没有设置指针,或启用了数组.由于数组已去掉,GL将使用属性2的当前值 - 用于所有顶点.因此,对于三角形,您可以创建所有点都相同的三角形 - 获得表面积为0的三角形并且无论如何都是不可见的,无论当前具有什么实际值属性2.

glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer2);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,(void*)0);
Run Code Online (Sandbox Code Playgroud)

现在你做了一件奇怪的事情:启用属性2数组,但不要为它设置指针!您应该重新指定属性0的指针以指向您的第二个模型.

glDrawArrays(GL_TRIANGLES, 0, 4*3);
Run Code Online (Sandbox Code Playgroud)

现在绘制时启用了属性0和2.属性0将包含所需的数据,但着色器会忽略它.属性2只是指向某个地方,你会得到未定义的行为 - 它可能会崩溃,但它也可能显示奇怪的东西,或者根本没有.

要使其工作,只需vertexPosition_modelspace2从着色器中完全删除即可.MVP也只使用一个矩阵.绘制任何对象时,您必须:

  1. 设置MVP对象的统一矩阵
  2. 设置属性0的属性指针
  3. 为属性0启用属性数组(或确保它已启用)
  4. 发出平局调用

您可以根据需要使用尽可能多的对象.