Good gaming tutorials for SDL2/OpenGL 3.3+?


#1

Using Windows 10 (sometimes Ubuntu 16.04), IDE = Code::Blocks, Compiler = mingw.

I have been using OpenGL with SDL2 for a while now, only to have realized that I was writing for old versions of OpenGL, because apparently most of the tutorials have that and I didn’t know to check.

What I’m looking for are some solid tutorials (game-based preferable) for modern versions of OpenGL (I believe that’s 3.3+) that work with SDL2. So far I have only used SDL2’s included OpenGL functionality, and the few tutorials on new stuff introduce new libraries like GLEW, GLAD, etc., so I don’t know if I’ll have to use those in addition to SDL2, or if I can get away with pure SDL2.

Hopefully someone has had more luck than me and can share with the crowd. Some of what I have found so far that may help some:

Great tutorials, but sadly only this one (and maybe another) are new:
https://lazyfoo.net/tutorials/SDL/51_SDL_and_modern_opengl/index.php

On this domain. It’s 3.2, so I’m not sure if it’s considered new:
https://www.libsdl.org/release/SDL-1.2.15/docs/html/guidevideoopengl.html

Another option. Again, 3.2:
https://www.khronos.org/opengl/wiki/Tutorial1:Creating_a_Cross_Platform_OpenGL_3.2_Context_in_SDL(C_/_SDL)

As a last note, I’m open to other options, but I would prefer to keep it with SDL2.


#2

3.3 and 3.2 don’t make much of a difference.
I think what people (at least used to) call “modern OpenGL” started with 3.0, and since 3.2 it has a “core profile” that enforces using only the new (GL3+) way of doing things and not the older deprecated stuff.

https://www.libsdl.org/release/SDL-1.2.15/docs/html/guidevideoopengl.html

this one seems to be for SDL1.2, so it’s probably not too useful, also the code there doesn’t really look like modern GL

BTW, I found the tutorials at https://open.gl/ helpful.
Also, once you’ve got an OpenGL window (with a simple triangle in it) working with SDL, you should be able to follow any GL3 tutorials - all the OpenGL rendering stuff is the same, no matter if you’re using SDL or SFML or whatever. Just window- and context-creation (and OpenGL function pointer loading) is a bit different.
I think I also used http://www.opengl-tutorial.org/ as an additional resource for learning, it’s sometimes helpful to have the same things explained by different people to finally understand it oneself.


#3

@Daniel_Gibson

Thanks for your quick reply. I’m reading over those links right now. It looks like some good stuff.

So from what I understand, I can use my existing (older OpenGL) window and context creation with the new OpenGL? Here’s the initialization part of my code with all (I think) relevant variables (credit: lots of tutorials).

constexpr int SCREEN_WIDTH = 800;
constexpr int SCREEN_HEIGHT = 600;
constexpr char WINDOW_TITLE[] = "Very basic SDL2 OpenGL application";

// Variables for setting up the perspective.
// The amount of 1.0 should be (width / (5 * aspect)) or (height / 5).
constexpr GLfloat aspect = (GLfloat) SCREEN_WIDTH / (GLfloat) SCREEN_HEIGHT; // Aspect ratio for view port.
constexpr GLdouble fovY = 45.0f; // Field of vision in degrees in the y direction.
constexpr GLdouble zNear = 0.1f; // Near clipping distance.
constexpr GLdouble zFar = 100.0f; // Far clipping distance.
constexpr GLdouble fH = tan(fovY / 360 * M_PI) * zNear;
constexpr GLdouble fW = fH * aspect;

constexpr int OPENGL_MAJOR_VERSION = 2;
constexpr int OPENGL_MINOR_VERSION = 1;

// Defines the profile to create the context for.
// CORE, COMPACT or ANY. 3.2 and prior should use ANY.
constexpr SDL_GLprofile OPENGL_PROFILE = SDL_GLprofile::SDL_GL_CONTEXT_PROFILE_CORE;

// Background color for clearing the screen. (32-bit float from 0.0f to 1.0f)
constexpr GLclampf BG_CLEAR_RED = 0.33f;
constexpr GLclampf BG_CLEAR_GREEN = 0.33f;
constexpr GLclampf BG_CLEAR_BLUE = 0.33f;
constexpr GLclampf BG_CLEAR_ALPHA = 0.0f;

  // Initialize SDL.
	if (SDL_Init(SDL_INIT_VIDEO) < 0)
  {
		std::cerr << "ERROR: Could not initialize SDL2 because "
              << SDL_GetError() << std::endl;
		throw 10;
  }
  else
  {
    // Set OpenGL profile and version MAJOR.MINOR.
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, OPENGL_PROFILE);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, OPENGL_MAJOR_VERSION);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, OPENGL_MINOR_VERSION);

    // Create SDL display window.
    displayWindow = SDL_CreateWindow(WINDOW_TITLE, SDL_WINDOWPOS_CENTERED,
                                     SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
                                     SCREEN_HEIGHT, SDL_WINDOW_OPENGL);

    if (displayWindow == nullptr)
    {
      std::cerr << "ERROR: Could not create the window."
                << SDL_GetError() << std::endl;
      throw 10;
    }
    else
    {

      // Pick SDL window to associate with OpenGL context.
      context = SDL_GL_CreateContext(displayWindow);
      if (context == nullptr)
      {
        std::cerr << "ERROR: Cannot create OpenGL context."
                  << SDL_GetError() << std::endl;
        throw 10;
      }
      else
      {
        // Must be after the context is assigned.
        const unsigned char *version = glGetString(GL_VERSION);

        if (version == nullptr)
        {
          std::cerr << "ERROR: OpenGL configuration issue."
                    << SDL_GetError() << std::endl;
          throw 10;
        }
        else
        {
          SDL_GL_MakeCurrent(displayWindow, context);

          // Enable smooth shading.
          glShadeModel(GL_SMOOTH);

          // Set the background color (R, G, B, A). Range (0.0 to 1.0).
          glClearColor(BG_CLEAR_RED, BG_CLEAR_GREEN, BG_CLEAR_BLUE, BG_CLEAR_ALPHA);

          // Depth buffer setup.
          glClearDepth(1.0f);

          // Enable depth testing.
          glEnable(GL_DEPTH_TEST);

          // The type Of depth test.
          glDepthFunc(GL_LEQUAL);

          // Nice perspective calculations.
          glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

          // Setup view port inside SDL window: left, top, width, height.
          glViewport(0, 0, (GLsizei) SCREEN_WIDTH, (GLsizei) SCREEN_HEIGHT);

          // Set matrix mode as projection. (GL_MODELVIEW, GL_TEXTURE, GL_COLOR)
          glMatrixMode(GL_PROJECTION);

          // Replace the current matrix with the identity matrix.
          glLoadIdentity();

          // Vertical left and right clipping planes.
          // Horizontal bottom and top clipping planes.
          // Distance near and far clipping planes. Both MUST be positive.
          glFrustum(-fW, fW, -fH, fH, zNear, zFar);

          // Switch from projection to model view.
          glMatrixMode(GL_MODELVIEW);

          // Load the identity matrix to reset the view.
          glLoadIdentity();

#4

I’d write new code based on those tutorials, yours contains lots of old stuff, like glMatrixMode() and related (not used at all anymore, you pass the matrix/matrices to the shader as uniforms and multiply with them yourself).
Just work through the basic open.gl tutorials to get an idea how things are supposed to be done now :slight_smile:

Oh yeah, yet another page full of tutorials: https://learnopengl.com/


#5

Very good then. I’ll replace what I have with some of the new stuff. The whole what’s new and what’s old sometimes gets me lost, so I’ll post my new code when I get it done. Thanks for your help so far.


#6

Another vote for Learn OpenGL, it’s how I learned “modern” OpenGL. It only teaches OpenGL 3.3 (last version was 4.5 IIRC), and shows you how to set it up with GLFW, but it’s easy to adapt to SDL2, and OpenGL 4.5 is backward compatible with 3.3.

Just make sure that you set the SDL_GL_CONTEXT_FLAGS hint to give you a forward compatible context for greater compatibility and (possibly) performance:

SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);

#7

Thanks, I’ll check Learn OpenGL out.

I’m glad that 3.3 is compatible with the later versions. I just want to make sure that I’m not learning things that are obsolete. I’ll make sure to add that line to my code.

Recently, I have had people tell me that I need to drop OpenGL because it’s old and to start learning Vulkan. Others are telling me that unless I’m an expert programmer making game engines for a living, then I need to drop coding and switch to Unity. It’s confusing to know what to pursue sometimes.


#8

It’s easier and faster to get started with OpenGL than with Vulkan. By quite a bit (learning Vulkan right now, myself). And while OpenGL is essentially deprecated now (and literally deprecated on Mac and iOS), it’s not going to disappear soon, and learning the basics of 3D graphics will probably be easier on an easier API. Then if you later decide to learn Vulkan you’ll just be learning the API itself, not what matrixes are etc.

As to the thing about only doing graphics programming or making an engine if you’re getting paid to do it professionally: hogwash. Yes, you will be up and running sooner if you use Unity (or Unreal, etc.), but that’s not counting the time it takes to learn Unity, and ignoring the fact you still have to write game logic code with Unity or Unreal or Godot or whatever. Honestly, I’ve seen a lot of that talk coming from Vulkan advocates when trying to defend it for being kind of a pain to use (“Well, why aren’t you using an existing engine, then? Vulkan isn’t supposed to be easy to use!” etc. etc. etc.).

Graphics programming can be fun! It’s like real-time VFX!