Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

glDrawElements using the wrong VBO?

Tags:

c++

opengl

I'm trying to render two different objects on screen. The problem I as far as I can tell is OpenGL is using the wrong Vertex Buffer but the correct Index Buffer, but I'm not too sure about anything I'm currently doing as I've pretty much started learning OpenGL again.

This is what currently gets displayed: http://puu.sh/ekhd7/cca60981ab.jpg

If its a bad idea having classes for objects, or how it should be done, please tell me - I'm going off nothing.

struct point4{
vec4 vertex;
vec4 color;
};


class Pyramid
{
public:
//Variables and Contructor here 
void init(){
    glGenBuffers( 1, &Arraybufferx );
    glBindBuffer( GL_ARRAY_BUFFER, Arraybufferx );
    glBufferData( GL_ARRAY_BUFFER, sizeof(point4)*16, NULL, GL_STATIC_DRAW );
    glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(left), left );
    glBufferSubData( GL_ARRAY_BUFFER, sizeof(left)  , sizeof(right), right );               
    glBufferSubData( GL_ARRAY_BUFFER, sizeof(left)*2, sizeof(back), back );
    glBufferSubData( GL_ARRAY_BUFFER, sizeof(left)*3, sizeof(front), front );
    glBufferSubData( GL_ARRAY_BUFFER, sizeof(left)*4, sizeof(bottom), bottom );

    glGenBuffers( 1, &IndexBuffer );
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, IndexBuffer );
    glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(gIndices), gIndices, GL_STATIC_DRAW );
}

void display(GLint tr,GLint theta, GLfloat rt1[], GLfloat Theta1[]){

    glBindBuffer( GL_ARRAY_BUFFER, Arraybufferx );      
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, IndexBuffer );

    glUniform3fv( tr, 1,  rt1 );
    glUniform3fv( theta, 1, Theta1 );   

    glDrawElements( GL_TRIANGLES, sizeof(gIndices), GL_UNSIGNED_INT, 0 );

    glBindBuffer( GL_ARRAY_BUFFER, 0 );     
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
}
};

class cube{
 public:
//Variables and Contructor here     
void init(){
    glGenBuffers( 1, &Arraybuffer );
    glBindBuffer( GL_ARRAY_BUFFER, Arraybuffer );
    glBufferData( GL_ARRAY_BUFFER, sizeof(left)*6, NULL, GL_STATIC_DRAW );
    glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(left), left );
    glBufferSubData( GL_ARRAY_BUFFER, sizeof(point4)*4, sizeof(right), right );
    glBufferSubData( GL_ARRAY_BUFFER, sizeof(point4)*8, sizeof(top), top );
    glBufferSubData( GL_ARRAY_BUFFER, sizeof(point4)*12, sizeof(bottom), bottom );
    glBufferSubData( GL_ARRAY_BUFFER, sizeof(point4)*16, sizeof(back), back );
    glBufferSubData( GL_ARRAY_BUFFER, sizeof(point4)*20, sizeof(front), front );    

    glGenBuffers( 1, &IndexBuffer );
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, IndexBuffer );
    glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(gIndices), gIndices, GL_STATIC_DRAW );
}

void display(GLint tr,GLint theta, GLfloat rt1[], GLfloat Theta1[]){

    glBindBuffer( GL_ARRAY_BUFFER, Arraybuffer );       
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, IndexBuffer );

    glUniform3fv( tr, 1,  rt1 );
    glUniform3fv( theta, 1, Theta1 );       

    glDrawElements( GL_TRIANGLES, sizeof(gIndices), GL_UNSIGNED_INT, 0 );   
    glBindBuffer( GL_ARRAY_BUFFER, 0 );     
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
}
};

void init()
{
  // Create a vertex array object
  GLuint vao;
  glGenVertexArrays( 1, &vao );
  glBindVertexArray( vao );

  pyramid.init();
  Cube.init();  

  GLuint program = InitShader( "vshader36.glsl", "fshader36.glsl" );
  glUseProgram( program );

  GLuint vPosition = glGetAttribLocation( program, "vPosition" );
  glEnableVertexAttribArray( vPosition );    

  GLuint vColor = glGetAttribLocation( program, "vColor" ); 
  glEnableVertexAttribArray( vColor );    

  model_view = glGetUniformLocation(program, "model_view");
  GLuint projection = glGetUniformLocation(program, "projection");

  glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, sizeof(point4), 0 );  

  glVertexAttribPointer(vColor,4,GL_FLOAT,GL_FALSE,sizeof(point4),(void*)sizeof(vec4));

  // Create and send the model view matrix
  mat4 mv = LookAt(eye, at, up);
  glUniformMatrix4fv(model_view, 1, GL_TRUE, mv);

  theta = glGetUniformLocation( program, "theta" );

  tr = glGetUniformLocation( program, "tr" );   

  glEnableClientState (GL_VERTEX_ARRAY);    
  mat4 p = Frustum(-1.0, 1.0, -1.0, 1.0, 10.0, -20.0);
  glUniformMatrix4fv(projection, 1, GL_TRUE, p);

  glEnable( GL_DEPTH_TEST );
  glClearColor( 1.0, 1.0, 1.0, 1.0 );    
}
//----------------------------------------------------------------------------
void display( void )
{
    mat4 mv = LookAt(eye, at, up);
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    glUniformMatrix4fv(model_view, 1, GL_TRUE, mv);

    Cube.display(tr,theta,Translate1,Theta);
    pyramid.display(tr,theta,Translate2,Theta);

    glutSwapBuffers();
}
like image 480
yuh25 Avatar asked Dec 26 '22 00:12

yuh25


1 Answers

You misunderstood how Vertex Array Pointers (and VAOs) work. glDraw*() commands never care about the current GL_ARRAY_BUFFER binding. That binding is relevant at the time of the glVertexAtrrib*Pointer() calls - a reference to the currently bound GL_ARRARY_BUFFER becomes part of the attribute pointer. This also means that you can set up each attribute to be fetched from a different buffer.

Consequently, your code will only use the VBO of the cube object, as this is the one that is bound at the time you set vertex attrib pointers.

When you want to draw your different objects, you have to switch the vertex attrib pointers, so it will look like this:

drawObject() {
    glBindBuffer(GL_ARRAY_BUFFER,vbo_for_attr0);
    glVertexAttribPointer(0,...);
    glBindBuffer(GL_ARRAY_BUFFER,vbo_for_attr1);
    glVertexAttribPointer(1,...);
    [...]
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
    glDrawElements(...);

(This is assuming you are using the same attribs for all objects. If this is not the case, you may also have to enable/disable the attrib arrays in this function).

This is where VAOs enter the picture. VAOs are container objects stroing the complete vertex array pointer states for each attribute (including the buffer binding and enable/disable state), and the GL_ELEMENT_ARRAY buffer binding. Conceptually, you can create a VAO per object, and move the vertex pointer setup to yout init() function, reducing the draw code to

drawObject() {
    glBindVertexArray(vao);
    glDrawElements(...);

So conceptually, it looks like this: enter image description here

like image 170
derhass Avatar answered Feb 10 '23 06:02

derhass