glDrawElements использует неправильный VBO?

Я пытаюсь сделать два разных объекта на экране. Насколько я могу судить, проблема в том, что OpenGL использует неверный буфер вершин, но правильный индексный буфер, но я не слишком уверен в том, что я сейчас делаю, потому что я в значительной степени начал изучать OpenGL снова.

Это то, что в настоящее время отображается: http://puu.sh/ekhd7/cca60981ab.jpg

Если это плохая идея иметь классы для объектов или как это должно быть сделано, пожалуйста, скажите мне - я ничего не делаю.

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

1 ответ

Решение

Вы неправильно поняли, как работают Vertex Array Pointers (и VAO). glDraw*() команды никогда не заботятся о текущем GL_ARRAY_BUFFER связывание. Эта привязка актуальна во время glVertexAtrrib*Pointer() звонки - ссылка на текущую привязку GL_ARRARY_BUFFER становится частью указателя атрибута. Это также означает, что вы можете настроить каждый атрибут для выборки из другого буфера.

Следовательно, ваш код будет использовать только VBO из cube объект, так как это тот, который связан в то время, когда вы устанавливаете указатели атрибутов вершин.

Когда вы хотите нарисовать разные объекты, вам нужно переключить указатели атрибутов вершин, чтобы они выглядели так:

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

(Это предполагает, что вы используете одни и те же атрибуты для всех объектов. Если это не так, возможно, вам также придется включить / отключить массивы атрибутов в этой функции).

Здесь ВАО входят в картину. VAO - это объекты-контейнеры, создающие полные состояния указателя массива вершин для каждого атрибута (включая привязку буфера и состояние включения / выключения), и GL_ELEMENT_ARRAY привязка буфера. Концептуально, вы можете создать VAO для каждого объекта и переместить настройку указателя вершины на yout. init() функция, уменьшающая код отрисовки до

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

Так что концептуально это выглядит так:

Другие вопросы по тегам