DEV Community

Harry Tanama
Harry Tanama

Posted on • Edited on

Create Basic Window Frame with SDL3 and OpenGL in Linux

  1. Setting up GLAD

GLAD is an open-source, multi-language OpenGL Loading Library (specifically, an extension loader generator) based on the official Khronos XML specifications. Its primary job is to find and dynamically load the memory locations (function pointers) of OpenGL functions provided by your graphics card driver at runtime.

Go to the GLAD web service, make sure the language is set to C++, and in the API section select an OpenGL version of at least 3.3 (which is what we'll be using; higher versions are fine as well). Also make sure the profile is set to Core and that the Generate a loader option is ticked. Ignore the extensions (for now) and click Generate to produce the resulting library files.

Download https://www.glfw.org/

GLFW (Graphics Library Framework) is a lightweight utility library used to create windows, handle user input (mouse, keyboard, gamepads), manage timers, and set up rendering contexts for OpenGL, OpenGL ES, and Vulkan

For linux:

  1. Update Drivers and Build ToolsOpen your terminal and install the core compiler tools alongside your system's graphics development files.
sudo apt update && sudo apt install build-essential cmake git
sudo apt install libgl1-mesa-dev
Enter fullscreen mode Exit fullscreen mode
  1. Install Windowing and Input LibrariesInstall GLFW and X11/Wayland dependencies so your application can create windows and register keyboard or mouse inputs.
sudo apt install libglfw3-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev
Enter fullscreen mode Exit fullscreen mode

Get the SDL3 from here https://wiki.libsdl.org/SDL3/FrontPage

How to Compile or Build the Binary Executable

The command to compile and link the source code main.cpp and compile glad.c

g++ -Wall -I$HOME/Local/SDL3/include -I./glad/include main.cpp ./glad/src/glad.c -L$HOME/Local/SDL3/lib -lSDL3 -o test

Enter fullscreen mode Exit fullscreen mode

or

g++ -Wall -I$HOME/Local/SDL3/include \
 -I./glad/include \
 main.cpp ./glad/src/glad.c \
 -L$HOME/Local/SDL3/lib -lSDL3 -o test
Enter fullscreen mode Exit fullscreen mode

Or You can use this is Makefile for Build Automation Tool

build:
    bear -- g++ -Wall -g -I$(HOME)/Local/SDL3/include \
    -I./glad/include \
    main.cpp ./glad/src/glad.c \
    -L$(HOME)/Local/SDL3/lib -lSDL3 -o test

run:
    ./test

clean:
    rm test         
Enter fullscreen mode Exit fullscreen mode

The SDL3 library is installed at the home directory $HOME/Local/SDL3 And the dynamic library is not store globally in /usr/lib so we need to set the the ENVIRONMENT VARIABLE

Get the glad library from https://glad.dav1d.de/

Place the glad library folder with your main.cpp file to test the SDL3 and OpenGL.

export LD_LIBRARY_PATH=$HOME/Local/SDL3/lib
Enter fullscreen mode Exit fullscreen mode

After everything is compiled run the binary file

./test
Enter fullscreen mode Exit fullscreen mode

This is a simple source code to create window frame to test if your SDL3 and OpenGL work correctly

And at the end of the source code there is a picture showing how compilation process work.

#include <glad/glad.h>  // CRITICAL: Always include GLAD before SDL3!
#include <SDL3/SDL.h>
#include <iostream>

int main(int argc, char* argv[]) {
    // 1. Initialize SDL3 Video Subsystem
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        std::cerr << "SDL3 Initialization Failed: " << SDL_GetError() << std::endl;
        return -1;
    }

    // 2. Request an OpenGL 4.6 Core Profile Context
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

    // 3. Create the Native Window Context
    SDL_Window* window = SDL_CreateWindow(
        "HT Game Engine - Engine Context Verified",
        1024,
        768,
        SDL_WINDOW_OPENGL
    );

    if (!window) {
        std::cerr << "Failed to Create Window: " << SDL_GetError() << std::endl;
        SDL_Quit();
        return -1;
    }

    // 4. Create the OpenGL Context bound to our Window
    SDL_GLContext glContext = SDL_GL_CreateContext(window);
    if (!glContext) {
        std::cerr << "Failed to Create OpenGL Context: " << SDL_GetError() << std::endl;
        SDL_DestroyWindow(window);
        SDL_Quit();
        return -1;
    }

    // 5. Initialize GLAD by feeding it SDL's function loader address
    if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) {
        std::cerr << "Failed to Initialize GLAD OpenGL Loader!" << std::endl;
        SDL_GL_DestroyContext(glContext);
        SDL_DestroyWindow(window);
        SDL_Quit();
        return -1;
    }

    // Success! Query the GPU to prove we are running hardware acceleration
    std::cout << "HT Game Engine Initialized Cleanly!" << std::endl;
    std::cout << "VENDOR:   " << glGetString(GL_VENDOR) << std::endl;
    std::cout << "RENDERER: " << glGetString(GL_RENDERER) << std::endl;
    std::cout << "VERSION:  " << glGetString(GL_VERSION) << std::endl;

    // Keep the engine sandbox alive for 4 seconds to view terminal metrics
    // SDL_Delay(4000);

    // --- NEW: CORE ENGINE LIFE WORKBENCH ---
    bool isRunning = true;
    SDL_Event event;

    // The Master Game Loop
    while (isRunning) {

        // Pillar 1: Process Native OS Input & Events
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_EVENT_QUIT) {
                isRunning = false; // Player clicked the 'X' button on the window
            }
            else if (event.type == SDL_EVENT_KEY_DOWN) {
                // If player presses the Escape key, flag the engine to shut down cleanly
                if (event.key.key == SDLK_ESCAPE) {
                    isRunning = false;
                }
            }
        }

        // TODO: Update Engine Systems (Physics, Positions, Frame Timers go here)

        // Render Frames via OpenGL GPU Buffers
        // Clear the screen with a beautiful, custom dark tactical background color
        glClearColor(0.1f, 0.14f, 0.18f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // Swap the back buffer to the front screen buffer to display what we drew
        SDL_GL_SwapWindow(window);
    }

    // Explicit Clean Resource 
    std::cout << "HT Game Engine shutting down cleanly..." << std::endl;
    SDL_GL_DestroyContext(glContext);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}
Enter fullscreen mode Exit fullscreen mode

Here is how compilation process work

TODO

Top comments (0)