glDrawElements使用错误的VBO?

时间:2015-01-10 14:17:01

标签: c++ opengl

我试图在屏幕上渲染两个不同的对象。我可以告诉的问题是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 个答案:

答案 0 :(得分:9)

您误解了顶点阵列指针(和VAO)的工作原理。 glDraw*()命令从不关心当前的GL_ARRAY_BUFFER绑定。该绑定在glVertexAtrrib*Pointer()调用时与相关 - 对当前绑定的GL_ARRARY_BUFFER的引用变为属性指针的部分。这也意味着您可以设置要从不同缓冲区中提取的每个属性。

因此,您的代码将仅使用cube对象的VBO,因为这是在设置顶点属性指针时绑定的对象。

当您想要绘制不同的对象时,您必须切换 顶点attrib指针,所以它看起来像这样:

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

(假设您对所有对象使用相同的attrib。如果不是这种情况,您可能还必须在此函数中启用/禁用attrib数组。)

这是VAO进入图片的地方。 VAO是容器对象,用于描述每个属性的完整顶点数组指针状态(包括缓冲区绑定和启用/禁用状态),以及GL_ELEMENT_ARRAY缓冲区绑定。从概念上讲,您可以为每个对象创建一个VAO,并将顶点指针设置移动到yout init()函数,将绘制代码减少到

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

从概念上讲,它看起来像这样: enter image description here