Domanda

The issue is that I can't figure out how to properly draw two objects, because my another object isn't being drawn.

Here's the main code:

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

  }

And shader:

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

I have noticed that only last object is being drawn, so the issue is that 'gl_Position' overwrites it's values, but how should I figure it out?

È stato utile?

Soluzione

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

That is not how the graphics pipeline work. You can not draw two objects at the same time. Just the last write to gl_Position will be effective, and your first object will be completely ignored. In the most basic variant, you want to draw two completely independent objects, and you will need two draw calls for that - as you do in your code.

However, when doing so, you do not need two different vertex attributes. Your shader just processes vertices, which in your case only have the verexPosition_modelspace attribute. So you can use that attribute for all the objects you want to draw. There is no point in using different attributes for different objects if the attribute means the same thing.

Let's have a look at your drawing code:

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

Here, you set up vertex attribute 0 to point to the vertex data of the first buffer, and you enable the attribute array. So the data will not be used as source for vertexPosition_modelspace.

glDrawArrays(GL_TRIANGLES, 0, 12*3);        

Now you draw the object. But as we already have seen, your shader does only really use vertexPosition_modelspace2, for which you did not have set an pointer, or enabled the array. Since the array is disabled, the GL will use the current value of attribute 2 - for all vertices. So in the case of triangles, you create triangles with all points being the same - getting triangles with a surface area of 0 and are invisible anyways, no matter what actual value attribute 2 currently has.

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

Now you do a strange thing: you enable attribute 2 array, but do not set a pointer for it! You should re-specify the pointer for attribute 0 to point to your second model.

glDrawArrays(GL_TRIANGLES, 0, 4*3);

Now you draw with both attribute 0 and 2 enabled. Attribute 0 will contain the data you want, but is ignored by the shader. Attribute 2 is just point somewhere, and you get undefined behavior - it might just crash, but It might also display strange stuff, or nothing at all.

To make this work, just remove vertexPosition_modelspace2 completely from the shader. Use just one MVP matrix also. When drawing any object, you have to:

  1. Set the MVP uniform matrix for the object
  2. Set the attribute pointer for attribute 0
  3. Enable the attribute array for attribute 0 (or make sure it is already enabled)
  4. Issue the draw call

You can do this with as many objects as you want.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top