I am trying to learn OpenGL ES 2.0 to do some iPhone game development. I have read through multiple tutorials and some of the OpenGL ES 2.0 spec. All of the examples I have seen have created a single mesh, loaded it into a vertex buffer and then rendered it (with the expected translation, rotation, gradient, etc.)
My question is this: how do you render multiple objects in your scene that have different meshes and are moving independently? If I have a car and a motorcycle for example, can I create 2 vertex buffers and keep the mesh data for both around for each render call, and then just send in different matrices for the shader for each object? Or do I need to somehow translate the meshes and then combine them into a single mesh so that they can be rendered in one pass? I'm looking for more of the high-level strategy / program structure rather than code examples. I think I just have the wrong mental modal of how this works.
Thanks!
I realize this is an older post, but I was trying to find instructions on how to render multiple objects within
OpenGL
. I found a great tutorial, which describes how to render multiple objects and could be easily extended to render objects of different types (i.e. one cube, one pyramid).The tutorial I'm posting also describes how to render objects using
GLKit
. I found it helpful and thought I'd repost it here. I hope it helps you too!http://games.ianterrell.com/opengl-basics-with-glkit-in-ios5-encapsulated-drawing-and-animation/
If the meshes are different, you keep them in different vertex buffers. If they are similar (eg. animation, color) you pass arguments to the shader. You only have to keep the handles to the VBOs, not the vertex data itself if you don't plan on animating the object on the application side. Device side animation is possible.
The best way I found to do this is using VAOs in addition to VBOs.
I'll first answer you question using VBOs only.
First of all, assume you have the two meshes of your two objects stored in the following arrays:
where:
And you also have to vertix buffers:
Now, to draw those two cubes (without VAOs), you have to do something like that: in draw function (from OpenGLES template):
This will answer you question. But now to use VAOs, your draw function code is much simpler (which is good because it is the repeated function):
First you will define to VAOs:
and then you will do all the steps previously done in draw method, you will do it in setupGL function but after binding to the VAO. Then in your draw function you just bind to the VAO you want.
VAO here is like a profile that contains a lot of properties (imagine a smart device profile). Instead of changing color, desktop, fonts.. etc every time you wish to change them, you do that once and save it under a profile name. Then you just switch the profile.
So you do that once, inside setupGL, then you switch between them in draw.
Of course you may say that you could have put the code (without VAO) in a function and call it. That's true, but VAOs are more efficient according to Apple:
http://developer.apple.com/library/ios/#documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/TechniquesforWorkingwithVertexData/TechniquesforWorkingwithVertexData.html#//apple_ref/doc/uid/TP40008793-CH107-SW1
Now to the code:
In setupGL:
Then finally in your draw method:
It is possible when using shaders, to use the same program for all objects without having to compile, link and create one for each. To do this, simply store the GLuint value to the program and then for each object "glUseProgram(programId);". As a result personal experience, i use a singleton to manage GLProgram structures.. (included below :))
Note that once data-spaces (attributes/uniforms) are passed in, you DONT have to pass them in each render cycle but only when invalidated. This results a serious GPU performance gain.
Per the VBO side of things, the answer above spells out how best to deal with this. Per the orientation side of the equation, you'll need a mechanism to nest tdobjects inside each other (similar to UIView and children under iOS) and then evaluation relative rotations to parents etc.
Good luck !
I am hopefully-contributing to this older post, because I undertook to solve this problem a different way. Like the question asker, I have seen lots of "one-object" examples. I undertook to place all vertices into a single VBO, and then save the offset to that object's position (per object), rather than a buffer handle. It worked. The offset can be given as a parameter to glDrawElements as below. It seems obvious in retrospect, but I was not convinced until I saw it work. Please note that I have been working with "vertex pointer" rather than the more current "vertex attribute pointer". I am working towards the latter so I can leverage shaders. All the objects "bind" to the same vertex buffer, prior to calling "draw elements".
I did not find anywhere spelled out what was the purpose of this offset, so I took a chance. Also, this gotcha: you have to specify the offset in bytes, not vertices or floats. That is, multiply by four to get the correct position.
You maintain separate vertex/index buffers for different objects, yes. For example, you might have a RenderedObject class, and each instance would have it's own vertex buffer. One RenderedObject might take it's vertices from a house mesh, one might come from a character mesh, etc.
During rendering you set the appropriate transform/rotation/shading for the vertex buffer you're working with, perhaps something like:
As mentioned in there other answer, the bufferID is just a GLuint not the entire contents of the buffer. If you need more details on creating vertex buffers and filling them with data, I'm happy to add those as well.