glDrawElements使用了错误的VBO? [英] glDrawElements using the wrong VBO?

查看:81
本文介绍了glDrawElements使用了错误的VBO?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在屏幕上渲染两个不同的对象.据我所知,问题是OpenGL使用了错误的Vertex Buffer,但使用了正确的Index Buffer,但是我不太确定自己目前正在做什么,因为我已经开始重新学习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();
}

解决方案

您误解了顶点数组指针(和VAO)的工作方式. glDraw*()命令从不关心当前的GL_ARRAY_BUFFER绑定.在glVertexAtrrib*Pointer()调用时,该绑定是相关的-对当前绑定的GL_ARRARY_BUFFER的引用成为属性指针的 part .这也意味着您可以将每个属性设置为从不同的缓冲区中获取.

因此,您的代码将仅使用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(...);

因此,从概念上讲,它看起来像这样:

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

解决方案

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:

这篇关于glDrawElements使用了错误的VBO?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆