Introduction

In order to program in 3D, you need a 3D library. Sure, you could base your game of an already existing engine. But that’s not what this blog is about! Instead, we’ll
used a graphics library. The most common ones are OpenGL or DirectX.

Since DirectX is a Microsoft technology and only works under Windows, we will be using OpenGL. This means the applications we make will work on just about any operating system.

Note : I recommend that you read at least the first few parts of my SDL2 tutorial before continuing. My SDL2 tutorial will explain the SDL2 elements like SDL_Window in more detail. The first few parts are really short and should give you a basic understanding of SDL2

What is OpenGL

OpenGL is a specification or an abstract API if you will. It is not an actual implementation. It doesn’t do anything on its own. But rather, it just defines a lot of functions and data types that we can use in our program. Then it’s the job of the underlying implementation to actually do the job. This implementation is part of the graphics card driver. The means that the implementation varies from platform to platform. The Linux version is different from the Windows version. It’s also different based on the hardware. So a nVidia version is different from an ATI version.

We really won’t be giving this too much thought, we’ll only use the functions and types defined by the OpenGL specification. But it’s useful to know exactly what OpenGL is.

Old vs new

Back in the day, programming in OpenGL was tricky. Setting it up was a mess, you had several different libraries to keep track of like glu, glut and glew. I’m still not quite sure what all of them did. On top of that, the code itself was rather bad too. Really not intuitive and not as flexible as the new version. But after version 3.0 a lot changed. Lots of code was deprecated and lots of new stuff were added. So new we can write very simple and concise OpenGL that’s also multi platform.

GLEW

I briefly mentioned GLEW( OpenGL Extension Wrangler Library ) above as one of the libraries that made OpenGL confusing. But that’s really not GLEWs fault. GLEW is actually quite simple, it just lets us write OpenGL code in a simple, platform-independent way. We won’t be noticing it a lot, except for an init call, so there’s really no need to learn a lot about it. But it’s always nice to know what its there for.

OpenGL and SDL2

SDL2 makes setting up OpenGL really easy. You can use SDL2 to create your window and hook up a rendering context ( I’ll explain what a rendering context is later. ) If we didn’t do this using OpenGL we’d have to do it in different ways on different platforms. The code would get messy and really complicated. SDL2 lets us do all of this in a really simple way. I

Rendering context

A rendering context is a structure that keeps track of all of our resources, basically every thing we want to put on the screen. It also keeps some state like what version of OpenGL we are using and some other stuff. We need a rendering context before we can do any OpenGL stuff. A rendering context is connected to a window ( like SDL_Window ). It can be connected to just one window, several windows and a window can have several rendering contexts.

An SDL_Renderer is a kind of a rendering context, but SDL_Renderer only supports the SDL2 way of rendering, which is 2d. But now we want 3d, and it’s here that OpenGL comes in. SDL2 even has its own rendering context object, SDL_GLContext. We’ll see how to create it later.

Setting it up

Now let’s try to set up a simple OpenGL application. It won’t be much different from the first SDL2 application we made, the point is just to set up OpenGL.

First of all, if you haven’t already, you should set up SDL2. You can do this by following my guide.

Linux / Mac

If you’re on Linux or Mac, you don’t have to set up anything else. All you need is an extra compilation flag which I’ll show you later.

Windows

If you’re on Windows things are a little trickier.

2. Put the “glew.h” header file in a folder named “GL” in the same directory as you put the “SDL” folder
3. Put the “glew32d.lib” file in the directory you place “SDL.lib
4. In the Visual Studio -> Project Properties -> Linker -> Input add glew32d.lib;opengl32.lib;
• You also need SDL2.lib like in the guide, so your string should start with glew32d.lib;opengl32.lib;sdl2main.lib;sdl2.lib;
5. Puth the .dll in your project folder

That should be it. If you get the error 0xc000007b you’ve probably mixed up 32 / 64 bits lib or dll files.

Creating the window

The first part of the code should look very familiar to that of plain SDL2

In fact, the only new thing here is the SDL_WINDOW_OPENGL which tells SDL2 that we will be using this window for OpenGL and not SDL2.

Just like with plain SDL2, we end up with a SDL_Window. And now that we have created it, we just need to connect a rendering context to it.

Setting the variables

Before we create and connect the rendering context, we’ll set a few variables to tell SDL2 and OpenGL which version of OpenGL we want to use. To do this, we use the function SDL_GL_SetAttribute

Parameters :

• attr – the attribute we want to set.
• value – the value we want to set it to

For a list of all SDL_GLattrs, click here.

Return

0 on success, otherwise negative.

So now let’s use it to set a few variables :

Here we set SDL_GL_CONTEXT_PROFILE_MASK to SDL_GL_CONTEXT_PROFILE_CORE  This means that the old, deprecated code are disabled, only the newer versions can be used.

You can also use this to limit your application to which means your code will work on smart phones too. But it also means we’ll have less functionality, so we won’t be doing that.

Context version

Set up so that we use version 3.2 of OpenGL. We could set the number higher to use a new version, but your graphics card might not support that. This means we wont have access to all of OpenGL, but for now, 3.2 is sufficient for our needs.

Double-buffering

We need to tell OpenGL we want double-buffering. Which basically means that we draw to a hidden “screen” ( or buffer ) When we are done drawing to it, we swap the buffer we drew on with the buffer on the screen so that it becomes visible. Then we start drawing on the buffer we just swapped out ( which is now invisibe). This way, we never draw directly on the screen, making the game look a lot smoother

The buffer/screen we are drawing on is usually called the “back buffer” and the one on the screen is called the “front buffer”

Connecting a rendering context

Now that we’ve set up the properties, we need to connect our rendering context. Fortunately, SDL2 makes this really simple, all we need is the SDL_GL_CreateContext method :

Parameters :

• window – the SDL_Window we want the code>rendering context to connect to.

Return

A valid SDL_GLContext on succes, otherwise NULL.

Initializing GLEW

After initializing SDL2 we need to initialize GLEW so that it can take care of our OpenGL calls. There is a two steps to this :

This tells OpenGL that we want to use OpenGL 3.0 stuff and later.

Depending on your graphics card driver, some functions might not be available through the standard lookup mechanism. This means that GLEW can’t find it for us, and the application will crash. glewExperimental enables us to use functionality. So there might be functions that exists, are valid and will work, but the isn’t normally available. glewExperimental tells GLEW that we want to use these functions as well.

A side note : in my experience, this is needed even when using very basic OpenGL stuff, so it’s possible that some graphics card drivers report a lot of functions as experimental resulting in the need for glewExperimental = GL_TRUE

As you probably guessed, this simply initializes GLEW so that it can take care of looking up functions for us. And that’s really all we need as far as GLEW goes.

Drawing stuff

Finally, let’s use OpenGL to draw something. I’ll just cover the very basics in this part, more interesting stuff next time!

OpenGL and colors

For the most part, OpenGL uses float values for colors. So instead of 255 being “max color”, 1.0 is max color. So means no color and 0.5 means 50 % color ( same as 255 / 2 = 127 in SDL2)

glClearColor

In order to clear the screen with a single color, we first need to set which colors to clear it with. For that, we can use glClearColor.

Parameters :

• red – the amount of red ( 0.0 – 1.0 ).
• green – the amount of green ( 0.0 – 1.0 ).
• blue – the amount of blue ( 0.0 – 1.0 ).
• alpha – the amount of alpha ( 0.0 – 1.0 ).

If you specify a value higher than 1.0, it’ll be clamped to 1.0 which means that any number higher than 1.0 will be changed to 1.0.

You can think of this function as the same as

SDL_SetRenderDrawColor(&renderer, r, g, b, a)

The parameters are a little different, but both sets the color that will be used in the next step.

glClear

In order to update / fill the screen with the color we sat above using glClearColor(), we use glClear()

Parameters :

• GLbitfield is basically an enum that tells us what we want to clear. We’ll use GL_COLOR_BUFFER_BIT which means we want to clear the colors, reseting the screen to the color we set using glClearColor

You can think of this function as the same as

SDL_RenderClear(&renderer);

SDL_GL_SwapWindow

This function swaps the back buffer ( were we are currently drawing ) with the front buffer ( the one currently on the screen) . So you could say that this function does the actual double-buffering.

Parameters :

window the SDL_Window we want to swap the buffers on

You can think of this function as the same as

SDL_RenderPresent(&renderer);

Basically ; it pushes things onto the screen.

Setting background color example.

Setting the background color in OpenGL is just as simple as in SDL2.

In SDL2, you can do something like this :

To do the same in OpenGL, you can do :

A small example

Let’s put it all together and make a small example. This example uses the event system in SDL2, so if you’re unfamiliar with that, you should read up on it.

In order to compile on Linux / Mac, you can simplu run

clang++ main.cpp -lGL -lGLEW -lSDL2 -std=c++11 -o Test

or

g++ main.cpp -lGL -lGLEW -lSDL2 -std=c++11 -o Test

In the application, you can press r, g, b to swap the color

Conclusion

Setting up OpenGL with SDL2 is easy! And now that we have it set up, we can do lots of fancy 3D stuff. I have been thinking about writing this for a long time, and I finally got around to it. I really hope you enjoy it and want to learn more about OpenGL. 3D is much more fun than 2D, and I promise things will get more interesting when we get the basics out of the way

The code in this post was based on the code from this post

Feel free to comment if you have anything to say or ask questions if anything is unclear. I always appreciate getting comments.

You can also email me : olevegard@headerphile.com

32 thoughts on “[OpenGL – Part 1] OpenGL using SDL2”

1. Luke says:

Your OpenGL tutorials are awesome and exactly what I was looking for after months of searching 🙂

Thanks for taking the time to make them!

1. olevegard says:

Thanks for you comment, always makes me happy to see that my tutorials are helping people : )

1. olevegard says:

You’re right, I’ll update the gist and remove that flag . Thank you for pointing it out : )

2. Do you really need to qualify your comment with “silly”? If you know it all, why should you come here and read this tutorial?

2. Siddharth Chandra says:

This has really helped me a lot in setting up opengl with sdl2. Thanks a ton.

3. Dunke says:

Thanks for the help. 🙂

4. Zero says:

Well it is a good tutorial, but you create SDL_GL_SetAttribute before creating context (SDL_GL_CreateContext), calling SDL_GL_* functions before context creation can mess things up (which makes sense if you think about it). So it better set atributes after creating context.

1. olevegard says:

Hello!

Updated the gist, thanks for helping me improve my posts 🙂

1. dimman says:

Actually no this is wrong according to the SDL wiki: https://wiki.libsdl.org/SDL_GL_SetAttribute

Attributes should be set _before_ window creation. And to be able to create an OpenGL context you need to have a window, thus the attribute setters must go first.

2. Rational Coder says:

That is incorrect. You are getting the default OpenGL context with this code, and the functions you are using are basic enough that it will work.

If you check the documentation: https://wiki.libsdl.org/SDL_GL_SetAttribute
It explicitly states that the attributes need to be set BEFORE OpenGL window creation.

1. In tutorials, is probably not a bad idea to be explicit. It may be redundant, but it is less of “black magic” for the people trying to learn.

1. olevegard says:

Hello!

I haven’t been able to test my code on Mac, so I haven’t really been able to verify that everything works correctly. So thank you for letting me know and helping me make the code work on Mac as well!

5. jscr says:

Hi olevegard!

Your tutorials seems very useful! But I’m having trouble following the right order. Where should I start?

1. olevegard says:

Hello 🙂

Assuming you are familiar with C++, the ideal place to start would be the first SDL2 post. The OpenGL series kinda builds upon the SDL2 series. And alot of things learned in the SDL2 series will be helpful when making your OpenGL game.

6. Gabriel says:

Are you comeback with more please?

7. Gabriel Morales says:

After months of writing SDL2 code, I ran into a wall and suddenly found myself needed to rip all my rendering code out and migrate over to modern OpenGL. Last time I’d touched OpenGL, it was the fixed function days. Your tutorials were exactly what I needed for this migration, thank you so much for writing these. You saved my skin!

8. CaptainKraft says:

You should provide attribution for the code: https://www.opengl.org/wiki/Tutorial1:_Creating_a_Cross_Platform_OpenGL_3.2_Context_in_SDL_(C_/_SDL)
(my apologies if I missed the attribution in the article)

Also, please call SDL_GL_SetAttribute before creating the SDL window and context, otherwise those attributes will not be set. From the SDL wiki:

“This function sets the OpenGL attribute attr to value. The requested attributes should be set before creating an OpenGL window. You should use SDL_GL_GetAttribute() to check the values after creating the OpenGL context, since the values obtained can differ from the requested ones. “

1. olevegard says:

Hey

Of course, you are right, thanks for informing me. I added your link to the bottom of the post.

I’ll have a look at the SDL_GL_SetAttribute when I can. You’re most likely right, but I want to test it out myself and make sure it doesn’t have any side effects or changes the behaviour of the program.

9. Well explained SDL2 and opengl integration. Thank you…

10. Hello,The OpenGL specification describes an abstract API for drawing 2D and 3D graphics. Although it is possible for the API to be implemented entirely in software, it is designed to be implemented mostly or entirely in hardware. if you facing any problem regarding dell computer support service you can visit this site.

11. Programmers prefer OpenGL for graphics. If you are one of them, you are strongly advised by its producer, to use a window toolkit (such as SDL) and OpenGL loading libraries (such as GLEW). This guide will help you get over the first challenge of using OpenGL with SDL and GLEW: Installing and setting them up, and creating your first project with OpenGL-SDL-GLEW Template in Visual Studio 2017.

12. The OpenGL provides the various drivers for the Linus system and as well as has the compatibility with the MacOs.

13. Julio says:

Why is “#define GL3_PROTOTYPES 1” required?

14. OpenGL tutorials are fantastic. This is very useful for me. thanks for sharing and keep updating..

15. Before we go through the steps you need to perform to troubleshoot Epson driver issues, it is best to understand why they occur in the first place.

16. // Delete our OpengL context
SDL_GL_DeleteContext(mainContext);

// Destroy our window
SDL_DestroyWindow(mainWindow);

// Shutdown SDL 2
SDL_Quit();

17. Open GL is the best for Linux operating system. it is very useful for me. Keep up the good work.

18. OpenGL is most useful for installing the driver in Linux or Mac operating system.

19. Ben says:

Hey, you need to swap these

mainContext = SDL_GL_CreateContext(mainWindow);

SetOpenGLAttributes();

So the created context actually has the attributes you requested.

Thanks