Jump to content
  • Advertisement
Sign in to follow this  
tracer_bullet

OpenGL new to 3.2, VBO problems?

This topic is 3084 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok I recently came back to some OpenGL development, but my experience dates back to 1999 and I mostly used immediate mode stuff (glBegin, glEnd, etc). So I started reading into OpenGL 3.2 + GLSL 1.5 and my assumption is that everthing now is done with VBOs and Vertex/Geometry/Fragment shaders ... am I right? I succesfully initiated a "3.2.9704 Forward-Compatible Context" on Linux (Ubuntu 9.10) with a HD 4850. So far I got shaders loaded and executed allright, and I can draw a simple quad using a VBO and glDrawElements() with an indices array. Is this how all drawing is supposed to happen now? Now I met a problem in this early stage: I am using a second VBO with vertex color values (3 floats each) and the vertex shader inputs the color and transfers it to the fragment shader. The first 2 vertices are drawn with the correct color, but then color values don't match the supplied array. What am I doing wrong here? (vertex, fragment shader, relevant C++ code)
#version 150

in vec4 vertex;
in vec3 col;

out vec3 v_col;

void main(void) {
	v_col = col;
	gl_Position = vertex;
}

#version 150

in vec3 v_col;

out vec4 fragColor;

void main(void) {
	fragColor = vec4(v_col, 1.0);
}

void createBuffers(GLuint program) {
	// generate vertex data
	GLfloat data[] = {
			-1.0,  0.0, 0.0,
			 0.0,  1.0, 0.0,
			 1.0,  0.0, 0.0,
			 0.0, -1.0, 0.0
	};

	GLfloat color[] = {
			 1.0, 0.0, 0.0,
			 0.0, 1.0, 0,0,
			 0.0, 0.0, 1.0,
			 1.0, 1.0, 1.0
	};

	// VertexArrayObject is needed - ToDo: lookup what a VAO is
	GLuint vao;
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	// vertex data
	glGenBuffers(1, &buffer_data);
	glBindBuffer(GL_ARRAY_BUFFER, buffer_data);
	glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
	// map input attribute: vertex
	GLuint attr_vertex = glGetAttribLocation(program, "vertex");
	glVertexAttribPointer(attr_vertex, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(attr_vertex);

	// color data
	glGenBuffers(1, & buffer_color);
	glBindBuffer(GL_ARRAY_BUFFER, buffer_color);
	glBufferData(GL_ARRAY_BUFFER, sizeof(color), color, GL_STATIC_DRAW);
	// map input attribute: col
	GLuint attr_color = glGetAttribLocation(program, "col");
	glVertexAttribPointer(attr_color, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(attr_color);
}

void render() {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glBindBuffer(GL_ARRAY_BUFFER, buffer_data);
	glBindBuffer(GL_ARRAY_BUFFER, buffer_color);

	GLuint indices[] = {0, 1, 2, 2, 3, 0};
	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, indices);


	glutSwapBuffers();
	glFlush();
}

wrong output

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by tracer_bullet
Ok I recently came back to some OpenGL development, but my experience dates back to 1999 and I mostly used immediate mode stuff (glBegin, glEnd, etc).

So I started reading into OpenGL 3.2 + GLSL 1.5 and my assumption is that everthing now is done with VBOs and Vertex/Geometry/Fragment shaders ... am I right?

I succesfully initiated a "3.2.9704 Forward-Compatible Context" on Linux (Ubuntu 9.10) with a HD 4850.

So far I got shaders loaded and executed allright, and I can draw a simple quad using a VBO and glDrawElements() with an indices array.
Is this how all drawing is supposed to happen now?

Yeah, vertex arrays and shaders are the only way to go. It's either glDrawElements, or glDrawArrays if you don't have shared vertices or an index array.

Quote:
Original post by tracer_bullet
Now I met a problem in this early stage:
I am using a second VBO with vertex color values (3 floats each) and the vertex shader inputs the color and transfers it to the fragment shader.
The first 2 vertices are drawn with the correct color, but then color values don't match the supplied array.

What am I doing wrong here?

(vertex, fragment shader, relevant C++ code)

*** Source Snippet Removed ***

*** Source Snippet Removed ***

Pay very, very close attention to the B color component of the second vertex.

Share this post


Link to post
Share on other sites
omg ... this is most embarrissing, I thought I had checked all the values!

I posted this to the OpenGL discussion board and got no reply ... maybe they all couldn't type while laughin so hard ;)

ok, another question, i read that i could use GL_ELEMENT_ARRAY_BUFFER to store vertx indices instead of supplying the array each time I draw them.

ok, creating the VBO for the indices isn't that hard


// generate index array
GLint indices[] = {0, 1, 2, 2, 3, 0};
// indices for vertices
glGenBuffers(1, &buffer_indices);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer_indices);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices, GL_STATIC_DRAW);



but what draw call should I use?
glDrawElements requires the index array, what kindof defeats the purpose of uploading them to the GPU with a VBO.

and glDrawArrays doesn't need an index array (that is why I assume this is the correct call). and glDrawArrays(GL_TRIANGLES, 0, 3) draws the first triangle all right, but using glDrawArrays(GL_TRIANGLES, 0, 6) messes things up: left half of the screen shows the half first triangle, the right half of the screen is completely filled with pink

so what is the correct usage?

Share this post


Link to post
Share on other sites
glDrawElements, same as glVertexAttribPointer, assumes pointer is offset from start of the buffer when buffer is bound. So pass 0 to indices argument to use your ELEMENTS_ARRAY_BUFFER from the beginning.

Share this post


Link to post
Share on other sites
Quote:
Original post by tracer_bullet
ok, another question, i read that i could use GL_ELEMENT_ARRAY_BUFFER to store vertx indices instead of supplying the array each time I draw them.

ok, creating the VBO for the indices isn't that hard

*** Source Snippet Removed ***

but what draw call should I use?
glDrawElements requires the index array, what kindof defeats the purpose of uploading them to the GPU with a VBO.

It works the same as glVertexAttribArray. The pointer parameter is; a pointer to the array in system memory if an array buffer is currently not bound; an offset, in bytes, into the currently bound array buffer. Similarly, if an element array buffer is bound, the pointer parameter in glDrawElements is the offset within the bound element array buffer.

Quote:
Original post by tracer_bullet
and glDrawArrays doesn't need an index array (that is why I assume this is the correct call). and glDrawArrays(GL_TRIANGLES, 0, 3) draws the first triangle all right, but using glDrawArrays(GL_TRIANGLES, 0, 6) messes things up: left half of the screen shows the half first triangle, the right half of the screen is completely filled with pink

If you want to use glDrawArrays, you must also rearrange your vertex array so it works without an index array. Your current vertex array requires an index array to produce two triangles from the four vertices. glDrawArrays is effectively a special case of glDrawElements where the index array contains increasing indices only.

Quote:
Original post by tracer_bullet
so what is the correct usage?

In your last code where you load the element array buffer, all you need to do is call glDrawElements with a pointer of 0. Since you have an element array buffer bound, the parameter specifies the offset into the bound element array buffer to read indices from.

Share this post


Link to post
Share on other sites
Quote:
Original post by tracer_bullet
ah ok, I misinterpreted the * indices as pointer to the actual index array, not some offset array.
this makes sense, great!



That's correct IF no buffer is bound to GL_ELEMENT_ARRAY_BUFFER, but if a buffer is bound, then the pointer value is interpreted as an offset into the buffer.

Share this post


Link to post
Share on other sites
yes i got that already, thanks ;)
oh and while we are at it:

the VAO ... are the VBOs bound to it or just the attribPointer?

so if i unbind the VAO and later rebind it, do i have to bind the VBOs too or not?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!