Cross-Platform Game Development for C++ Developers, Part III: The 3D Irrlicht Engine

CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

The Irrlicht Engine is a high-performance, real-time 3D engine written and usable in C++ and also available for .NET languages. It is completely cross-platform, using your choice of Direct3D on Windows, OpenGL 1.2, or its own software renderer. Although open source, the Irrlicht library offers state-of-the-art features normally found in commercial 3D engines, such as dynamic shadows, particle systems, character animation, indoor and outdoor technology, and collision detection (see Figure 1).

Figure 1. The Irrlicht 3D Engine

Irrlicht is the name of a German fairy-tale creature that glows and flies, and can be found mostly in the vicinity of swamps. The word “Irrlicht” is the combination of the two German words: “irr,” meaning mad; and “Licht,” meaning “light.” In English, it translates to “will-o’-the-wisp.”

Irrlicht is also blessed with a huge, active development community with lots of projects. Yet, because Irrlicht is primarily the work of gaming auteur Nikolaus Gebhardt, it reflects a very cohesive design. You can find enhancements for Irrlicht all over the Web, such as alternative terrain renderers, portal renderers, exporters, world layers, tutorials, and editors. Also, it has independently created language bindings for Java, Perl, Ruby, BASIC, Python, LUA, and more. And best of all: It’s completely free.

Inside the Irrlicht Feature Set

Before drilling down into the API, let me get a bit more specific about what Irrlicht has to offer the 3D game developer:

  • An engine that runs on Linux as well as Windows 98, ME, NT, 2000, and XP (MacOS planned)
  • Anti-aliasing support in Direct3D version 8 or 9 renderers (optional)
  • Skinnable-GUI environment (including a cool metallic shaded skin) to give some pizzazz to old dialogs
  • Scene management system that allows seamless indoor and outdoor transitions
  • Character animation system with skeletal and morph target animation
  • A special effects system, including particle effects (rain, smoke, fire, snow, and so forth), billboards, light maps, environment mapping, stencil buffer shadows, fog, texture animation, parallax mapping, bump mapping, and more
  • Built-in materials, including support for Pixel and Vertex Shaders 1.1 to 3.0, ARB Fragment and Vertex Programs, and HLSL (GLSL is planned)
  • .NET language binding, which makes the engine available to all .NET languages such as C#, Visual Basic.NET, and Delphi.NET
  • A built-in platform-independent software renderer, featuring z-buffer, Gouraud shading, alpha-blending and transparency, and fast 2D drawing (see Figure 2)
  • 2D drawing functions you’ve come to expect, such as alpha blending, color key-based blitting, font drawing, and mixing 3D with 2D graphics
  • Direct import of common mesh file formats: Maya, 3DStudio Max, COLLADA, DeleD, Milkshape, Quake 3 levels, Quake2 models, DirectX, Pulsar, My3DTools, FSRad, and Cartography Shop
  • Direct import of Textures from BMP, PNG, Photoshop, JPEG, Targa, and PCX
  • Fast and easy collision detection and response
  • Optimized fast 3D math and container template libraries
  • Directly reading from (compressed) archives (.zip)
  • Integrated fast XML parser
  • Unicode support for easy localization

Figure 2: Irrlicht-based game called Yet Another Space Shooter (YASS) displays breathtakingly good rendering for a static game frame

Special Effects in Irrlicht

I always like to show off just a little bit more than “hello world” when I’m demo-ing a new game engine. In this example, I’ll show how to use stencil buffer shadows, the particle system, billboards, dynamic light, and the water surface scene node—all at the same time (see Figure 3).

Figure 3. Render This Scene with Dynamic Light and Water

The Irrlicht Engine automatically checks to see whether your hardware supports the stencil buffer, and disables shadows if it’s not present. In this demo, the ‘shadows’ flag in createDevice() is set to render a dynamic shadow cast from an animated character. If this example runs too slowly on your PC, set it to false or buy a better graphics card.

To be able to use the Irrlicht.DLL file, you need to link with the Irrlicht.lib. You could set this option in the project settings, but to make it easy, use a pragma comment. The createDevice() instantiates the root object for doing everything with the engine. Parameters are as follows:

  • deviceType: The device type. This can currently be the Null device, the Software device, DirectX8, DirectX9, or OpenGL.
  • windowSize: Size of the window or full screen mode to be created. This example uses 512×384.
  • bits: Number of bits per pixel (when in full screen mode). The only values are 16 or 32.
  • fullscreen: Specifies whether you want the device to run in full screen mode or not.
  • stencilbuffer: Specifies whether you want to use the stencil buffer for drawing shadows.
  • vsync: Specifies whether you want to have vsync enabled (full screen only). Optional
  • eventReceiver: An object to receive events. Optional

For the example environment, you’ll load a 3D Studio Max file of a room. The room is nothing much to look at, but the Irrlicht Engine is able to create a cool texture mapping for you. Just use the mesh manipulator and create a planar texture mapping for the mesh:

#include <irrlicht.h>
#include <iostream>

using namespace irr;

#pragma comment(lib, "Irrlicht.lib")

int main()
{
   // Let's assume the user wants OpenGL for this example
   // could have specified DirectX 8, 9, etc.
   video::E_DRIVER_TYPE driverType = video::EDT_OPENGL;

   // create device and exit if creation failed
   IrrlichtDevice *device = createDevice(driverType,
      core::dimension2d<s32>(640, 480), 16, false, true);

   if (device == 0)
      return 1;

video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();

I wasn’t happy with the emissive light color from this import file. The following shows how to implement these steps:

scene::IAnimatedMesh* mesh = smgr->getMesh("room.3ds");

smgr->getMeshManipulator()->makePlanarTextureMapping(
   mesh->getMesh(0), 0.008f);

scene::ISceneNode* node = 0;

node = smgr->addAnimatedMeshSceneNode(mesh);
node->setMaterialTexture(0, driver->getTexture("wall.jpg"));
node->getMaterial(0).EmissiveColor.set(0,0,0,0);

Water Animation

The first special effect you will add is water animation. To do this, the WaterSurfaceSceneNode takes a mesh as input and makes it wave like a water surface. If you let this scene node use a nice material like the MT_REFLECTION_2_LAYER, it looks really cool:

mesh = smgr->addHillPlaneMesh("myHill",
   core::dimension2d<f32>(20,20),
   core::dimension2d<s32>(40,40), 0, 0,
   core::dimension2d<f32>(0,0),
   core::dimension2d<f32>(10,10));

node = smgr->addWaterSurfaceSceneNode(mesh->getMesh(0),3,300,30);
node->setPosition(core::vector3df(0,7,0));

node->setMaterialTexture(0,driver->getTexture("water.jpg"));
node->setMaterialTexture(1,driver->getTexture("stones.jpg"));

node->setMaterialType(video::EMT_REFLECTION_2_LAYER);

As input mesh, you create a hilly plane mesh, but you could use any other mesh for this. You could even re-use the room.3ds input file (which would look really strange). The example also paints all the other surfaces with a generic stone texture pattern.

Transparent Billboard and Light

The second special effect is very basic but highly useful: a transparent billboard combined with a dynamic light. To make this happen, you simply create a light scene node, let it fly around, and, to make it look cooler, attach a billboard scene node to it:

// create light

node = smgr->addLightSceneNode(0, core::vector3df(0,0,0),
             video::SColorf(1.0f, 0.6f, 0.7f, 1.0f), 600.0f);
scene::ISceneNodeAnimator* anim = 0;
anim = smgr->createFlyCircleAnimator(core::vector3df(0,150,0),
                                         250.0f);
node->addAnimator(anim);
anim->drop();

// attach billboard to light

node = smgr->addBillboardSceneNode(node, core::dimension2d<f32>
                                  (50, 50));
node->setMaterialFlag(video::EMF_LIGHTING, false);
node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
node->setMaterialTexture(0,driver->getTexture("particlewhite.bmp"));

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read