glDrawElements 使用了错误的 VBO?
glDrawElements using the wrong 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();
}
您误解了顶点数组指针(和 VAO)的工作原理。 glDraw*()
命令 从不 关心当前的 GL_ARRAY_BUFFER
绑定。该绑定在 glVertexAtrrib*Pointer()
调用时 是相关的 - 对当前绑定 GL_ARRARY_BUFFER
的引用成为 的一部分 属性指针。这也意味着您可以将每个属性设置为从不同的缓冲区中获取。
因此,您的代码将仅使用 cube
对象的 VBO,因为这是在您设置顶点属性指针时绑定的对象。
当你想绘制不同的对象时,你必须切换
顶点属性指针,所以它看起来像这样:
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(...);
(假设您对所有对象使用相同的属性。如果不是这种情况,您可能还必须 enable/disable 此函数中的属性数组)。
这就是 VAO 发挥作用的地方。 VAO 是容器对象,存储每个属性的完整顶点数组指针状态(包括缓冲区绑定和 enable/disable 状态),以及 GL_ELEMENT_ARRAY
缓冲区绑定。从概念上讲,您可以为每个对象创建一个 VAO,并将顶点指针设置移动到您的 init()
函数,将绘制代码减少到
drawObject() {
glBindVertexArray(vao);
glDrawElements(...);
所以从概念上讲,它看起来像这样:
我正在尝试在屏幕上渲染两个不同的对象。据我所知,问题是 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();
}
您误解了顶点数组指针(和 VAO)的工作原理。 glDraw*()
命令 从不 关心当前的 GL_ARRAY_BUFFER
绑定。该绑定在 glVertexAtrrib*Pointer()
调用时 是相关的 - 对当前绑定 GL_ARRARY_BUFFER
的引用成为 的一部分 属性指针。这也意味着您可以将每个属性设置为从不同的缓冲区中获取。
因此,您的代码将仅使用 cube
对象的 VBO,因为这是在您设置顶点属性指针时绑定的对象。
当你想绘制不同的对象时,你必须切换 顶点属性指针,所以它看起来像这样:
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(...);
(假设您对所有对象使用相同的属性。如果不是这种情况,您可能还必须 enable/disable 此函数中的属性数组)。
这就是 VAO 发挥作用的地方。 VAO 是容器对象,存储每个属性的完整顶点数组指针状态(包括缓冲区绑定和 enable/disable 状态),以及 GL_ELEMENT_ARRAY
缓冲区绑定。从概念上讲,您可以为每个对象创建一个 VAO,并将顶点指针设置移动到您的 init()
函数,将绘制代码减少到
drawObject() {
glBindVertexArray(vao);
glDrawElements(...);
所以从概念上讲,它看起来像这样: