SDL2 with OpenGL

Ever since SDL developer joined Valve and revamped most of its source code, SDL 2 has been seen by many as the game changer that will reshape the linux (and Mac OSX) gaming scene by allowing developers to easily port their games to these platforms.

Although there are some other APIs that are equally portable, but none of them are supported by big company with strong financial muscle and development experience like Valve. The major advantage of SDL being used by a company that has had countless experience developing AAA titles is that they can help avoiding ideas that sound good only on paper but not working quite well when applied to real world problems. This is why I think SDL 2 is a library worth studying for long term benefit.

In this tutorial, I’m going to directly use the OpenGL for rendering, instead of using SDL’s own renderer, because OpenGL works better in term of performance and flexibility. You can develop both 2D/3D games with OpenGL but only 2D if you use SDL renderer.

So let’s get it started by opening your favorite C/C++ IDE, which in my case, the Code::Blocks. You have to link your project to several libraries such as OpenGL, GLEW and SDL2. GLEW is basically a library that makes your life easier for connecting to OpenGL extensions. Different IDE has different approach in linking to external libraries, so I will not be explaining it here. Check out other tutorials that are related to your choice of IDE.

Let’s start writing some code. First of all, you need to link all the relevant header files to your main source file, using the #include macro. Notice we used #define GLEW_STATIC before #include <GL/glew.h> in-order to build GLEW statically into your project. Without the macro, you need to provide the dynamic library file for the compiler.

// OpenGL headers
#define GLEW_STATIC
#include &lt;GL/glew.h&gt;
#include &lt;GL/glu.h&gt;
#include &lt;GL/gl.h&gt;

// SDL headers
#include 
#include 
#include 

Next, define all the necessary variables, in this case, a boolean which determines whether the game is still running or not, as well as other pointers/references that are linked to the SDL window, OpenGL context, and SDL event.

bool quit;

SDL_Window* window;
SDL_GLContext glContext;
SDL_Event sdlEvent;

After that, let’s move on to the main() function. Here we define the quit variable as false, so that later on we can use it for the game loop and keep the game running without closing. We also set the OpenGL’s context to 3.1 core profile. Do notice that in version 3.1 above, the fixed-function pipeline is completely deprecated, so you need to be careful when picking the right context for your OpenGL renderer.

int main(int argc, char *argv[])
{
    quit = false;

    //Use OpenGL 3.1 core
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
}

Next, we call SDL_Init(SDL_INIT_VIDEO) to initiate SDL. If the result returned by the function is -1, it means something is going wrong and you should stop immediately. Otherwise, you are good to go and start creating the rendering window using SDL_CreateWindow(). There are several inputs for this functions, such as:

1. Title
2. Horizontal position
3. Vertical position
4. Width
5. Height
6. Flags

We need to specifically set the type of window as OpenGL rendering window using the SDL_WINDOW_OPENGL flag. Otherwise, SDL will not be able to use OpenGL to do the rendering.

After we have created a window, use it to create the OpenGL context by calling SDL_GL_CreateContext(window). Call glewInit() to automatically load all the relevant extensions based on the OpenGL context you have just set.

// Initialize video subsystem
if(SDL_Init(SDL_INIT_VIDEO) &lt; 0)
{
    // Display error message
    printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
    return false;
}
else
{
    // Create window
    window = SDL_CreateWindow("Hello World!", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN );
    if( window == NULL )
    {
        // Display error message
        printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
        return false;
    }
    else
    {
        // Create OpenGL context
        glContext = SDL_GL_CreateContext(window);

        if( glContext == NULL )
        {
            // Display error message
            printf( "OpenGL context could not be created! SDL Error: %s\n", SDL_GetError() );
            return false;
        }
        else
        {
            // Initialize glew
            glewInit();
        }
    }
}

You have now created an empty window that doesn’t render anything and will be closed once it’s being launched. This happen because we have not yet created the game loop for it. A game loop is basically a while loop that keeps on running repeatedly until the user closes the application. In gaming term, each loop is called a “frame” or a “tick”. Graphics will be rendered and displayed on the screen for several times a second, hence the term for measuring the rate of rendering is called “frame-per-second”.

To create the game loop, we will be using the quit variable that we have defined previously. If the variable quit is true, the window will never be closed and keep the rendering going. Within the game loop, we detect the keyboard event and check if player has pressed the Escape button. If the Escape button is pressed, set quit as true and the application will then be closed.

We also set the background color as cornflower blue, and then ask OpenGL to start rendering the scene by swapping the render buffer. We don’t have anything to be rendered for now so you will just see a blue color background.

// Game loop
while (!quit)
{
    while(SDL_PollEvent(&amp;sdlEvent) != 0)
    {
        // Esc button is pressed
        if(sdlEvent.type == SDL_QUIT)
        {
            quit = true;
        }
    }

    // Set background color as cornflower blue
    glClearColor(0.39f, 0.58f, 0.93f, 1.f);
    // Clear color buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    // Update window with OpenGL rendering
    SDL_GL_SwapWindow(window);
}

Lastly, we need to clean everything up if the variable quit is set to true and breaks the game loop. It’s important to quit the application neatly! Destroy the rendering window properly by calling SDL_DestroyWindow(window), then clear the window pointer from the memory by setting the pointer to NULL, and lastly call SDL_Quit() to make sure SDL quits properly.

//Destroy window
SDL_DestroyWindow(window);
window = NULL;

//Quit SDL subsystems
SDL_Quit();

return 0;

For those who are lazy, this is the full source code:

// OpenGL headers
#define GLEW_STATIC
#include &lt;GL/glew.h&gt;
#include &lt;GL/glu.h&gt;
#include &lt;GL/gl.h&gt;

// SDL headers
#include 
#include 
#include 

bool quit;

SDL_Window* window;
SDL_GLContext glContext;
SDL_Event sdlEvent;

int main(int argc, char *argv[])
{
    quit = false;

    //Use OpenGL 3.1 core
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

    // Initialize video subsystem
    if(SDL_Init(SDL_INIT_VIDEO) &lt; 0)
    {
        // Display error message
        printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
        return false;
    }
    else
    {
        // Create window
        window = SDL_CreateWindow("Hello World!", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN );
        if( window == NULL )
        {
            // Display error message
            printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
            return false;
        }
        else
        {
            // Create OpenGL context
            glContext = SDL_GL_CreateContext(window);

            if( glContext == NULL )
            {
                // Display error message
                printf( "OpenGL context could not be created! SDL Error: %s\n", SDL_GetError() );
                return false;
            }
            else
            {
                // Initialize glew
                glewInit();
            }
        }
    }

    // Game loop
    while (!quit)
    {
        while(SDL_PollEvent(&amp;sdlEvent) != 0)
        {
            // Esc button is pressed
            if(sdlEvent.type == SDL_QUIT)
            {
                quit = true;
            }
        }

        // Set background color as cornflower blue
        glClearColor(0.39f, 0.58f, 0.93f, 1.f);
        // Clear color buffer
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        // Update window with OpenGL rendering
        SDL_GL_SwapWindow(window);
    }

    //Destroy window
    SDL_DestroyWindow(window);
    window = NULL;

    //Quit SDL subsystems
    SDL_Quit();

    return 0;
}

Change Unity3D Build Target Using CMD

Most people probably won’t need this, unless you encountered such scenario:

You're handling a huge project, and you somehow need to move the entire project folder from a Windows machine to a Mac for porting the project to iOS.
What will happen is when you open the project for the first time on Mac, Unity will load all the files and convert them into Windows formats because well, your project was set to run on Windows previously.
You waited for half an hour or so for all the files to be converted (it' a huge project!) and now you must change the build settings again, and wait for another half an hour for it to be converted to iOS!

If you want to avoid running the conversion twice, you can change your Unity project’s build target before opening the editor, by using the command prompt, like so:

Windows:

"C:\Program Files(x86)\Unity\Editor\Unity.exe" -buildTarget 

Mac:

/Applications/Unity/Unity.app/Contents/MacOS/Unity -buildTarget

Possible options are: win32, win64, osx, osxintel64, osxuniversal, linux, linux64, linuxuniversal, ios, android, web, webstreamed, webgl, xbox360, xboxone, ps3, ps4, psp2, wsa, wp8, bb10, tizen, samsungtv

For example:

"C:\Program Files (x86)\Unity\Editor\Unity.exe" -buildTarget ios

This way, Unity will straight away convert your project files to iOS formats and no need to convert it twice. Time saved!

View Debug Messages on Android

If you’re currently developing any android apps, you might be wondering how to check debug messages when running the apps on a physical device. Android SDK actually comes with an utility called Logcat, which does exactly that.

If you’re running Eclipse IDE and it is not showing any debug messages, your Eclipse is probably not linked to the Logcat. You can set it up by going to:

Window -> Show View -> Other… -> Android -> LogCat

However, if you’re running other development tools that don’t support this feature (such as Unity Engine), you can fire up Logcat manually by using the command pad/terminal.

On Windows, you need to enter the (android sdk folder)\platform-tools folder before calling Logcat:

cd C:\android-sdk-windows\platform-tools

After that, you can call Logcat by first calling the ADB (Android Debug Bridge) and launch Logcat from it, like so:

adb logcat

However, if you’re just calling adb logcat you may see the terminal going crazy by showing tons of debug texts in crazy speed. This is because the Logcat is actually displaying debug texts of ALL the processes running on your device. You definitely do not want that, don’t you?

You can add an extra parameter behind the command which filters out the process list and only display your app. For example, if your app is built using Unity Engine, you can call:

adb logcat -s Unity

…which looks like this on the terminal:

That’s all. You can now easily debug your app and know exactly what’s going when bugs occur. Happy debugging!

Exposing QML Object Pointer to C/C++

Sometimes, for whatever reason, we want to modify the properties of a QML object through C/C++ scripting. Qt’s QML engine actually supports this and it allows you to register your QML objects as C/C++ types, however, this is often not well-explained.

For example, I created a label in QML and I want to change its text occasionally. In order for me to expose the label object to C/C++, I created a C/C++ class called MyClass which extended from QObject class.

myclass.h:

class MyClass : public QObject
{
    Q_OBJECT
public:
    // Object pointer
    QObject* myObject;
    
    explicit MyClass(QObject *parent = 0);
    
    // Must call Q_INVOKABLE so that this function can be used in QML
    Q_INVOKABLE void SetMyObject(QObject* obj);
}

In myclass.cpp source file, I defined a function called SetMyObject() to save the object pointer. This function will later be called in QML.

myclass.cpp:

void MyClass::SetMyObject(QObject* obj)
{
     // Set the object pointer
     myObject = obj;
}

After that, in main.cpp, include MyClass header and register it to QML engine using the function qmlRegisterType():

main.cpp:

#include "myclass.h"

int main(int argc, char *argv[])
{
     // Register your class to QML
     qmlRegisterType<MyClass>("MyClassLib", 1, 0, "MyClass");
}

Notice there are 4 parameters you need to declare in qmlRegisterType(). Besides declaring your class name (i.e. MyClass), you also need to declare your library name (i.e. MyClassLib) and its version (i.e. version 1.0), which will be used for importing your class to QML later on.

Now that QML engine is fully aware of my custom class, I can then map it to my label object in QML. First off, in my QML file, I imported my class library by calling import MyClassLib 1.0. Notice that the library name and its version number have to be matching with the one you declared in main.cpp, otherwise it will throw you an error.

After declaring MyClass in QML (and set its id as myclass), I then call myclass.SetMyObject(myLabel) to expose the label’s pointer to C/C++ right after the label is being initialized:

import MyClassLib 1.0

ApplicationWindow
{
     id: mainWindow
     width: 480
     height: 640
     
     MyClass
     {
          id: myclass
     }

     Label
     {
          id: myLabel
          text: qsTr("Hello World!")
          Component.onCompleted:
          {
               myclass.SetMyObject(myLabel);
          }
     }
}

Please be aware that you need to wait until the label is fully initiated before exposing its pointer to C/C++, otherwise you may cause the program to crash. To make sure it’s fully initiated, call SetMyObject() within Component.onCompleted and not other places.

Now that the QML label is being exposed to C/C++, I can do whatever I want to the label. For instance, I can set its visibility to true and change its text to “Bye bye world!”:

// QVariant automatically detects your data type
myObject->setProperty("visible", QVariant(true));
myObject->setProperty("text", QVariant("Bye bye world!"));

Besides changing the properties, I can also call its functions by calling QMetaObject::invokeMethod():

QVariant returnedValue;
QVariant message = "Hello world!";

QMetaObject::invokeMethod(myObject, "myQMLFunction",
    Q_RETURN_ARG(QVariant, returnedValue),
    Q_ARG(QVariant, message));

qDebug() << "QML function returned:" << returnedValue.toString();

…or simply:

QMetaObject::invokeMethod(myObject, "myQMLFunction");

That’s all for this tutorial. If you have any problem please feel free to leave a comment below. Happy coding!

Application Development with Qt Creator Second Edition

Application Development with Qt Creator Second Edition” is the 3rd book I reviewed for Packt Publishing. Although it’s the second edition, the contents of the book are greatly varied from its predecessor.

First off, it has more chapters compare to the first edition, bringing more contents to the readers especially topics related to Qt Quick. The book also included some pretty fun projects for readers to work on such as media player and simple paint program.

The book also covers some of the fundamental and important topics such as localization, software optimization, and debugging which are needed to develop industry-standard applications.

Let’s take a look at the chapter outline:

Chapter 1
Getting Started with Qt Creator, shows you how to download and install Qt Creator as well as edit simple applications to test your installation.

Chapter 2
Building Applications with Qt Creator, shows you how to compile, run, and debug your application using Qt Creator. You will learn how Qt Creator integrates with both the GNU debugger and the Microsoft console debugger to provide breakpoints, memory inspection, and other debugging help.

Chapter 3
Designing Your Application with Qt Designer, shows you how to use the drag-and-drop GUI designer that is a part of Qt Creator to build both Qt Widget-based applications and Qt Quick applications.

Chapter 4
Qt Foundations, takes you through the foundations of software development using Qt and also covers its support for platform-agnostic application development.

Chapter 5
Developing Applications with Qt Widgets, shows you how to build applications using Qt Widgets that look and act like native desktop applications on the platform of your choice.

Chapter 6
Drawing with Qt, shows the various ways you can move beyond the built-in controls in Qt and make your own drawing on the screen and other drawable entities such as image files in PNG or JPEG.

Chapter 7
Doing More with Qt Quick, expands on what you learned about Qt Quick in the introductory chapters.

Chapter 8
Multimedia and Qt Quick, introduces you to Qt Quick’s support for multimedia, such as audio and video playback as well as how to use a camera if it is connected.

Chapter 9
Sensors and Qt Quick, shows you how to use the various sensors on many of the devices available today using Qt Quick.

Chapter 10
Localizing Your Application with Qt Linguist, shows you how to manage resource strings for different locales, letting you build your application with different languages in different locales.

Chapter 11
Optimizing Performance with Qt Creator, shows you how to use Qt Creator to examine your Qt Quick application’s runtime performance, as well as how to perform the memory profiling of your application with Valgrind, an open source diagnostic tool.

Chapter 12
Developing Mobile Applications with Qt Creator, gives you a glimpse of the exciting arena of mobile software development and shows you how you can use what you’ve learned in this book about Qt and Qt Creator to write applications for platforms such as Google Android.

Chapter 13
Qt Tips and Tricks, is packed with tricks for using Qt and Qt Creator that will help you use the Qt framework and the Qt Creator IDE efficiently.

You can get the book from here.