I am building an iOS game with OpenGL ES 2.0 that contains a scene with around 100 different 'objects' which I need to be able to transform independently of one another. I am new to OpenGL ES. As such, I initially thought I should start with OpenGL ES 1.1, then later migrate the app to 2.0 to take advantage of the enhanced visual effects.
However, just as I was getting comfortable with 1.1, I realized, partly based on Apple's very 2.0-centric Xcode template for OpenGL, that it was going to be more trouble than it's worth to fight moving straight into 2.0, so I bit the bullet.
Now, I'm finding it difficult to grasp the concepts enough to do simple transforms on my vertex array objects independently of one another. I read in the OpenGLES 2.0 docs that the best way to do this would be to use multiple VBOs, one for each vertex array. However, I can't seem to transform one of them without affecting the entire scene.
I started the project with the Apple OpenGL ES template and streamlined it, such that the setupGL method looks like this:
-(void)setupGL
{
// Setup
[EAGLContext setCurrentContext:self.context];
[self loadShaders];
self.effect = [[GLKBaseEffect alloc] init];
self.effect.light0.enabled = GL_TRUE;
self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f);
glEnable(GL_DEPTH_TEST); // do depth comparisons and update the depth buffer
// Initialize first buffer
glGenVertexArraysOES(1, &_vertexArray);
glBindVertexArrayOES(_vertexArray);
glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(gPyramidVertexData), gPyramidVertexData, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));
glBindVertexArrayOES(0);
// Initialize second buffer
glGenVertexArraysOES(2, &_vertexArray2);
glBindVertexArrayOES(_vertexArray2);
glGenBuffers(2, &_vertexBuffer2);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer2);
glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));
glBindVertexArrayOES(0);
}
I know that's incredibly sloppy code- I basically copy-and-pasted the buffer creation portion to set myself up for experimenting with two different vertextArrays in separate buffers. It appears to have worked, as I can render both buffers in the drawInRect method:
-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
glBindVertexArrayOES(_vertexArray);
glUseProgram(_program);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);
glDrawArrays(GL_TRIANGLES, 0, numberOfVerteces);
glBindVertexArrayOES(_vertexArray2);
glUseProgram(_program);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);
glDrawArrays(GL_TRIANGLES, 0, numberOfVerteces2);
}
My problem comes when I try to do transforms on one vertex array without affecting the other one. I tried adding transforms in the above method just before the glDrawArrays calls, without success- I think that may only work with 1.1. It appears my transforms must be done within the update method:
-(void)update
{
float aspect = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f);
self.effect.transform.projectionMatrix = projectionMatrix;
GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation( 0.0f, 0.0f, -4.0f);
baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _sceneRotation, 1.0f, 1.0f, 1.0f);
GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, zoomFactor);
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _objectRotation, 0.0f, 1.0f, 0.0f);
modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix);
_normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL);
_modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix);
}
However, this is where I get really confused-- it's not at all clear how I could modify this method to do transforms to one VBO or the other. It's not even clear that th above code is making any reference to one particular buffer at all.
Eventually I would like to expand my game by moving the code for each game object into an instance of a custom class, which would handle the transforms, etc. But I would like to know if I'm completely misguided in my approach before doing so.
In case this is helpful to anyone having similar issues, I found the answers I was looking for on Ian Terrell's excellent blog, Games by Ian Terrell.
In particular, this tutorial and its accompanying sample code were exactly what I needed to get a grip on this very complicated subject. Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With