OpenGL VBOs - Not rendering

Hello,

I am creating a project that I am using Vertex Buffer Objects in OpenGL to store vertices in my video card's memory. For some reason, however, the vertices are not rendering when I try to draw them.

I am using a nVidia GeForce GTX 660 graphics card with the latest drivers. I have already run tests to make sure that all of the VBO functions are supported with my graphics card.

The camera is pointed towards the origin, which is where the VBO is being drawn, and is set back 5 units in the z direction to ensure that the cube that I am drawing is visible on the screen.

I am using a cube for my vertices:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 'Location' is just three GLfloats (x, y, z)
Location cube[24] = {
		{  0.5, -0.5, 0.5  },
		{  0.5,  0.5, 0.5  },
		{ -0.5,  0.5, 0.5  },
		{ -0.5, -0.5, 0.5  },

		{  0.5, -0.5, -0.5 },
		{  0.5,  0.5, -0.5 },
		{  0.5,  0.5,  0.5 },
		{  0.5, -0.5,  0.5 },

		{  0.5, -0.5,  0.5 },
		{  0.5, -0.5, -0.5 },
		{  0.5, -0.5, -0.5 },
		{  0.5, -0.5, -0.5 },

		{ -0.5, -0.5,  0.5 },
		{ -0.5,  0.5,  0.5 },
		{ -0.5,  0.5, -0.5 },
		{ -0.5, -0.5, -0.5 },

		{  0.5,  0.5,  0.5 },
		{  0.5,  0.5, -0.5 },
		{ -0.5,  0.5, -0.5 },
		{ -0.5,  0.5,  0.5 },

		{  0.5, -0.5, -0.5 },
		{  0.5, -0.5,  0.5 },
		{ -0.5, -0.5,  0.5 },
		{ -0.5, -0.5, -0.5 },
};


To load my vertices into the graphics card memory, I use:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
	if (this->data != NULL) {
		glGenBuffers(1, &(this->vbo.id));
		glBindBuffer(GL_ARRAY_BUFFER, this->vbo.id);
		glBufferData(GL_ARRAY_BUFFER, this->vbo.id, NULL, GL_STATIC_DRAW);
		glBufferSubData(GL_ARRAY_BUFFER, (this->vbo.v_size), this->vbo.id,
				this->data);
                // indices data - will be NULL
		if (this->idata != NULL) {
			glGenBuffers(1, &(this->ivbo.id));
			glBindBuffer(GL_ARRAY_BUFFER, this->ivbo.id);
			glBufferData(GL_ARRAY_BUFFER, this->ivbo.id, NULL,
					GL_STATIC_DRAW);
			glBufferSubData(GL_ARRAY_BUFFER, (this->ivbo.v_size),
					this->ivbo.id, this->idata);
		}
	}


this->data is of type Vertex, which is defined as:

1
2
3
4
5
6
7
8
9
typedef struct {
        // these four things are structures containing a number of GLfloats
	Location l; // the vertex (x, y, z)
	TVertex t; // the texture coordinate (u, v)
	Location n; // the normal vertex (x, y, z)
	Color c; // the color (r, g, b, a)

	GLubyte padding[16]; // to improve performance by making the structure 64 bytes, can be used for extra data if needed
} Vertex;


And last, but not least, how I draw everything
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
        /*
        Much of this following is not going to be run, to make things easier to 
        read, what will be run is put here:

        glBindBuffer(GL_ARRAY_BUFFER, this->vbo.id);
        glEnableClientState(GL_VERTEX_ARRAY);
        glVertexPointer(3, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(0));
        
        glDrawArrays(this->type, 0, (this->vbo.v_size / sizeof(Location)));

        glDisableClientState(GL_VERTEX_ARRAY);
        */          

	if (this->data != NULL) {
		glBindBuffer(GL_ARRAY_BUFFER, this->vbo.id);

                // going to be false
		if (this->idata != NULL) {
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->ivbo.id);
		}

		glEnableClientState(GL_VERTEX_ARRAY);

                // going to be false
		if (this->color_texture_normal[0]) {
			glEnableClientState(GL_COLOR_ARRAY);
			glColorPointer(4, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(32));
		}

                // going to be false
		if (this->color_texture_normal[1]) {
			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
			glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(12));
		}

                // going to be false
		if (this->color_texture_normal[2]) {
			glEnableClientState(GL_NORMAL_ARRAY);
			glNormalPointer(GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(20));
		}

		glVertexPointer(3, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(0));

                // going to be false
		if (this->idata != NULL) {
			glDrawElements(this->type, (this->vbo.v_size / sizeof(Location)),
					GL_UNSIGNED_BYTE, BUFFER_OFFSET(0));
		} else {
                        // actually drawing it
			glDrawArrays(this->type, 0, (this->vbo.v_size / sizeof(Location)));
		}

                // going to be false
		if (this->color_texture_normal[0]) {
			glDisableClientState(GL_COLOR_ARRAY);
		}

                // going to be false
		if (this->color_texture_normal[1]) {
			glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		}

                // going to be false
		if (this->color_texture_normal[2]) {
			glDisableClientState(GL_NORMAL_ARRAY);
		}

		glDisableClientState(GL_VERTEX_ARRAY);
	}


Edit: More code added

This is the constructor of the class that handles everything. I have checked over this carefully to make sure that everything is as it should be, but I may have missed something. It is not uncommon for me to have small, careless mistakes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Model::Model(Location* _v, Index* _i, Location* _n, Color* _c, TVertex* _t,
		GLuint _size, GLuint _is, GLuint _type) {
	this->type = _type;

	this->data = new Vertex[_size];
	for (GLuint i = 0; i < _size; i++) {
		this->data[i].l = _v[i];
		if (_n != NULL) this->data[i].n = _n[i];
		else			this->data[i].n = {0.0f, 0.0f, 0.0f};
		if (_c != NULL) this->data[i].c = _c[i];
		else			this->data[i].c = {0.0f, 0.0f, 0.0f, 0.0f};
		if (_t != NULL) this->data[i].t = _t[i];
		else			this->data[i].t = {0.0f, 0.0f};
	}

	//this->idata = new Index[_is];
	this->idata = _i;

	this->vbo.id = 0;
	this->vbo.v_size = _size * sizeof(Location);
	this->vbo.t_size = _size * sizeof(TVertex);
	this->vbo.n_size = _size * sizeof(Location);
	this->vbo.c_size = _size * sizeof(Color);

	this->ivbo.id = 0;
	this->ivbo.v_size = _is;

	if (_c == NULL) {
		this->color_texture_normal[0] = false;
	} else {
		this->color_texture_normal[0] = true;
	}

	if (_t == NULL) {
		this->color_texture_normal[1] = false;
	} else {
		this->color_texture_normal[1] = true;
	}

	if (_n == NULL) {
		this->color_texture_normal[2] = false;
	} else {
		this->color_texture_normal[2] = true;
	}

	if (_n == NULL) {
		// TODO: Calculate normals
	}

	this->create_vbo();
}
Last edited on
I haven't checked very much of it, but I am questioning the call to glDrawArrays.
glDrawArrays(this->type, 0, (this->vbo.v_size / sizeof(Location)));

If location is a struct with 3 floats, then sizeof(Location) will be 12 (3 floats, 4 bytes each). Remember sizeof returns an amount memory in bytes.

What you are supposed to pass, is the number of vertices. If vbo.v_size, is the amount of Locations, which seams to be 24, then you are trying to draw a quad made of 2 points.

If vbo->v_size is actually the amount of memory, 24 * 3 * 4, then that should not be the problem.

Maybe if you post the code behind your vbo object I can look closer.
Last edited on
@htirwin

It is the size in memory. It is set in the constructor as:
this->vbo.v_size = _size * sizeof(Location);
where _size is the number of vertices.
1
2
3
		glBufferData(GL_ARRAY_BUFFER, this->vbo.id, NULL, GL_STATIC_DRAW);
		glBufferSubData(GL_ARRAY_BUFFER, (this->vbo.v_size), this->vbo.id,
				this->data);


I've never used glBufferSubData. But, in the documentation, it says that the second argument is supposed to be the offset where data replacement will begin, the third should be the size of the data you are replacing, and the last should be a pointer to the new data.

But it seams you are passing in the id as the size, and the size as the offset.

And the other thing is that glBufferData should take the size as the second argument, and a pointer to the data as the third. But you pass in the id as the size, and null as the pointer to the data.

Why don't you just do this and leave out glBufferSubData?

glBufferData(GL_ARRAY_BUFFER, (this->vbo.v_size), this->vbo.id, this->data);

But you have another problem, you're giving this->data, but you should be passing in a pointer to the array of points as in your Location cube[24], so you should pass in cube, or equivalent. As of now, you're passing in a pointer to an array of your Vextex objects which include more than just the points. You need to create separate buffers for the UV's and Normals.

You might want to rename your Vertex class, because it is a little confusing that you have included the color, and normal, and uv's, and vertecies (named locations), in one Vertex object.

It would be maybe better to have 3 separate vectors or arrays, one for the normals, one for the uv's, and one for the vertices.

Here is an example,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct Vertex {
    float x;
    float y;
    float z;
};

vector<Vertex> vertices;

for (GLuint i = 0; i < _size; i++) 
	vertices.push_back(v[i]);

glGenBuffers(1, &id));
glBindBuffer(GL_ARRAY_BUFFER, id);
glBufferData(GL_ARRAY_BUFFER,  sizeof(vertices) * sizeof(Vertex) , &vertices[0].x,  GL_STATIC_DRAW);
Last edited on
@htirwin

Thank you! I left out glBufferSubData, and it worked. As for the other problem, I'll have to look into that. Currently, it does not affect the rendering of the cube, but your method of handling the data may be more manageable.

Again, thank you for your help.
Topic archived. No new replies allowed.