I’m starting from the Apple-spupplied iOS OpenGL game template in Xcode and I have an array of structs (more of an array of structs of structs, if you will) that I’m trying to use with an OpenGL VBO. However, while I get no errors, nothing is drawn to the screen.
First I create and populate this array which is of type VecAttributeType, a struct which in turn has 3 other structs: vPosition, vTCoordinates and vNormal.
Then I try copying the array to a VBO and binding the positions and normals (meaning VecAttributeType.vPosition and VecAttributeType.vNormal in terms of offsets) via glVertexAttribPointer to the appropriate in / attributes in the vertex shader.
Then I try rendering.
And nothing is drawn :/
Mind you, the arrayOfStructs contains ALL vertices needed to draw the model. That is, I’m not using indices to vertices. Rather, for this test, I’m going through the face definitions in the obj and for each index, retrieving the appropriate vertex,texture,normal and copying it in the arraOfStructures.
So for instance, for a classic cube in obj format, the file lists 8 vertices but my final arrayOfStructs has length 12 and there’s 12 VecAttributeType structs in it, each with the right position, texture coord and normal for that vertex, derived from the indices in the obj file’s face definition. And yes, I’m offsetting the indices in the f definitions by -1 to account for the fact that obj files index starting at 1.
My guess is that I’m simply calculating the offset into the VBO for the positions and normals wrong. I think so because I’ve tried printing the first position x coordinate in the first VecAttributeType in the arrayOfStructures like so:
NSLog(@"\nTEST:\nfirst vertex X = %f", arrayOfStructs[0].vPosition.x);
and I get the expected value, while trying to print like so:
char* address = (char*)arrayOfStructs+offsetof(VecAttributeType, vPosition.x);
float b = *address;
NSLog(@"\nTEST:\nfirst vertex X = %f", b);
prints 0 instead (the right value should be 1);
Here are the relevant sections of code:
//Inside a c++ class I'm parsing an Obj and creating the vertex attribute array:
typedef struct
{
float x;
float y;
float z;
} Vec3fType;
typedef struct
{
float s;
float t;
} Vec2fType;
typedef struct
{
int p;
int n;
int t;
} Vec3iType;
typedef struct
{
Vec3fType vPosition;
Vec3fType vNormal;
Vec2fType vTCoordinates;
} VecAttributeType;
int arrayLength = // Some number;
VecAttributeType* arrayOfStructs = new VecAttributeType[arrayLength];
// Populate the array.
// . . .
// Then, in the ViewController (Objective-C) class, I try binding to the VBO and getting the offsets right:
[EAGLContext setCurrentContext:self.context];
[self loadShaders];
glEnable(GL_DEPTH_TEST);
GLuint _vertexBuffer;
glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(VecAttributeType)*arrayLength, arrayOfStructs, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(VecAttributeType), BUFFER_OFFSET(0) + offsetof(VecAttributeType, vPosition) + offsetof(Vec3fType, x));
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, sizeof(VecAttributeType), BUFFER_OFFSET(0) + offsetof(VecAttributeType, vNormal) + offsetof(Vec3fType, x));
And finally, the drawing code is:
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
glClearColor(1.f, 0.f, 0.f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArrayOES(_vertexArray);
// Render the object again with ES2
glUseProgram(_program);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);
glDrawArrays(GL_TRIANGLES, 0, arrayLength);
}
Any ideas?
Ok I got it…
Turns out at some point I forgot I was using the VAO extension (
glBindVertexArrayOES) and after disabling it at the end of the VBO setup, I was forgetting to enable it inglkView:draInRect:My code above shows it enabled, but only cause I created a new project to copy the relevant sections of code to before posting on SO.
Also, the
glVertexAttribPointerlines can be rewritten a bit more compactly like this: