【问题标题】:Multiple objects drawing (OpenGL)多对象绘图 (OpenGL)
【发布时间】:2014-06-20 21:44:22
【问题描述】:

问题是我不知道如何正确绘制两个对象,因为我的另一个对象没有被绘制。

主要代码如下:

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' 覆盖了它的值,但我应该如何弄清楚呢?

【问题讨论】:

标签: c++ opengl console-application


【解决方案1】:
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);

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

glDrawArrays(GL_TRIANGLES, 0, 12*3);        

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

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. 发出绘图调用

您可以对任意数量的对象执行此操作。

【讨论】:

  • glEnableVertexAttribArray(2); glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer2); glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,(void*)0);哦,这是一个错字,对不起,我本来是 glVertexAttribPointer(2,3,GL_FLOAT,GL_FALSE,0,(void*)0);在我的实际代码中但是如何仅使用一个 MVP 矩阵独立地转换对象?
  • @RevanReborn:在绘制对象之前更改/更新矩阵(参见我的步骤 1)。
  • 是的!现在可以了!所以我只是删除了所有不必要的“2”,并以正确的顺序inside重新组织了MVP转换。非常感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2016-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-04
  • 1970-01-01
相关资源
最近更新 更多