Skip to content

Archive

Tag: OpenGL

Hairlock - dev pic

Originally developed under the codename ‘Hairlock’, Antistar 3D: Rising. is a universal game (iPhone, iPad, iPod Touch) published on the 1st of August 2010. Artwork in the game is a mix of Blender art and procedurally generated elements.

A Key Decision…

It was decided very early that all the details in the game would be modeled – no textures! There are several reasons why Antistar was created this way:

1 – I have never been very fond of textured games. This is isn’t because I think textures are bad, but because usually, I find that textures are abused, becoming an easy substitute for shading and high quality visual content.

2 – I trained myself in blender around 2000-2002; I always focused on modeling.

3 – Supporting textures would have added a load on the engine, taking longer to develop, leaving much less time to produce the actual content, making it potentially harder to run at frame rate and increasing loading times.

4 – Although it is now available on iPhone 4 and iPad, the game was originally developed to run nicely on an iPod Touch. On a small screen, the need to crowd scenes with tiny flatland decorations isn’t obvious – even if some games (e.g. Samurai: Way of the Warrior) use textures very ingenuously.

Blender’s good

Edit mode rocks!

Back in 2000 when I discovered Blender, I was still looking for software that could help me make my models. I am not a professional artist, so I need to try again and again until I see what I have in mind in the 2D view. Blender’s edit mode, with one hand on the keyboard and another securely cuddling the mouse, lets you change things over and over again at the speed of thought.

While the game doesn’t use textures, Blender has a nifty ‘retopo’ mode allowing to project geometry onto a surface while editing. This was used to add effects that make some players think that the game supports textures, but more importantly, offer an OK substitute to textures in situations where they’re really needed.

Free and comprehensive

It just turns out that Blender is completely free, open source and comprehensive. I didn’t use many features, but these are key to creating a game:

1 – Support for bone animation, with a little of a learning curve, but the same ergonomics found in edit mode, allowing to quickly define and adjust areas of influence for bones, add constraints, etc…

2 – Python scripting. I looked around for an export plugin for ages before getting into it, only to realise that python scripting isn’t hard, and there are key advantages to writing your own file format for 3D. In Antistar, geometry is loaded on the fly, in a format that Open GL understands, as exported directly from Blender, in just a couple of clicks.
Hairlock - dev pic
Technical data

How much geometry in there?

As this was my first 3D engine, and my first experience on a mobile platform, I was fairly cautious when I started modeling, as I was worried I would run out of GPU time fairly quickly. Over time I realised that (a) rendering is pretty fast, even on an iPod Touch 2nd gen, and (b) once we do away with mapped images, we have a lot of polygons to play with (it’s also good to know that smaller poylgons render much faster than large ones). Here are some examples:

- Humanoids and other creatures: 650 to 2500 vertices/quads(*)
- Small decorations: ~40 vertices/quads or less. These can get duplicated a few dozen times in the same scene.
- Terrain (e.g. the ‘incubator’ scene displayed at the top): up to 10,000 vertices/quads.

(*) In most cases, the number of vertices is roughly equal to the number of quads.

Rendering

For rendering, I used a mix of just-in-time calculated and real time lighting (for actors and props). Evaluating simple illumination on the fly while loading models has advantages, but I haven’t implemented a method to refresh lighting following the day/night cycle in the game; instead, fog is used to affect the rendering of the environment according to the day/night cycle.

I’m still considering whether to use LOD (level of detail) nodes (aka, lighter models when viewed from far away) or not. In the first version of the game, I used depth of field balancing to avoid dropping the frame rate too much. depth of field balancing works quite well, although it seems a little difficult to make it perfect :). in the meantime, artefacts aren’t usually disturbing and may even bring a little life to the game, with soft oscillations in depth of field and fog level.

Cheats ?

At times 3D can get a little intense. To create the dark forest near Klinnburg, I flattened the trees, only leaving 2D geometry. This allowed keeping patches of procedural grass that I kinda like, and adding walkable stones here and there. I don’t like doing that too much, because it always does show a little.

Future work

materials

In the first release, the exporter only processed RGBA colors for materials. The engine is a little more powerful though, as it can take parameters for shading, ambient… well, the basic kit.

I probably want to get better at python scripting, so I can explore ways of generating geometry using plugins, and better balance what’s generated on the fly versus what gets loaded.

Hairlock - dev pic

level editor

Currently, my export plugin handles objects and bone animations quite well, but it works more like a library export plugin, with any blender file containing a generous mix of actors, items and terrain. I want to take the time to turn this into a level editor. This would help streamlining the workflow, as for now the ‘level editing’ process consists in walking around the world and writing down coordinates (**)

forward raytracing?

And finally, I’ve been working on ‘rough and ready’ procedures for self illumination (!). This can be used part in real time, part by pre-calculating contributions. Initial results are promising and the results may ship with the game within a couple of months!

————-

Antistar 3D: Rising – is a realtime 3D adenture taking advantage of 3D capabilities on the iPod Touch, iPhone 3G/3GS, iPhone 4 and iPad. (app store link)

Hairlock - dev picHere’s a quick glimpse of the forest covering about a quarter of Hairlock’s tiny world. You bet the large flowers that you see at the bottom are generated/cloned on the fly.

How much plant growth can I afford within frame rate? Probably not as much as I’d like, but little is better than nothing and at least the ground recipe is set. Here’s a quick summary:

  • I define growth per material. So if the terrain has grass, something can grow on the grass, and so forth.
  • Growth isn’t just random. It uses random sources, then randomizes plant locations within (it could be anything. Bones? Bones grow in the desert, right?) and their density. This helps a little because plants aren’t just there to decorate. Pseudo-random distributions also help the player orient themselves a little, acting as landmarks in the landscape.
  • It’s not too hard to hit the roof on how many decorations can be added to a 3D scene. If you double the definition of a 3D model, you don’t double the number of pixels rendered for that model. On the other hand, if I double the number of flowers in a scene, you really draw twice as many pixels over.
  • Better news, there’s no practical limit to how many species of plants you might throw in your game. In this scene, I have only a couple of species (water lillies lost in the fog on the left) but that’s not a rendering limitation – from a design point of view, the trick is not to throw everything in at the same time: if we get our players to find stuff less often, we’re surprising them more often.
  • A side effect of having to pack geometry together (well yea… we can’t call glDrawElements once per flower, right?) is that it’s probably OK to vary the size, shape and color of each element. Haven’t tried yet.

Putting this up has been a little troublesome. as I’ve just mentioned, we can’t just draw each element on the fly, which makes things a little harder

  • For a given terrain (a piece of the 3D world), sources for growth are evaluated the first time the terrain is rendered. Each source will contain many instances of the same decoration, but we don’t evaluate anything at this point.
  • Sources pass a test to make sure they’re in-bound. The first time a source passes the test, memory is allocated for all flowers (or whatever) within that source. Then the terrain is intersected to find the insertion point of each element.
  • For each source, geometry for each element has to be duplicated (remember, we’re trying to call glDrawElements less often). This means the allocation for each source is… sizable. Surely we don’t want to evaluate each rendered source every time. So we cache the sources. So we quickly arrive at a point where the memory is filled with, wow, bouquets of low poly models (here, roughly 30 triangles each).
  • In a first approach, I release geometry for sources that haven’t been drawn for a while.

The trees in the pic are also randomized. But these are large enough (and the geometry is much heavier) so I just use gl operations to transform and render each tree.

By the way these trees have been around for at least a month, time to change them for something better I guess :) The decorator module wasn’t really hard to write – just a little more than an evening’s job.

OpenGL is the IT industry standard for drawing triangles, lines and points, and a lot more all the way down to the best realtime 3D games around.

OpenGL-ES1 is ‘OpenGL light’ suitable for mobile platforms such as the iPhone.

ES2 is the high end version of OpenGL-ES. Available on iPhone 3GS and maybe other platforms. ES2 has shaders, ES1 doesn’t.

Do I need to know OpenGL/ES to make (mobile) 3D games?

Not really, I don’t think so. You can learn a game engine instead, such as Unity, SIO2, Panda3D, Irrlich, Ogre.

So why would I learn OpenGL/ES?

OpenGL has been around for more than 15 years. If you want to become a 3D graphics programmer, it’s probably a good idea to learn both OpenGL and a game engine.

OpenGL is low level. Compared to using a game engine, knowing how to use the GL lets you be creative in different ways.

OpenGL is a little weird, but a lot of it is actually simple. Drawing shapes is a low level, yet simple concept. If you like ‘drawing and programming in 3D’, then OpenGL could be a better choice than a high level game engine that encourages/constrains you to just get your models from a 3D artist and fire animation commands.

OpenGL is the only API that maps directly to modern graphics hardware. Some people use the GL to do weird stuff that’s not really related to graphics, just because GPUs are fast and full of maths.

I’ve been hesitating a lot between re-learning the GL and learning a game engine. I’ll probably do both in the end but for now, because I don’t need serious physics, probably can’t afford having a lot of textures and I quite like drawing, I thought OpenGL may be a reasonable choice. Also, I’m currently creating a very high level scripting API to a 3D platform, so I like to look at things from the other end in my spare time.

Some GL calls are used to pass data, other GL calls are used to effect commands on this data.

The data you pass is usually retained, e.g. if you change the ‘drawing color’ the same color is used until you change the color again.
If you have never seen GL code before, this may feel awkward – why not just have commands like triangle(a,b,c,color) or the like? The reason is, GL is built for speed versus convenience. Passing lots of vertices at once reduces communication between the CPU and GPU; passing a color just once and then painting together all shapes of the same color reduces communication between CPU and GPU. Reusing coordinates on the fly for drawing two triangles (this is what TRIANGLE_STRIP is for) reduces memory usage and communication between the CPU and GPU.