§ Структура

Этот шаблон является просто пустой болванкой, программа которой ничего не делает, кроме как просто вызывает виртуальный метод frame() для рисования пустого экрана.

§ makefile/main.cc

all: com
	./main
com:
	g++ main.cc -lSDL2 -lGL -o main
#include "app.cc"
int main(int argc, char** argv)
{
    App app(1280, 800);
    return app.main();
}

§ app.h

#include <SDL2/SDL.h>
#include <GL/gl.h>

class App
{
protected:

    SDL_Window*     window;
    SDL_GLContext   context;
    SDL_Event       event;

public:

    App(int, int);
    ~App();
    int  main();
    virtual void frame();
};

§ app.cc

Реализация методов класса.
#include "app.h"

// Создание окна на экране
App::App(int w, int h)
{
    SDL_Init(SDL_INIT_EVERYTHING);
    window  = SDL_CreateWindow("OpenGL World", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, w, h, SDL_WINDOW_OPENGL);
    context = SDL_GL_CreateContext(window);
}

// Удалить контекст из памяти и закрыть окно
App::~App()
{
    SDL_GL_DeleteContext(context);
    SDL_DestroyWindow(window);
}

// Основной цикл окна
int App::main()
{
    uint32_t pticks = 0;

    while (1) {

        while (SDL_PollEvent(& event) != 0) {
            if (event.type == SDL_QUIT) {
                return 0;
            }
        }

        Uint32 ticks = SDL_GetTicks();

        // Обновление 60 раз в секунду
        if (ticks - pticks >= 16) { pticks = ticks; frame(); }

        // В конце - вывод нарисованного кадра в окно на экране
        SDL_GL_SwapWindow(window);
        SDL_Delay(1);
    }

    return 0;
}

// Обновление и рисование сцены
void App::frame()
{
    glClearColor(0, 0, 0.2, 1);
    glClear(GL_COLOR_BUFFER_BIT);
}