In order to see the Flickr control that goes here, please install Microsoft Silverlight!
Get Microsoft Silverlight

Ideal Binary

by Kevin Doolan 4. August 2009 17:49

Gravity Wave FREE has been submitted to Apple.  The premium version will be submitted within a week.  I already have at least two major feature updates planned, but I'm going to hold off implementing until the premium version is in the pipe.

By sheer coincidence, my brother has also completed the first version of our new corporate site, idealbinary.com.  He'll be joining me full time from September.

I'll be keeping this blog for non-work related posts, some code related and some not so.  I'll be covering anything work related on my Ideal Binary blog.

Gravity Wave

by Kevin Doolan 25. July 2009 22:10

After about four months worth of development time I’m nearly ready to submit my first full App for the iPhone.  It’s called Gravity Wave and it is loosely inspired by the old 8-bit classic, Thrust.  There have been many, many Thrust clones over the years (and there are already a few on the iPhone) but most tend to be slow, precision-movement type games.  Gravity Wave is a little different because it opts for a more arcade, fast pace type of game play.

I used Gravity Wave to help drive the development of my middleware platform UtopiaGL.  The first draft of UtopiaGL was completed at the end of December last year, and over the last 6 months or so I have been refining and further developing it to along side a few different projects, including Gravity Wave.

Gravity Wave is a pretty straight forward game.  I deliberately kept it simple because I knew I would be doing everything myself, except the title music and sound effects, which I licensed from a sound production company.  Essentially that means every task was on the critical path, pretty much.  That’s not an ideal situation, but this was very much an experimental project.  Given the super saturation of Apps on the App Store, I’m not sure how this project will do commercially, so I’ve done my best to keep my costs down, while maintaining the quality level as high as I could.

Below is a sneak peak of the game.  I’ll post further on technical aspects of the engine over the coming weeks. 

Level 1

Level 1

Level 1

Level 1

iPhone App Development

by Kevin Doolan 25. July 2009 21:59

I’m entering the final sprint of my current iPhone App project, so I thought I’d post some notes on the practices used (and some I should have used much more!) during its development.  I’ll post further on the low-level development, submission and review process later. For now I’ll focus on high level development issues.  These points are not iPhone specific but the ecosystem of the App Store makes them particularly relevant for a lot of the start-up, one-man band or small indie team projects that are buzzing at the moment.

Define Your Purpose

It sounds so obvious, and yet plenty of projects flounder for lack of it.  Begin by explicitly defining your purpose.  Be as specific as you can be.  The very first step you take in any endeavor is the one that establishes your direction.  Every single move you make should be in agreement with your purpose.  All those mini decisions you make every hour, week, month and so on have a compass.  If you don’t define your purpose, those compasses can drift without any clue where they should be pointing – the odds of all them pointing in the right direction are arbitrary and extremely unlikely.  Defining your purpose establishes your polar north and gives each one of those decisions a shared context and allows them to proceed intelligently, as if in concert. This applies as much to individuals as to teams.  Always define your purpose, and refer to it regularly.

Prioritize

You can’t do everything.  You have limited time, resources and energy.  Make a list of what you need to do, and sort it by priority – what do you vitally need to do and what can you live without?  Be prepared to drop features.  Establish up front which ones are core, and which ones you can drop later if you need to.

Be Realistic

If you’re working on your first iPhone project, keep it small, simple and straight forward.  It’s very easy to bite off more than you can chew.  The smaller your team is, the more sensitive you’ll be to schedule overruns.  Keeping things simple helps minimize this.  Use your first project as an intelligence gathering exercise.  You want to find out the full extent of the pipeline of going from an idea to a finished App on the deck.  If you can’t complete a simple project, you can’t complete any project.  Don’t let your App turn into Duke Nukem Forever Never.

Use Agile Practices

This is really a no-brainer for any software development project.  If you have not had the good fortune to have tried out proper Agile dev practices, stop what you’re doing immediately.  Pick up Agile Principles, Patterns, and Practices or any of the many great books on the subject and dig in.  The ultimate payoff is this.  Clean, simple, safe and focused code, regular working builds that actually do something useful, and best of all low stress levels even in high paced dev cycles.  Pick a practice, say Test Driven Development, and start using it.  When you’re comfortable with it, pick another.  Make Agile practices second nature and you’ll never look back.  If you’re like me, it’s not that difficult to occasionally slip back into old-school habits, particularly if you’re working on your own. Resist!

Get to the Heart of the Matter, Quickly

Whatever your app is supposed to do, make sure it can do it as soon as possible in stub form.  If it’s a game, then you should be able to play it early in the schedule, not late.  Use content placeholders. Don’t leave the core feature of your app until the last few weeks of your development schedule.  Any kind of app needs time to settle into it’s final shape.  You rarely see this happen immediately – it takes time, attention, testing and iteration.  Write your code to facilitate this.  For example, I wrote a Finite State Machine compiler for UtopiaGL which allowed me to flesh out the overall app flow in literally 30 minutes.  On day one of my current app, I could navigate through all screens and menus (splash screens, main menus, sub-menus, level selection, in-game etc).  The same process was used for game play, and all entity behavior.

Procedural Content

One of the best ways to cut your content creation time down is to make good use of Procedural Content.  It will depend largely on the type of app you’re working on, but many apps can benefit in some way.  Terrain generation and texture generation are the usual things you hear about within game development, but you can apply procedural methods to pretty much any type of content.  Ninety percent of the content in my current app is procedurally generated (most of it off-line).  The world terrain was generated by a mixture of hand made level layout images (a simple two-color image mask that identifies where a player can go) which feeds into a noise based terrain texture and geometry generation system.  The net result is a terrain that exactly matches the game-play needs, but looks like typical landscape.  I also used code to create some of the regular geometry using basic primitives.

In-App Editing

My current app is a simple arcade game.  I’m using it to flesh out my middleware engine and ensure that it’s as flexible as it can be.  I wanted the game-play creation cycle to be as quick and friction-free as possible, where you can make changes to levels and immediately test the game-play.  Rather than creating a separate editor I opted to implement editing in-game.  For the windows build of the App (I’ve done 99% of the work in Windows) you can play any level, hit the on-screen edit button and go into editing mode.  You have full editorial control over all entities (placement, attributes etc), and an on-screen edit palette that allows you to create, drag and drop, zoom, pan etc and otherwise manipulate the scene.  When you’re happy with your changes you hit commit and you’re back to normal game-play.  Each level was drafted in less than an hour. I further play-tested over the space of a few days, and that’s still on-going with minor tweaks here and there.  The typical cycle was:

  1. EditMode: Layout overall level structure. 
  2. PlayMode: Test overall timing. 
  3. EditMode: Flesh out a small section of level up to a check point. 
  4. PlayMode: Test game play up to check point. 
  5. Repeat steps 3 and 4 until level is fleshed out fully. 
  6. PlayMode: Play test the entire flow and timing of the level.

Before editing commenced I established the overall design goals of each level, so that I could work through them fairly quickly and still have them fit into the overall scheme of the game.  There’s a very interesting latency issue with any kind of creation process.  There’s a timing ‘sweet spot’ where the whole process flows very smoothly provided you can get the details out of your head and onto the screen at a rate fast enough to move with your thoughts, and not be held up waiting for something (like having to quit an editor, compile content, load into the game, navigate menus, load a level, move to the point in the level you’re interested in, and…what was I doing again?!?!).  It would have taken considerably longer if I had opted for offline editing. 

There is also another very important creative aspect: feedback.  When you plan on a certain type of game play, it usually doesn’t translate into reality just the way you expect – there will be things you didn’t anticipate.  I really enjoy watching this process happen, because you can usually find a wealth of opportunities you overlooked initially.  Some things you thought would be fun may not be, and something you never considered important may end up being your game-play center piece.  You can only capitalize on this if you get game-play working early.

If you’re contemplating creating editing tools yourself, whether in-app or not, think carefully about how they should work.  Consider the workflow of the artist or the designer in detail, how much time each step will take, how much effort is involved, what can be automated etc.  Multiply your timing estimates over the expected creation cycle timeframe, and identify the stages that should be focused on to increase production speed.

Pragmatism

This is something you need to get clear to ensure the best chance of lift-off for your project.  Programmers often slip into a frame of mind where they want their code to be spotless.  I don’t sleep well when I know there is a mess waiting for me the next time I sit in front of my machine.  The problem is, it’s impossible to make things really spotless – everything has a context in which it is judged and that context is a moving target.  This can turn into an enormous tar pit.  Avoid it.

You can deal with this by referring to your project’s purpose and by keeping Agile.  Does the work I’m about to do agree with my purpose?  Will cleaning up this class, writing a general purpose solution, etc, get me closer to my goal?  If the answer is “no, but…”, then it’s probably time to stop and have a think about what you’re Real purpose is, because it’s not what you’ve convinced yourself it is.  Use Refactoring (to allow your code to change quickly, dramatically, and manageably), TDD (to help keep the design clean and guarantee changing or refactoring your code doesn’t break anything), User Stories (to keep User focused, and avoid wasting time writing code that doesn’t help your project) and short iterations (to help establish your pace, and allow better forecasting of completion times) to ensure you keep on track and avoid getting stuck in this pit.  Do the least amount of work to get to your goal.

If you’re writing an app to be used by people then…you’re writing your App for a User.  That clarifies everything you need to know.  You want things to be perfect?  That’s great.  Don’t try to make your code perfect.  Try to make the App perfect instead.  Ideally, when the User uses your App they should see as close to Perfection as you can create with the time and resources you have.  When a programmer looks at your Apps source code they should see Pragmatism.

If you’re using Agile practices, then it’s ok to have parts of your code appear a little messy by traditional standards – it’s the quickest way to get your User Stories implemented.  Short, simple code is beautiful.  When you start needing to revisit that code, or repeatedly duplicate it, or require more flexibility, then (and only then) you generalize and clean it.  It’s ok, because you have automated tests that constantly watch that code for bugs. It’s ok because refactoring allows you to radically change the code quickly and in a stable way when you need to.  When you leave your work at the end of a day, you know with a high degree of certainty where you are on your schedule, how stable your work is, and that with one click you can spit out a release you could put in someone’s hands and have them use the App.  You also feel far less stress – one of the most welcome side effects of Agile practices.

Pragmatism means writing solid code, not perfect code.  Perfect code usually means Indulgent Code – someone indulging their appetite for elegant, sophisticated, complex-toy kind of code, often at the expense of clarity, time, usefulness etc – this kind of code is absolutely not for the Users benefit, it’s for the Coders ego, or misplaced idea of what good code is.  Indulgent Code is what happens when a developer gets so focused on the code that the end result, the App they’re developing, gets completely overshadowed by the act of coding.  This is detrimental, and usually forecasts failure for the project.  Ironically, shifting a perfectionist focus off the code and onto the App by using robust practices is when the code actually starts to approach the only measureable perfection you can humanly achieve.

Conclusion

If you’re aiming to put applications out on the iPhone then you’re up against some pretty stiff competition.  The sheer numbers of competing Apps is daunting to say the least.  It’s more important than ever to try to minimize development time and maximize quality.  The practices you use can make or break your project.  I benefitted from using Agile practices on my current project, but I could have used them more fully – something I intend to do on my next project.  I can’t recommend them enough.

iPhone OpenGL ES Performance

by Kevin Doolan 6. March 2009 01:30

Fine tuning 3D code can be a black art, particularly if you are new to it.  If you’re not familiar with the hardware, it may not be immediately obvious why certain calls are expensive and others aren’t. To make matters more complicated, each system has little quirks and gotchas that surface along the way while developing 3D code.  The iPhone is no exception.  Here are some optimizations that may save you some head scratching, particularly if you’re new to OpenGL.

EDIT: I have updated some of the points below to reflect the iPhone benchmarking done by Patrick Hogan. Thanks again Patrick. For more details, check out the comments at the bottom.

Timers are Great, Threads are Better

The ‘Hello World’ iPhone OpenGL ES project sets up a simple timer based run loop, which is a very convenient way of executing your app.  You don’t have to worry about synchronization issues, there’s no overhead involved in context switches (your app is executing in a single thread) and debugging is trivial.  So why would you want to rework your code to operate in a separate thread?  The reason is simple:  With timers there will potentially be a gap of ‘dead time’ where your engine is doing nothing, waiting for the next timer event to fire.  This simply defeats the potential parallelism that you can achieve between your app and OpenGL.  The GPU has enough to cause it to stall when interacting with your app, without the additional delay of your app also waiting for a specific time in which to execute.  As soon as there are CPU cycles available to your app, you should take them immediately, get all frame processing out of the way and issue your calls to OpenGL.  From a performance point of view, ideally neither the CPU, nor the GPU should ever be stalled if it can be avoided.  My engine, UtopiaGL, runs around 15% faster using a thread based frame update instead of a timer based approach.

Avoid thread synchronization issues by engineering your code to simply not need synching.

EDIT: My current project has turned up some new details here. When I tested on generation 1 hardware, the threaded approach resulted in sporadically choppy update.  I was able to address it by introducing a short sleep per frame, but it ended up being the same as the timer method in terms of performance.  It looks like the OS background tasks get starved of CPU cycles and then all of a sudden decide to shut your app out for a relatively huge chunk of time while they look after themselves.  This feels very Brew 1.1!!  The timer method is far simpler, so for generation 1 hardware I opt for the timer approach.

Allow OpenGL to run in Parallel

The OpenGL ES pipeline executes in its own thread.  When you issue calls to the API, they are not executed immediately, and instead get placed into a command buffer which eventually gets flushed.  Calls to the API return immediately, allowing your app to proceed with whatever it’s doing.  This means that in theory you should be able to execute for a considerable chunk of time in parallel with the graphics hardware.  This is as you would expect, but there are certain calls you can make that effectively break this parallelism, and with them, the frame rate of your app comes spinning down.  The usual suspects are glReadPixels, glTex(Sub)Image, glBuffer(Sub)Data etc.  If you need to use them per frame, be aware they have quite a performance hit. 

If your app runs within a single thread (i.e. the renderer) then avoid calls to glFlush and never, ever use glFinish.  glFinish is particularly bad.  It flushes the command buffer and blocks the calling thread while it does it.  glFlush does the same thing, less the block.  Both are used to synchronize with the GL driver, but you rarely need to do that.  An example of when you might need it is if you had two rendering threads, both of which were rendering into the same GL context.  If you do need synchronization, use glFlush.  Pretend glFinish doesn’t exist – you should literally never call it on the iPhone.

Use Vertex Buffer Objects or Not!

Make good use of Vertex Buffer Objects for any static geometry.  In theory this allows you to store geometry (including index data) in fast video memory.  The iPhone uses shared memory i.e. the CPU and PVR hardware share the same memory, so in this case it simply means you save having to upload your geometry to GL every time you call glDrawElements etc.  The savings here can be very significant.  You would be amazed how much geometry you can throw at the iPhone with VBOs before it breaks a sweat.

EDIT: After reading Patricks comments below, I went back and looked at my VBO code. Unfortunately the gl driver doesn't take advantage of VBOs and uses a full copy operation in both the VBO and non-VBO case. Up until now I’ve been working off observations with my own shader pipeline. I see an increase in speed using VBOs but from examining it more closely, the speed increase doesn't come from the fact that the vertices are in a VBO - it comes from the fact that my non-VBO path does more work on the CPU side. This surprised me because I saw a drop of around 8fps with a stress-test scene in the non-VBO case - quite a bit more than I expected from the extra CPU work alone – I expected it would be in line with VBOs being effective, and that things would run slower without them. My shader pipeline works like this. Geometry is queued for rendering, and when the scene is complete it tries to minimize the number of calls to glDrawElements by rendering from shader buckets. Effectively each shader has a geometry bucket and any geometry in the same reference frame is packed together and issued to gl in a single call to glDrawElements. Most of the geometry (anything not dynamically generated per frame) lives in its own VBO. In this case I don't add it to the shader bucket; I just render it on its own with a call to glDrawElements. Since VBOs don't seem to offer a speed increase, when I turn them off and fall back to my packing scheme, it should be fairly similar in speed – but it’s not. It’s doing the same amount of work as the VBO case plus the extra work I’m doing to pack everything. There seems to be no advantage in minimizing calls to glDrawElements - at least not with the scenes I’ve been testing. It seems it’s better to just issue multiple glDrawElements calls. I didn't look at it too closely originally because my typical scenes were running at 60fps - I saw what I was expecting to see: that VBOs were faster – in my case they were, but not for the reason I assumed.

The tests I did above were not exhaustive and are very particular to my engine and current app, but they agree with Patricks findings below. When I remove the code to minimize glDrawElements calls, and issue the same geometry with and without VBOs I see no real difference in speed. Vertices have xyz, tc and color attributes – lighting is precached.

Be Cache Aware

Use indexed striped triangles for geometry, and render through the glDrawElements call.  Sort tris to maximize vertex cache usage, then sort vertices to be in sorted-tri-order.  Don’t worry too much about having the tris in strip order – make sure cache usage is your sorting metric.  Where it makes sense, interleave vertex attributes, for example all static geometry should have interleaved attributes.

EDIT: I haven’t confirmed it in my engine yet but it seems strips do outperform lists by a small amount.

Read the Apple and PVR performance guidelines

In short: RTFM.  There’s a lot of good advice in those docs.  Surprisingly, when I last checked, Vertex Buffer Objects weren’t mentioned in the Apple guidelines – an odd thing to omit.

EDIT: In light of the VBO implementation, this isn't an odd thing to omit at all. Also, the Apple recommendation to use lists instead of strips doesn’t seem to hold water, although it is fairly close. See the comments below from Patrick. The best advice is: Read the guidelines, but profile your code.

Use Instruments

Instruments is an excellent app that comes with Xcode and allows you to profile your app running on-device.  You can examine all kinds of details about how your app executes, and zero in on bottle necks.  With respect to OpenGL, you can use it to see which calls are being issued a lot, and/or take the most time.  This is an invaluable tool, and should be your guide for any optimizations.

Conclusion

Every app is different, and even the same engine could perform wildly differently with different content, so when you hit a bottleneck you really need to profile to find out where your app+content is spending most of it’s time, and focus your optimizations there.  That said, many of the above points apply globally, and your app will almost certainly avoid performance pitfalls if you are careful to adhere to them.  The iPhone has some serious horse power under its hood. Initially I was skeptical about just how powerful it was, and after fine tuning my engine I’m extremely pleased with it.  Compared to other mobile 3D devices, the iPhone and iPod Touch are in a class of their own.

iPhone 3D Engine Development

by Kevin Doolan 24. January 2009 03:16

Last month I completed my middleware 3D engine, UtopiaGL for iPhone.  I’d never actually used a Mac before this project and I wasn’t sure what kind of effort would be required to get up to speed on OSX and the Mac development process (short answer – about 2 hours of effort!).  Here are some notes on my experience.

EDIT: I recently published a simple game on the App Store using my engine.  It’s called Gravity Wave and you can check it out here.  I will be blogging on my company site about how it was created, and how UtopiaGL made it straight forward to produce, so check out the site soon...

The Engine: UtopiaGL

It’s a C++ OpenGL ES, Shader-based engine and tool chain similar in feature-set to PC Games from around 5 years ago.  All OpenGL ES features supported by the iPhone are exposed through the Shader system, so you can do anything the PVR hardware can do.  The pipeline is optimised according to the PVR recommendations, as well as my own testing.  The helper tools include a Shader Compiler, Font Compiler, Model Compiler, 3DS Exporter and State Machine Generator.

Development

The core engine and tools took 8 weeks to write.  I wrote it in C++ on Vista using an OpenGL ES emulation layer.  I’m very familiar with Visual Studio – Xcode is cool, but at the time I just wasn’t comfortable with it so I battled on in Windows.  I wrote the engine to be portable across OS platforms so it has a System layer to abstract away the Platform specifics.

Once I had the engine ready and running well on Windows I moved it over to Xcode and rolled up my sleeves, expecting quite a bit of work.  Amazingly, it only took a few hours to get working, and most of that was learning the ins and outs of Xcode.  When I ran it on a device using a test scene it initially ran at 30 fps.  I was pretty disappointed at that speed given the optimisations that were being used.  I took a quick look over the code and saw that the Framebuffer was being created as a 32bit RGB buffer – I had just taken the setup code from the OpenGL ES Hello World app to get up and running.  I set it to RGB565 and sure enough it shot up to 60 fps.  It does drop down to 40/45 fps when you turn on Framebuffer effects (like Bloom glow).

Edit: After a few weeks of further optimisations and testing I've managed to squeeze quite a bit more GL performance out of the device (to my sheer astonishment).  For example Framebuffer effects now run at a constant 60 fps, details coming soon...

Xcode

I wasn’t sure what to make of Xcode initially.  After getting used to it I’m quite happy with it as a development environment.  There are a few things that feel a bit minimalist about it – it doesn’t feel as advanced as Visual Studio, but at the same time, you do feel like you’re getting more signal and less noise, considering what’s there.  (Actually Mac OSX in general feels quite minimalist, in a good way.) One thing I find annoying is there is no clean, simple way of including one iPhone project in another (this has been the single biggest influence on my view of Xcode).  VS does this extremely well with ‘Solutions’ which wrap Projects.  Obviously when you’re writing a middleware engine this is something of a requirement.  Right now I’m including all the engine source directly in the Application projects in Xcode, unlike in Visual Studio, where they have a neat Application Solution that simply includes the engine library project.  You can get Xcode to play ball, and a few people have blogged about it, but I’m not happy with the way it works – it should be a trivial thing and it certainly is not – it involves many, many steps, when it should require only one: inclusion of a reference to the library project.

EDIT: When I wrote the above, there was no Static Library project template in Xcode, and I didn’t know enough about the process on Mac to set it up quickly.  The Static Library project template does exist now (and has done for a while) and works extremely well, allowing exactly the same library project dependency set-up I was used to in Visual Studio.  Thanks to Simon for pointing me towards this in the comments to this post.

Objective C

If you haven’t written Objective C before, it can look a bit weird at first if you’re coming from a more traditional C derived language background.  It is growing on me, and I really do like the fact that the Apple Framework APIs look super clean.  I just have one problem with it – the way parameters are interleaved with Message names.  The idea is sound, but I don’t like the way it’s done in Objective C.  Many languages have done it well and they do it by allowing you to name parameters as you pass them, like MessageName( FirstParam=47, SecondParam=”Hello” ).  The reason I’m not keen on the Objective C way of doing it is I find I need to stare at the code to extract the meaning – it takes effort.  This is something I’ll probably get used to, but right now it’s a bit annoying.  I think it’s that there are no brackets delineating the parameter list – my eyes are scanning for it and can’t find it, making it a bit jarring.  If I had been proficient with Objective C and moved to C++ I might find C++ equally jarring.  I’ve learned many new languages over the years, but I’ve never found any so odd – not even Lisp or Prolog.  Maybe it’s just me…

In any case, I was able to avoid Objective C almost entirely.  The only Objective C is in the Platform code to set things up, drive the message pump, and provide implementations of system functions like getting the App path.  Maybe 200 lines of trivial code.  Everything else is portable C++.

Memory Management

Garbage Collection has been disabled on the iPhone (a good thing – full blown Garbage Collection is expensive, and arguably a nonsense feature to have on a mobile, power constrained device). I wrote 3 memory management systems for UtopiaGL, all very simple, and very specialised.  The first is for the core engine back-end which is very light, extremely fast and results in zero fragmentation.  It’s not Garbage Collected but it does allow you to nail memory leaks immediately.  You can also use it in the front-end Application code for making gross allocations, like loading large App-specific data.  The second one is exclusively for the Geometry processing engine and is super simple, and extremely fast – it’s an allocate-and-forget system designed for permanent allocations.  It gets zapped entirely at the end of each scene render.  Lastly, there’s the client memory manager (the client being an Application written using the engine).  This is designed exclusively for the front-end client code to use and is Garbage Collected (reference counted, but detects cyclic refs).  It’s also extremely fast (nowhere near as expensive as power-hungry Mark and Sweep GC for example), and is actually a relatively tiny piece of code.  When objects are no longer referenced they are deleted immediately unlike traditional GC.  Objects allocated with this system are only visible through reference pointer objects and reference pointer array objects (like in Java or C#).  You can create arrays (even multi-dimensional arrays) of object references that behave exactly like the Java or C# equivalents, complete with a .length member per dimension.  You never have to explicitly delete anything, space permitting. All allocations go through the ‘placement’ new operator, so it is very comfortably integrated with C++.

Touch UI and the Accelerometer

These are the most interesting new features you get to play with.  The Accelerometer is impressive – it’s extremely sensitive, way more than I was expecting.  It provides a 3 vector with force in each spatial dimension – simple and to the point.  You can control the rate at which the accelerometer feeds samples to your app, but for most interactive apps you’ll want that to be as close to 60Hz as possible.  In order to extract meaningful information from the data coming from the accelerometer you will eventually need to apply some kind of filtering.  Some knowledge of Digital Signal Processing is very useful here, but not required (a High or Low Pass filter can be written in a few lines of code and is very straight forward to understand).  The other input method is of course the Touch interface.  Your app gets a handful of messages informing it of touch events (when they start, move, end etc).  Each individual touch is tracked, so if you can imagine pressing your finger on the screen, that creates a ‘Touch’ object, if you move your finger that particular Touch object gets updated with new position information and a ‘Phase’ field that reflects the current phase of the touch event: Began, Moved, Ended etc.  When you finally lift your finger, the Touch object gets it’s Phase set to Ended and after you have been informed about it, the Touch object gets recycled by the system.  One Touch object exists for each point of contact on screen and is updated as its point of contact changes.  Tap events are modeled as touches also, with the tapCount field indicating the number of taps that have occurred.

I have abstracted Touch events essentially identically in UtopiaGL, except each Touch can be identified with an ID. UtopiaGL Touches can track several seconds of movement (you can configure this), unlike the raw events which just give you a current and previous position.  This eases the burden on Gesture Recognition somewhat.

UtopiaGL has it’s own event system, so in the platform specific code, native events are translated and fed to UtopiaGL’s system object in a format it recognises.  From there, they are distributed to the rest of the engine in an entirely platform independent way.

OpenGL ES on iPhone and iPod Touch

The features exposed by the PVR hardware are excellent.  There was one disappointing omission and that was the Vertex Program extension.  The PVR hardware supports Dot3 blending which means you can do Bump/Normal mapping.  Unfortunately, without the Vertex Program extension you are forced to enlist the CPU if you’re doing Tangent Space bump mapping, with a matrix multiply per vertex.  If you’re doing Object Space bump mapping you don’t need to do that, but you are stuck with rigid models that can’t deform without breaking their lighting.  Another reason why I was hoping the VP extension would be exposed is to supply my own lighting equation.  The standard OpenGL ES lighting system is expensive.  All you need in most cases is a very trivial ambient + diffuse lighting equation.  Without the VP extension you either bite the bullet and use the Standard OpenGL ES lighting model (which allows you to store your geometry in video ram) or write your own simplified lighting code and upload the vertex colors per lighting change.  If your models require CPU work, for example if you’re applying some kind of CPU-based deformation to them then it may make sense to implement the lighting on the CPU and upload everything in one go.  If your geometry is entirely static, then it may make sense to just use the OpenGL ES lighting model.  It’s not a clear cut situation. Right now I’m using the OpenGL ES lighting pipeline for all lighting, but I have left a stub for CPU based lighting – I’ll be experimenting with this shortly.

EDIT: The shared memory model on the iPhone and the fact that the VBO extension offers no speed up really mean you're faced with a more level playing field: you just operate off system memory vertices.

The Framebuffer (FBO) extension is supported, and actually the primary way you render to screen.  The FBO extension opens up a wealth of possibilities (using render-to-texture) and I was delighted to see it on the device.

Performance is excellent, above what I was expecting from a non-dedicated games device. 

UtopiaGL Shaders

The Shader system is a pass-based renderer, which is configured by a compiled shader script.  The compiled shaders are tiny, usually around 150 bytes.  The reason I compile them offline is to remove the burden of parsing them on-device at run time.  They’re not a million miles from Quake3 shaders, but they give lower-level control, for example you can fully control multi-texture (2 TMUs are expected) and the texture combiners.

I wrote a packing system for vertex attributes to minimise VGP and CPU cache misses.  It’s very straight forward and works like this: Shaders expect certain attributes to be present in a vertex in order to execute, e.g. if a shader does multi-texture mapping and lighting then it needs XYZ, Normal, TC0 and TC1 attributes.  You have two options when representing these attributes in ram.  You can either have a Structure of Arrays (SOA) or you can have an Array of Structures (AOS).  SOA is conceptually easier.  Essentially you have an array of XYZs per vertex, an array of Normals per vertex and so on.  This has the advantage that if you are performing CPU-based deformation on any attribute array, you limit cache misses.  You pay for it when the GPU gets to work though, because the CPU cache is under-utilised as it pulls vertex information from very different locations in ram.  The alternative is to interleave the attributes ala AOS.  In this case you have and array of vertex structures, each of which has the XYZ, Normal, TC0 and TC1 attributes.  This means you under utilise the cache if you need to perform CPU-based deformation on any attribute, but it means the cache is well utilised when the GPU is pulling in vertices.  My solution to the problem was to not use either method, but a hybrid of both.  Any static, non-changing attributes get interleaved into a per-vertex structure.  This doesn’t incur any cache abuse w.r.t the CPU because it never looks at them and the GPU maximises cache hits as it pulls in the vertices.  Any volatile attributes that need to be processed by the CPU are arranged into arrays for quick processing and I take the cache miss on the GPU end which is essentially limited to those specific attributes.  You get the best of both worlds.

Before the geometry ever gets to the Shader system, I apply a reordering algorithm to both the triangles and then the vertices to ensure maximum VGP cache usage.  It’s a fast process and is performed offline in a Model Compilation tool which is part of the engine tool-chain.

EDIT: There seems to be an advantage to using strips with a call to glDrawElements: see my more recent post on gl performance.

One thing I found odd about writing the shader code was the PVR compressed texture support.  PVR compressed textures appear flipped along the y axis – they load upside down!  The apparent reason for this is to maintain consistency with the render-to-texture support.  That doesn’t make any sense to me!  Anyway, our lives are now slightly harder - that’s how it is, so unfortunately you need to add an entirely redundant step into your content build process to manually flip textures before PVR-compressing them, or resort to other hacks as you load the textures. Bad smell.  Apart from that oddity, the compression is excellent and the quality is likewise impressive.

Conclusion

iPhone development has been fun so far.  I’ve done a lot of work in mobile game development, and the iPhone is easily the best thing I’ve ever experienced in a mobile device.  I’ll be submitting my first applications built using UtopiaGL to Apple soon, with a little luck.  Time permitting, I will blog about specific aspects of the engine in detail and iPhone development in general.

About

I'm a software engineer with a background in game engine development as well as art and animation.  More detail...

Calendar

<<  March 2010  >>
MoTuWeThFrSaSu
22232425262728
1234567
891011121314
15161718192021
22232425262728
2930311234

View posts in large calendar

Details

Powered by BlogEngine.NET 1.4.5.0
Theme and LensPanel/Flickr Control by Kevin Doolan



Hosted at DiscountAsp.net

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

This website is not responsible for externally hosted material, including linked articles, photos or any other media.

© Copyright 2009, Kevin Doolan.