Reputation: 615
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
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