GRW
GRW

Reputation: 615

OpenGL ES 2.0 rendering with glDrawElements only displays a single VBO

See edit below which significantly changes the question.

ORIGINAL:

I'm having a problem rendering elements using OpenGL ES 2.0 on iOS 4 using Xcode 4.1.

Things display just fine without any issues using glDrawElements:

glDrawElements(GL_TRIANGLES, indicesSizeAll/sizeof(IndicesAll[0]), GL_UNSIGNED_SHORT, 0);

but if I use an equivalent glDrawRangeElements I get various problems:

glDrawRangeElements(GL_TRIANGLES, 0, (indicesSizeAll/sizeof(IndicesAll[0]))-1, indicesSizeAll/sizeof(IndicesAll[0]), GL_UNSIGNED_SHORT, 0);

I get the following build warning:

Semantic Issue: Implicit declaration of function 'glDrawRangeElements' is invalid in C99

and the following error during execution:

Program received signal: "EXC_BAD_ACCESS"

I included this function prototype:

extern void glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid * indices);

which got rid of the build warning but I still have the execution error.

Not really sure what to do about solving this problem. I'm taking things one step at a time and got things to display, but moving forward I believe I'm going to need to use glDrawRangeElements so I'm trying to get that working. Anyone have some guidance for me?

EDIT:

Its been brought to my attention that:

DrawRangeElements doesn't exist in OpenGL ES 1.1 or 2.0, which is why it isn't in the system headers. You should call glDrawElements instead.

That puts me back in the situation I was before when I thought glDrawRangeElements would solve my problems.

That means I need to use multiple buffers to render everything since I want to apply a different rotation to each buffer.

[modelView rotateBy:CC3VectorMake(x, y, z)];
glUniformMatrix4fv(_modelViewUniform, 1, 0, modelView.glMatrix);

I set up two different buffers:

glGenBuffers(1, &vertexBufferA);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferA);
glBufferData(GL_ARRAY_BUFFER, verticesSizeA, VerticesA, GL_STATIC_DRAW);

glGenBuffers(1, &indexBufferA);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferA);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesSizeA, IndicesA, GL_STATIC_DRAW);
--------------------
glGenBuffers(1, &vertexBufferZ);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferZ);
glBufferData(GL_ARRAY_BUFFER, verticesSizeZ, VerticesZ, GL_STATIC_DRAW);

glGenBuffers(1, &indexBufferZ);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferZ);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesSizeZ, IndicesZ, GL_STATIC_DRAW);

Then when I want to render those elements:

glBindBuffer(GL_ARRAY_BUFFER, vertexBufferA);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferA);

glDrawElements(GL_TRIANGLES, indicesSizeA/sizeof(IndicesA[0]), GL_UNSIGNED_SHORT, 0);
--------------------
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferZ);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferZ);

glDrawElements(GL_TRIANGLES, indicesSizeZ/sizeof(IndicesZ[0]), GL_UNSIGNED_SHORT, 0);

A single call to glDrawElements will render just fine, but if I call it for each buffer only the second call does any rendering.

Not exactly sure what I am missing here. I'm new to the whole OpenGL thing and learning as I go.

Appreciate any pointers or clarification.

Upvotes: 1

Views: 2646

Answers (1)

GRW
GRW

Reputation: 615

I've figured out the answer to my own question. As it turns out, I can save all of my data in a single buffer and specify the desired range for each render.


Set up vertex and index buffers: single set of buffers to contain data for two graphics (A and Z)

glGenBuffers(1, &vertexBufferAll);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferAll);
glBufferData(GL_ARRAY_BUFFER, verticesSizeAll, VerticesAll, GL_STATIC_DRAW);

glGenBuffers(1, &indexBufferAll);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferAll);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesSizeAll, IndicesAll, GL_STATIC_DRAW);

Define offsets for data in the vertex array:

glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 0));
glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 3));

Draw elements located at specified offset in the index array:

glDrawElements(GL_TRIANGLES, indicesCountA, GL_UNSIGNED_SHORT, (GLvoid*) (sizeof(GLushort) * 0));
glDrawElements(GL_TRIANGLES, indicesCountZ, GL_UNSIGNED_SHORT, (GLvoid*) (sizeof(GLushort) * indicesCountA));

Apply the appropriate matrix before each glDrawElements to achieve the desired rotation:

glUniformMatrix4fv(_modelViewUniform, 1, 0, modelView.glMatrix);

Now that I have things working, it sure seems pretty simple and kind of obvious, but I had to go through a lot of variations until I stumbled upon the proper setup. Feels like with OpenGL, if things aren't 100% correct they are incorrect.

Upvotes: 1

Related Questions