Practical Blender with GLKit – Part 1 – Introducing GLKit
This is my first post for idevblogaday.com and I am quiet excited to be part of this community. The main reason to do this is so I do more constant iOS development. Hopefully I can keep up with the bi-weekly schedule.
With this post, I would like to start a series about the use of Blender for iOS game development. I will additionally base this series on the new iOS 5 framework GLKit. I will try to keep it rather practical and assume knowledge of OpenGL ES and Blender basics. If that is not the case for you, I will give reference to some literature for self-learning:
The general idea for the different parts of the series is at the moment as follows:
- Introduction: Basically set up a GLKit-based project from ground. This will be rather a beginners-type topic to get started. As GLKit is a just newly introduced API in iOS 5 I think that it makes sense to spend a whole post on it.
- Blender and Python: I will try to introduce the powerful python scripting engine underneath Blender. How to write own scripts that access the modeled object and modify them.
- Blender Exporting: We will use Blender’s python scripting engine to write our own export-function to a custom 3D model format and write the corresponding model-loader for our GLKit project of Part 1.
- Blender Animations: We will extend our model to contain skeletal animation and add the necessary adjustments to our Blender export-script and our GLKit project.
- We will see what I can come up with. I am not this far yet.
OpenGL ES Links
If you have followed this blog before, you might know that I expect you to read some external resource on your own to get the necessary concepts if you don’t know them yet. So here, some external literature for OpenGL ES, if you need to refresh your knowledge:
- Nehe: THE resource on OpenGL with alot of tutorials with sources for various platforms. Not specific for iOS, but you can find a port of the most projects on code.google.
- A great introduction into the concepts of OpenGL ES: Part 1, Part 2, Part 3.
- Jeff Lamarche has some nice tutorials for OpenGL ES 1 on iOS as well as some chapters on a planned OpenGL ES 2 book (Chapter 1, 2, 3, 4).
- Ray Wenderlich has also some iOS-specific tutorials on OpenGL ES.
- If you are like me and like to turn physical pages, this official guide on OpenGL ES 2 is worth it.
Introduction
- You have to learn the shader language
- You have to write the code for loading, compiling and linking the shaders yourself (well, it is in the template; but anyway)
- You have to set up the different buffers (pixelbuffer, depthbuffer, stencilbuffer, …) yourself (again; in the template, but it just leaves a bad feel in your stomach)
- You loose a lot of the beloved APIs for manipulating the modelview and projection matrices.
Project Setup
Next, go to the autogenerated GLKitAndBlenderViewController.h header-file and give it the protocols, methods, and member as you see below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#import <UIKit/UIKit.h> #import <GLKit/GLKit.h> @interface GLKitAndBlenderViewController : GLKViewController <GLKViewControllerDelegate, GLKViewDelegate> { @private GLKBaseEffect *effect; } #pragma mark GLKViewControllerDelegate - (void)glkViewControllerUpdate:(GLKViewController *)controller; #pragma mark GLKViewDelegate - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect; @end |
We do four main things here:
- Define this controller as a subclass of GLKViewController. This controller plus the GLKView we will define in the next step in interface-builder save a lot of work in regard of automatically setting up a render-loop and managing the framebuffer.
- We make this controller its own delegate by implementing the GLKViewControllerDelegate protocol. This protocol defines the method glkViewControllerUpdate: that is called each time before a new frame will be render. You can use it for any kind of calculations that have to be performed prior to the actual rendering; so, the render-method itself is as lightweight as possible. In a game you might also use this method to update your game-physics and -state.
- We also implement the GLKViewDelegate that defines us our actual render-method glkView:drawInRect:.
- Also, don’t forget to import the GLKit header-files!
Reimplementing the Swinging Square
You might know the standard OpenGL ES template in XCode, that displays a swinging, multi-colored square. We will reimplement this with the help of GLKit and the GLKBaseEffect. Once you have that running, you have a minimal GLKit template and we have a good basis for the next part of the series.
Let’s first review the viewDidLoad-method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
- (void)viewDidLoad { [super viewDidLoad]; EAGLContext *aContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; GLKView *glkView = (GLKView *)self.view; glkView.delegate = self; glkView.context = aContext; glkView.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888; glkView.drawableDepthFormat = GLKViewDrawableDepthFormat16; glkView.drawableMultisample = GLKViewDrawableMultisample4X; self.delegate = self; self.preferredFramesPerSecond = 30; effect = [[GLKBaseEffect alloc] init]; glClearColor(0.0f, 0.0f, 0.0f, 1.0f); } |
First, we set up the OpenGL Context (EAGLContext) for OpenGL ES 2 and set it on the GLKView (line 9). We also define us as the delegate for the GLKView and set some properties on the view so it can set up the framebuffer correctly.
From line 15 one, we first set us as the delegate for ourself (always good if you know how to help yourself!) and set the prefered framerate the GLKViewController will try to manage for us.
Oh; and we create an instance of GLKBaseEffect. If we look into the implementation of the GLKViewController delegate-method, we see what we can do with this effect-class:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
- (void)glkViewControllerUpdate:(GLKViewController *)controller { static float transY = 0.0f; float y = sinf(transY)/2.0f; transY += 0.175f; GLKMatrix4 modelview = GLKMatrix4MakeTranslation(0, y, -5.0f); effect.transform.modelviewMatrix = modelview; GLfloat ratio = self.view.bounds.size.width/self.view.bounds.size.height; GLKMatrix4 projection = GLKMatrix4MakePerspective(45.0f, ratio, 0.1f, 20.0f); effect.transform.projectionMatrix = projection; } |
As OpenGL ES 2 is missing all the APIs to easily manipulate the modelview and projection matrix (except from within the vertex-shader), GLKit defines a rich set of methods to create and manipulate matrices. So, equivalent to the code
glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslate3f(0, y, -5.0f);
we can do a GLKMatrixMakeTranslation() to create the translation-matrix and then set it on our GLKBaseEffect effect.transform.modelview-property. The internals will make sure to hand this over to the vertex-shader.
Same for defining our projection-matrix. Instead of glPerspective() in good ole OpenGL ES 1, we use GLKMatrix4MakePerspective() and set it on the effect-instance so these uniforms are internally passed to the shaders.
In fact, in the render-method, the first thing we have to do is call prepareToDraw on our GLKBaseEffect. Here the magic happends and the instance will bind uniforms/attributes that are internally defined and link the shaders. After that, it is rather standard OpenGL ES 2 code that defines verticies and colours for the vertecies and sticks them into the the standard glVertexAttribPointer-methods to feed them in the vertex-shader. Note though, that we have to use the GLKit constants GLKVertexAttribPosition and GLKVertexAttribColor so GLKit binds the attributes correctly to the variables in the shaders.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect { [effect prepareToDraw]; static const GLfloat squareVertices[] = { -0.5f, -0.5f, 1, 0.5f, -0.5f, 1, -0.5f, 0.5f, 1, 0.5f, 0.5f, 1 }; static const GLubyte squareColors[] = { 255, 255, 0, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 255, 255, }; glClear(GL_COLOR_BUFFER_BIT); glEnableVertexAttribArray(GLKVertexAttribPosition); glEnableVertexAttribArray(GLKVertexAttribColor); glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 0, squareVertices); glVertexAttribPointer(GLKVertexAttribColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, squareColors); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisableVertexAttribArray(GLKVertexAttribPosition); glDisableVertexAttribArray(GLKVertexAttribColor); } |
And, due to the glDrawArrays()-call we actually should see the swinging square when your run the project in the simulator. You can find the full project over at github.
So you see, GLKit is a quiet nice API that makes the transition to OpenGL ES 2 not so harsh. You get a great matrix-library and can also use the fixed-function pipeline from OpenGL ES 1 for some rendering where you are just fine with those capabilities.
And there is more: A class for easy texture-loading (GLKTextureLoader; no copying of Texture2D into your project as the first action), skybox-effects (GLKReflectionMapEffect) and Quaternions (GLKQuaternion). All stuff that you normally have to redo/reimport into your project to even get started.
What I was missing a bit at first was a base-class to derive and define your own effects. So, basically, get at least some help in loading and linking the shaders with a nice object-oriented API (there only is a protocol GLKNamedEffect you can implement to define your own effects). But this is only a minor point compared to all the other stuff you get for free. And, I assume we can look forward to some quiet nice additional effect in iOS 6+.
Blender Links & Hints
In the next part, we will start to use some advanced Blender scripting features. So, I will assume some basic blender knowledge up front. Here comes a list of what has helped me a lot to get started:
- The best resources can be found directly at blender.org in the Tutorials section. I basically did the introductory series and some advanced tutorials (1, 2) to model static objects. Once you have done the steps in the webcasts on your own, you should have a good overview of the basic blender features and check on advanced topics if you like. And don’t worry if you don’t get everything in the advanced tutorials; every part you get is great, the rest will come later.
- A great online-resource is the Blender 3D: Noob to Pro series.
- There is a great number of Blender video tutorials out there. Unfortunately, a lot are for older version. As the interface has been changed over time, be sure to look for the right tutorials; i.e. the interface in the webcasts should look the same as for your Blender version (presumable 2.5X) or you might not get the most out of it.
- Blender has a lot of keyboard shortcuts and mastering them is the key in becoming a Blender guru. This keyboard shortcut sheet helped me a lot in that regard.
- If you read this, chances are high that you work on a MacBook. Unfortunately, Blender makes good use of the numerical keypad and the third mouse-button for changing the viewport in the 3D view. So, I recommend using a three-button mouse for modeling. To at least emulate the 3-button mouse and the numerical keypad, there exist useful settings in the Preferences of Blender (File -> User Preferences): Check “Emulate 3-button mouse” to use Alt-left-mouse-button to rotate the 3D view and “Emulate numpad” to use the standard number-keys as a replacement for the num-pad. Don’t forget to press “Save as Default” if you want Blender to remember this until the next launch.
[…] Practical Blender with GLKit – Part 1 – Introducing GLKit 12 OCT 0 Share Categories: iPhone, Programming Tags: iPhone, Programming /* […]
Happy iOS 5 Day! « Under The Bridge
October 24, 2011 at 4:42 am
[…] the second part of this practical series on Blender for the use with GLKit-based iOS-applications. The first part focused on setting up a basic GLKit Xcode-project as the prerequisite for the following parts. As […]
Practical Blender with GLKit – Part 2 – Blender Scripting with Python « fruitfly
November 2, 2011 at 9:54 am
Hi 38leinad,
This post is wonderful in terms of learning GLKit and Blender.
I have been looking for a blog which can guide beginners on
studying opengl es 2.0, blender, ios and finally I find this one.
Thankyou 38leinad!
Johnson Tsay
November 4, 2011 at 5:30 pm
Seems to be a problem in Xcode 4.2: –
the lines below in the (void)viewDidLoad method cause errors: –
self.delegate = self;
self.preferredFramesPerSecond = 30;
Semantic Issue: Property ‘delegate’ not found on object of type ‘GLKitAndBlenderViewController *’
Semantic Issue: Property ‘preferredFramesPerSecond’ not found on object of type ‘GLKitAndBlenderViewController *’
Can anyone help?
Mick
November 5, 2011 at 10:47 pm
Did you use the sample-code from github or develop the steps on your own?
If the later, you maybe missed to make the GLKitAndBlenderViewController inherit from GLKViewController. Check your header-file:
@interface GLKitAndBlenderViewController : GLKViewController {
@private
GLKBaseEffect *effect;
MyModel *model;
}
38leinad
November 5, 2011 at 11:03 pm
Thank you 38leinad, you’re right I missed the inherit 🙂
Mick
November 5, 2011 at 11:19 pm
Great post., This is a much easier approach. Just one question:
How do you implement lights and textures without making the shaders yourself?
Justin
January 30, 2012 at 1:42 am
Hi Justin,
This is done as well with the class GLKBaseEffect. As stated in the post, it implements part of the fixed-function pipeline of OpenGL. This includes lighting and texturing.
See http://developer.apple.com/library/ios/#documentation/GLkit/Reference/GLKBaseEffect_ClassRef/Reference/Reference.html and in specific “Configuring Lights” and “Configuring Textures”.
Cheers,
Daniel
38leinad
January 30, 2012 at 11:30 am
Thanks for the info. I will look into it!
Justin
January 30, 2012 at 10:37 pm
I have a big problem here. I have to reload the texture from the pvrtc file every single time it draws. I have managed to bring the frames per second up to twenty five, but reloading everything is extremely expensive. Using the same texture and OpenGL ES 2.0, I was able to average 63 frames per second. Would you mind helping me to debug the code (I may have to send the project to you)?
Justin
January 30, 2012 at 11:30 pm
Hi Justin,
Maybe have a look here
https://github.com/jlamarche/iOS-OpenGLES-Stuff/tree/master/GLKit%20Stuff/GLKBaseEffect%20Drawing%20Example%20with%20Texture/blah
and here
http://games.ianterrell.com/how-to-texturize-objects-with-glkit/
for comparison. There definitvely seems to be something wrongly structured in your code. You only load and bind the texture once.
Cheers,
Daniel
38leinad
January 31, 2012 at 12:48 pm
– (void)glkViewControllerUpdate:(GLKViewController *)controller
should be in:
-(void) update
no?
adam
May 2, 2012 at 1:32 pm
Also, your glPerspective call looks odd. This:
GLKMatrix4 projection = GLKMatrix4MakePerspective(45.0f, ratio, 0.1f, 20.0f);
seems it should be in radians, according to the Apple docs (var name is “F.O.V. for y, radians”) not degrees?
adam
May 2, 2012 at 5:42 pm
ARGH! There’s an enormous bug in this code! It *WILL NOT WORK* correctly 😦
You haven’t set your EAGLContext as “current” – without that, half of the OGL commands will simply be ignored (and things like the depth buffer won’t work).
[EAGLContext setCurrentContext:aContext]; // do this before making any of your GL calls.
adam
May 2, 2012 at 9:45 pm
Awesome post, but adam is right, there are some things missing in the code. I found that, to enable the Depth Buffer, I needed the following calls as well:
GL.ClearDepth(30);
GL.Enable(EnableCap.DepthTest);
GL.DepthFunc(DepthFunction.Lequal);
This is MonoTouch/C# code, but its easy to translate to Objective-C.
Thank you!
Jonas
August 6, 2012 at 10:19 pm
you are right that it might make sense to enable the depth buffer if you want to tinker with some more advanced geometry, but the example i give does not real need/make use of depth buffering; so, i rather left it out.
38leinad
August 6, 2012 at 10:55 pm
I tend not to leave a response, but after reading a few of
the remarks on this page Practical Blender with GLKit – Part 1 – Introducing GLKit | fruitfly.
I actually do have a few questions for you if it’s allright. Is it simply me or do some of these responses look like they are left by brain dead visitors? 😛 And, if you are posting on additional online social sites, I would like to keep up with you. Could you make a list of the complete urls of your public pages like your linkedin profile, Facebook page or twitter feed?
binary options
November 6, 2012 at 7:09 pm
I know this web page provides quality depending articles and
extra data, is there any other web site which provides such stuff in quality?
disabled dating website
April 21, 2013 at 11:52 am
tnx!
yoni
July 24, 2013 at 12:39 pm
[…] Practical Blender with GLKit – Part 1 – Introducing GLKit […]
Happy iOS 5 Day! – Under The Bridge
May 11, 2016 at 11:27 pm
[…] https://38leinad.wordpress.com/2011/10/19/practical-blender-with-glkit-part-1-introducing-glkit/ […]
想要在iPhone上显示3D模型:如何开始?[关闭]|ios问答
December 4, 2020 at 9:23 pm