多个对象绘图(OpenGL)

时间:2014-05-04 15:38:39

标签: 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();

  }

着色器:

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

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

1 个答案:

答案 0 :(得分:14)

gl_Position =  MVP * vec4(vertexPosition_modelspace,1);
gl_Position =  MVP2 * vec4(vertexPosition_modelspace2,1);

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

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

让我们看一下您的绘图代码:

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

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

glDrawArrays(GL_TRIANGLES, 0, 12*3);        

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

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

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

glDrawArrays(GL_TRIANGLES, 0, 4*3);

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

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

  1. 设置对象的MVP统一矩阵
  2. 设置属性0的属性指针
  3. 为属性0启用属性数组(或确保它已启用)
  4. 发出绘制调用
  5. 您可以根据需要使用尽可能多的对象。