Your message has been sent.
This article has been saved to your account.
Go to my account
This article has been emailed to your Kindle.
Send this article
Complete the form below to send this article, Irrlicht: Creating a Basic Template Application, to a friend (or to yourself). We will never share your details (or your friend's) with anyone. For more information, read our Privacy Policy.
Irrlicht is an open source technology that is used to create 2D and 3D applications.
In this article by Aung Sithu Kyaw and Johannes Stein, authors of Irrlicht 1.7 Realtime 3D Engine, we will:
- Create a new empty project
- Explain the use of an Irrlicht device
- Use the "game loop"
So let's get on with it...
(For more resources related to this topic, see here.)
Creating a new empty project
Let's get started by creating a new project from scratch. Follow the steps that are given for the IDE and operating system of your choice.
Visual Studio
Open Visual Studio and select File | New | Project from the menu. Expand the Visual C++ item and select Win32 Console Application. Click on OK to continue:

In the project wizard click on Next to edit the Application Settings. Make sure Empty project is checked. Whether Windows application or Console application is selected will not matter. Click on Finish and your new project will be created:

Let's add a main source file to the project. Right-click on Source Files and select Add New Item...|. Choose C++ File(.cpp) and call the file main.cpp:

CodeBlocks
Use the CodeBlocks project wizard to create a new project as described in the last chapter. Now double-click on main.cpp to open this file and delete its contents. Your main source file should now be blank.
Linux and the command line
Copy the make file of one of the examples from the Irrlicht examples folder to where you wish to create your new project. Open the make file with a text editor of your choice and change, in line 6, the target name to what you wish your project to be called.
Additionally, change, in line 10, the variable IrrlichtHome to where you extracted your Irrlicht folder. Now create a new empty file called main.cpp.
Xcode
Open Xcode and select File | New Project. Select Command Line Tool from Application. Make sure the type of the application is set to C++ stdc++:

When your new project is created, change Active Architecture to i386 if you are using an Intel Mac, or ppc if you are using a PowerPC Mac.
Create a new target by right-clicking on Targets, select Application and click on Next. Target Name represents the name of the compiled executable and application bundle:

The target info window will show up. Fill in the location of the include folder of your extracted Irrlicht package in the field Header Search Path and make sure the field GCC_ PREFIX_HEADER is empty:

Right-click on the project file and add the following frameworks by selecting Add Existing Frameworks...|:
- Cocoa.framework
- Carbon.framework
- IOKit.framework
- OpenGL.framework
Now, we have to add the static library named libIrrlicht.a that we compiled in Chapter 1, Installing Irrlicht. Right-click on the project file and click on Add | Existing Frameworks.... Now click on the button Add Other... and select the static library.
Delete the original compile target and delete the contents of main.cpp.
Time for action – creating the main entry point
Now that our main file is completely empty, we need a main entry point. We don't need any command-line parameters, so just go ahead and add an empty main() method as follows:
int main()
{
return 0;
}
If you are using Visual Studio, you need to link against the Irrlicht library. You can link from code by adding the following line of code:
#pragma comment(lib, "Irrlicht.lib")
This line should be placed between your include statements and your main() function.
If you are planning to use the same codebase for compiling on different platforms, you should use a compiler-specific define statement, so that this line will only be active when compiling the application with Visual Studio.
#if defined(_MSC_VER)
#pragma comment(lib, "Irrlicht.lib")
#endif
(For more resources related to this topic, see here.)
Using Irrlicht namespaces
The Irrlicht 3D graphics engine is structured into different namespaces. Let's take a look at them:
|
Namespace |
Description |
|
irr |
Everything in the Irrlicht 3D graphics engine is to be found in the irr namespace. |
|
core |
The irr::core namespace contains basic data types like vectors, lists, and arrays. |
|
scene |
The scene namespace-as the name suggests-covers everything that has to do with scene management. |
|
video |
Anything that has to do with 2D and 3D rendering or accessing the video driver is found in the video namespace. |
|
io |
If you would need to load or save data from files such as XMLs or packaged archives from your local hard drive, you would need to use methods from the io namespace. |
Make sure to add: #include
And to make the function calls shorter, we'll add the following using directives to the previously mentioned namespaces. This way we don't need to specify the namespace whenever we want to call a function from that namespace:
using namespace irr;
using namespace core;
using namespace video;
But you should be aware that using such a using namespace is considered bad practice according to some coding standards. Because exposing all the names from the root namespace can cause some confusions, for example, what if two different namespaces contain a function with the same name? That's why using only the top-level namespace is encouraged and the low-level namespace developers should use the full qualified name. But in this chapter, we'll just use this way to make our code shorter.
Irrlicht device
The Irrlicht device is the core object that we need to interact with the Irrlicht engine. It is created using the device driver of choice such as Direct3D, OpenGL, and so on. Basically, it's an interface to the actual underlying graphics hardware. So, we need to create a device first to be able to draw anything on the screen.
Time for action – creating an Irrlicht device
Creating a device in Irrlicht is as easy as calling a single function. If you have prior experience with graphics APIs such as Direct3D or OpenGL, you will know there's a lot of code involved to set up and create a device. So let's create an Irrlicht device.
- Go into your main() function.
- Define a variable called device by writing IrrlichtDevice* device.
- Create our Irrlicht device by calling:
createDevice(EDT_OPENGL, dimension<u32>(640, 480), 16, false,
false, false, 0); - Add the condition if (!device) return 1; immediately after that.
- Finally we need to release our device with device->drop();.
#include <irrlicht.h>
using namespace irr;
using namespace core;
using namespace video;
#if defined(_MSC_VER)
#pragma comment(lib, "Irrlicht.lib")
#endif
int main()
{
IrrlichtDevice* device = createDevice(EDT_OPENGL,
dimension2d<u32>
(640, 480), 16,
false, false, false, 0);
if (!device)
return 1;
device->drop();
return 0;
}
What just happened?
At the moment, a new window with the specified parameters of createDevice will be created, but will be instantly closed. If there is a problem with the created device, the application will receive the return 1 code.
The Irrlicht device handles everything that has to do with creating and using the window that we need to draw anything on the screen.
The createDevice method
The createDevice has seven parameters. The first one is the renderer that we will be using. Because we want our application to be platform-independent, we are going to use OpenGL, which is available for Windows, Linux, and Mac OS X.
You can also use the DirectX 8 renderer with EDT_DIRECT3D8 or the DirectX 9 renderer with EDT_DIRECT3D9 on Windows. Irrlicht also provides two software renderers that are EDT_ SOFTWARE and EDT_BURNINGSVIDEO. If the first parameter is set to EDT_NULL, there won't be any window created.
The second parameter sets the window size, while the third parameter sets the color depth, which should be set to either 16 bit or 32 bit. If the application is going to be run in windowed mode, this parameter might be ignored and the color depth of the created window will be set to the depth of the desktop.
The fourth parameter determines whether or not the application should run in windowed or fullscreen mode. If the parameter is set to true the application will launch in fullscreen mode. If this is the case the sixth parameter is a boolean flag that can switch vertical synchronization (vsync) on or off.
The fifth parameter specifies whether to use the stencil buffer or not. If we would need to draw shadows, we need to set this parameter to true, but for now, we can leave this to false.
The seventh parameter should be used if we are going to use an event receiver; that does not interest us yet.
The "game loop"
You already know while and for loops, so what's the deal with this alleged "game loop"? In game development, we usually have a scene that needs to be updated in every frame. We would need to check for game logic events, like checking for collisions or if the player has won or lost the game then update the scene accordingly. The Irrlicht 3D graphics engine uses the same approach. Assume your application is like an interactive movie, each frame redraws the complete screen.
Time for action – creating the "game loop"
Let's create our game loop:
- The "game loop" is a simple while loop. We will have to redraw each frame as long as the device is running.
- Define the variable IVideoDriver* driver and allocate device- >getVideoDriver().
- Now jump to the "game loop".
- Add driver->beginScene(true, true, SColor(255, 255, 255, 255)); at the beginning of the loop.
- Add driver->endScene(); at the end of the loop.
Your source code should look something like this:
#include <irrlicht.h>
using namespace irr;
using namespace core;
using namespace video;
#if defined(_MSC_VER)
#pragma comment(lib, "Irrlicht.lib")
#endif
int main()
{
IrrlichtDevice* device = createDevice(EDT_OPENGL,
dimension2d<u32>
(640, 480), 16,
false, false,
false, 0);
if (!device)
return 1;
IVideoDriver* driver = device->getVideoDriver();
while (device->run())
{
driver->beginScene(true, true, SColor(255, 255, 255,
255));
driver->endScene();
}
device->drop();
return 0;
}You should see a blank window created as follows, if it runs successfully:

What just happened?
We just succeeded in creating our first application with Irrlicht that displays a window with a plain white background. To be able to draw within our "game loop", we need to get information about the video driver we are using. To save us some work, by not having to write device->getVideoDriver() each time, we would need something from the video driver; we define a variable that gets an instance from the video driver. You may have noticed the I in front of the type IVideoDriver tells you that this type is an interface. Irrlicht relies heavily on interfaces to be able to use different renderers under a common API.
beginScene
Drawing graphics to the display screen directly, every time, can cause the flickering artifact. To avoid this problem a method called double buffering is widely used. The idea is to use a secondary back buffer before drawing to the actual screen. So the renderer will draw on that back buffer first. Only once the drawing is finished, it'll flip the back buffer with the front buffer. The first parameter of beginScene method specifies if the back buffer should be cleared and set to true by default. The second parameter specifies whether to clear the Z buffer.
The third parameter is the color that will be used to clear the back buffer. The color type consists of four values alpha, red, green, and blue ranging from 0 to 255.
This method has to be called first before any rendering occurs.
endScene
The endScene method flips the screen buffers and draws everything on the screen.
Have a go hero – creating the fade-in/fade-out effect
Now that we have set up our base application with a white background, let's try to integrate a fade-in and fade-out effect into our application. If the background is white, we want to slowly fade to a black background and vice versa. So basically, you'll have to play around with the color values inside your game loop.
You figured it out? Compare it with this approach:
#include <irrlicht.h>
using namespace irr;
using namespace core;
using namespace video;
#if defined(_MSC_VER)
#pragma comment(lib, "Irrlicht.lib")
#endif
int main()
{
IrrlichtDevice *device = createDevice(EDT_OPENGL,
dimension2d<u32>
(640, 480), 16, false,
false, false, 0);
if (!device)
return 1;
IVideoDriver* driver = device->getVideoDriver();
f32 bg_r = 255.0f;
f32 bg_g = 255.0f;
f32 bg_b = 255.0f;
bool fadeOut = true;
int lastFPS = -1;
u32 then = device->getTimer()->getTime();
const f32 fadeRate = 0.1f;
while(device->run())
{
const u32 now = device->getTimer()->getTime();
const f32 frameDeltaTime = (f32)(now - then);
then = now;
if (bg_r <= 0.0f) fadeOut = false;
else if (bg_r >= 255.0f) fadeOut = true;
if (fadeOut)
{
bg_r-= fadeRate * frameDeltaTime;
bg_g-= fadeRate * frameDeltaTime;
bg_b-= fadeRate * frameDeltaTime;
}
else
{
bg_r+= fadeRate * frameDeltaTime;
bg_g+= fadeRate * frameDeltaTime;
bg_b+= fadeRate * frameDeltaTime;
}
driver->beginScene(true, true, SColor(255, (u32)bg_r,
(u32)bg_g, (u32)bg_b));
driver->endScene();
}
device->drop();
return 0;
}
However, the preceding approach contains a new concept that is called frame independent update. Before starting any rendering, we calculate the total time (ticks) difference between each frame, and multiply that with the rate we want to use for fade-in, fade-out. This way we can achieve a smooth transition across different PCs. Otherwise, if you just use a constant value to subtract or add to the color values, your program will fade-in/out very fast on fast computers.
Summary
We set up our development environment and created our first application.
Specifically, we covered:
- Creating an empty application using different platforms and IDEs
- Irrlicht namespaces
- Creating and using a device
- Introduction of the frame independent update concept
Further resources on this subject:
- Starting Ogre 3D [Article]
- Ogre 3D: Double Buffering [Article]
- Materials with Ogre 3D [Article]
- The Ogre Scene Graph [Article]
About the Author :
Aung Sithu Kyaw
Mr. Aung Sithu Kyaw is originally from Myanmar (Burma). He has been a developer in software development industry for over seven years and has a great passion in graphics programming, creating video games, writing and sharing knowledge with others. He holds a Master of Science from Nanyang Technological University (NTU), Singapore majoring in Digital Media Technology. Over the past years he had worked as Research Programmer at INSEAD, Sr. Game Programmer at Playware Studios Asia, Singapore and lastly Research Associate at NTU which involves implementing sensor based real-time movie system based on Unreal Development Kit.
Aung is currently the CEO of Rival Edge Pte Ltd, Singapore which he founded in 2011 with two other co-founders. The company focuses in interactive digital media industry with two primary operations: back-end technology development and contents production. The company's flagship product is a cross-platform social game API which is currently in beta stage, more information at http://rivaledge.sg.
He can be followed on twitter @aungsithu and LinkedIn profile linkedin.com/in/aungsithu.
Johannes Stein
Johannes Stein is currently a student at the University of Augsburg in Germany. He began showing an interest in computers and developing for the PC platform when he was just 12-13 years old. After learning Visual Basic and Delphi he eventually got into C/C++, C# as well as some scripting languages.
He specializes in game development, cross-platform applications which run on Windows, Linux and Mac OS X, 3D graphics modeling, applications for mobile devices and web development with HTML, CSS and JavaScript using the latest HTML5 technologies.



Post new comment