Getting Started with OpenGL ES 3+ Programming by Hans de Ruiter - HTML preview

PLEASE NOTE: This is an HTML preview only and some elements such as links or page numbers may be incorrect.
Download the book in PDF, ePub, Kindle for a complete version.

Tutorial 1: Getting Started

This tutorial we’ll be setting up our development environment, and creating a basic GLES3 app. It won’t do much; just open a window and clear it to black. The goal is simply to get something basic working.

  1. Setting Up the Development Environment

To write GLES3 + SDL2 apps we need a suitable development environment (dev-environment) that allows us to write code and compile it. There are two parts to this. First, we need to install the code editor and compiler. Second, most dev-environments don’t come with GLES3 and SDL2 support out of the box. Their dev-files need to be installed before we can use them.

NOTE: This tutorial currently only covers using Visual Studio on Windows. Don’t worry about developing for mobile devices yet; just get the basics working on your desktop computers. If you’re using MacOS X or some other platform then search the internet for how you set up a compiler (e.g., here’s one for SDL2 on MacOS X: http://lazyfoo.net/tutorials/SDL/01_hello_SDL/mac/index.php).

  1. Setup on Windows

Microsoft provide a comprehensive dev-environment called Visual Studio. So download that now from: https://www.visualstudio.com/downloads/

IMPORTANT: Download the free Visual Studio Community edition. The free version provides all that you need.

Start the Visual Studio installer, and select the “Custom,” (Figure 1).

Image

Figure 1: Choose the custom installation type.

Image

Figure 1: Choose the custom installation type.

Click the “Next” button. Next, make sure that you’re installing Visual C++ (see Figure 2).

Image

Figure 2: Select the features to install.

Image

Figure 2: Select the features to install.

With this done, click “Next,” then “Install,” and wait for the installer to complete.

  1. Installing the GLES3 & SDL2 Development Files

On Windows you need two sets of dev-files:

The setup process is currently rather tedious, so I’ve created a template that does it all for you. Download the template from: https://keasigmadelta.com/assets/GLTutorials/GLES3SDL2-Application.zip

To install the template, copy the downloaded file to: “<My Documents folder>\Visual Studio 2015\Templates\ProjectTemplates\Visual C++ Project” (see Figure 3).

Image

Figure 3: The template is installed by copying it to the project templates folder.

Image

Figure 3: The template is installed by copying it to the project templates folder.

  1. Create a New Project

Now we can create our project. In Visual Studio, select File => New => Project from the menu. Select the “GLES3SDL2 Application” template, and call the project something like “GLTutorial1” (Figure 4). After clicking “OK” it’ll create the new project.

Image

Figure 4: Create a new project using the GLES2SDL2 Application template.

Image

Figure 4: Create a new project using the GLES2SDL2 Application template.

Next, right-click on the new “GLTutorial1” project in the Solution Explorer (on the left) and select build. With the first build it’ll set up SDL2 and Angle within the project. The Angle files are in a self-extracting archive. It’ll pop up a window asking you where to put it (Figure 5). Simply click the Extract button.

Image

Figure 5: Click Extract to unpack the Angle files.

Image

Figure 5: Click Extract to unpack the Angle files.

 

NOTE: Visual Studio’s editor may claim it can’t find “SDL.h” despite having installed the SDL2 package during the initial build. Simply close and reopen the project/solution (File => Close Solution, followed by File => Recent Projects and Solutions => GLTutorial1.sln).

  1. Our First GLES3 & SDL2 Program

Right! Let’s get into actual coding, and write our first GLES3 + SDL program. In the solution explorer (left column), open Main.cpp. You’ll find it under GLTutorial1 => Source Files. Delete the existing code, and start writing.

IMPORTANT: As mentioned in the How to Get the Most Out of These Tutorials section (on page 6), it’s highly recommended that you type out the code by hand instead of copying and pasting. You’ll learn/remember more if you do it that way.

  1. Headers and Definitions

We’ll start by including the header files for libraries we’re using (SDL2 & OpenGL). Here’s the code:

// Basic OpenGL ES 3 + SDL2 template code

 

#include <SDL.h>

#include <SDL_opengles2.h>

#include <GLES3/gl3.h>

#include <cstdio>

#include <cstdlib>

 

Next, comes a few constants for the window’s dimensions:

const unsigned int DISP_WIDTH = 640;

const unsigned int DISP_HEIGHT = 480;

 

  1. SDL and OpenGL Initialization

Its time to set up SDL and create a window with an OpenGL ES 3 context. This is the start of your program. With SDL, the main entry point is SDL_main(). This is optional, but worth using because it hides the difference between main() & WinMain() (or whatever special main entry point an OS may have). Anyway, SDL is initialized as follows (put this directly below the headers and definitions):

int SDL_main(int argc, char *args[]) {

    // The window

    SDL_Window *window = NULL;

 

    // The OpenGL context

    SDL_GLContext context = NULL;

 

    // Init SDL

    if (SDL_Init(SDL_INIT_VIDEO) < 0) {

        SDL_Log("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());

        return EXIT_FAILURE;

    }

 

    // Setup the exit hook

    atexit(SDL_Quit); 

 

Notice that we’re only initializing SDL’s video subsystem in the SDL_Init() call:

    if (SDL_Init(SDL_INIT_VIDEO) < 0) {

 

SDL has other sub-systems such as audio and joystick input, but we’re not using any of them.

Next, we request OpenGL ES 3.0, and double-buffering:

    // Request OpenGL ES 3.0

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);

 

    // Want double-buffering

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

 

Double-buffering is a technique whereby we render to an invisible back-buffer and then flip the buffers round to show it. Rendering directly to the screen runs the risk that partially rendered images are shown. We definitely don’t want that because it’s ugly.

  1. Opening the Window

With base initialization done, we can now open the window and set up the OpenGL context:

    // Create the window

    window = SDL_CreateWindow("GLES3+SDL2 Tutorial", SDL_WINDOWPOS_UNDEFINED,

        SDL_WINDOWPOS_UNDEFINED, DISP_WIDTH, DISP_HEIGHT,

        SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);

    if (!window) {

        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",

        "Couldn't create the main window.", NULL);

        return EXIT_FAILURE;

    }

 

    context = SDL_GL_CreateContext(window);

    if (!context) {

        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",

        "Couldn't create an OpenGL context.", NULL);

        return EXIT_FAILURE;

    }

 

The code above has two steps; create the window (SDL_CreateWindow()), and create the OpenGL context (SDL_GL_CreateContext()). Everything else is error handling. If you wish to use OpenGL then it’s very important to pass SDL_CreateWindow() the SDL_WINDOW_OPENGL flag. Otherwise the SDL_GL_CreateContext() call will fail.

  1. Draw Something

Yes, it’s finally time to draw something! Okay, all we’re going to do this tutorial is clear the screen, but it’ll still be an OpenGL draw operation nonetheless. Clearing to black is done as follows:

    // Clear to black

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    glClear(GL_COLOR_BUFFER_BIT);

 

    // Update the window

    SDL_GL_SwapWindow(window);

 

GL_COLOR_BUFFER_BIT tells glClear() to only clear the screen/image (a.k.a., colour buffer). A context may also have depth/z and stencil buffers, and you may wish to clear one or more of them. The clear colour is, unsurprisingly, set by glClearColor(). Finally, SDL_GL_SwapWindow() swaps the buffers so that our new image is displayed. We enabled double-buffering (by passing SDL_GL_DOUBLEBUFFER to SDL_GL_SetAttribute()) so rendering is performed on an invisible back buffer. So the front and back buffers need to be swapped.

  1. Wait Until the User Wants to Quit

Normally a “real” OpenGL program would have a main loop that does things like respond to events and render animated graphics. Since this is a really basic program, all that’s needed is to wait for the user to click the window’s close button. SDL makes this relatively easy with its event handling functions:

    // Wait for the user to quit

    bool quit = false;

    while (!quit) {

        SDL_Event event;

        if (SDL_WaitEvent(&event) != 0) {

            if (event.type == SDL_QUIT) {

                // User wants to quit

                quit = true;

            }

        }

    }

 

    return EXIT_SUCCESS;

}

 

SDL_WaitEvent() stops the program until an event comes in. If the incoming event is an SDL_QUIT, then the code above exits the while loop, and quits.

  1. The Code in Full

Putting it all together, Main.cpp is:

// Basic OpenGL ES 3 + SDL2 template code

 

#include <SDL.h>

#include <SDL_opengles2.h>

#include <GLES3/gl3.h>

#include <cstdio>

#include <cstdlib>

 

const unsigned int DISP_WIDTH = 640;

const unsigned int DISP_HEIGHT = 480;

 

int SDL_main(int argc, char *args[]) {

    // The window

    SDL_Window *window = NULL;

 

    // The OpenGL context

    SDL_GLContext context = NULL;

 

    // Init SDL

    if (SDL_Init(SDL_INIT_VIDEO) < 0) {

        fprintf(stderr, "SDL could not initialize! SDL_Error: %s\n", SDL_GetError());

        return 10;

    }

 

    // Setup the exit hook

    atexit(SDL_Quit);

 

    // Request OpenGL ES 3.0

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);

 

    // Want double-buffering

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

 

 

    // Create the window

    window = SDL_CreateWindow("GLES3+SDL2 Tutorial", SDL_WINDOWPOS_UNDEFINED,

        SDL_WINDOWPOS_UNDEFINED, DISP_WIDTH, DISP_HEIGHT,

        SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);

    if (!