Skip to content

Modern OpenGL 3 3

Finalspace edited this page May 29, 2026 · 1 revision

Table of Contents

main.cpp

#define FPL_IMPLEMENTATION
#define FPL_NO_VIDEO_SOFTWARE
#define FPL_NO_AUDIO
#include <final_platform_layer.h>

// You have to include GL.h yourself or use any other OpenGL loader you want.
// FPL just creates an OpenGL rendering context for you, but nothing more.
#include <GL/gl.h>

#ifndef APIENTRY
#define APIENTRY
#endif
#define APIENTRYP APIENTRY *

#include <stddef.h>
typedef ptrdiff_t GLsizeiptr;
typedef ptrdiff_t GLintptr;
typedef char GLchar;

#ifndef GL_CONTEXT_PROFILE_MASK

#define GL_CONTEXT_PROFILE_MASK           0x9126
#define GL_CONTEXT_FLAGS                  0x821E

#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT  0x0001
#define GL_CONTEXT_FLAG_DEBUG_BIT               0x00000002
#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT       0x00000004
#define GL_CONTEXT_FLAG_NO_ERROR_BIT            0x00000008
#define GL_CONTEXT_CORE_PROFILE_BIT             0x00000001
#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT    0x00000002

#endif // GL_CONTEXT_PROFILE_MASK

#define GL_COMPILE_STATUS                 0x8B81
#define GL_INFO_LOG_LENGTH                0x8B84
#define GL_FRAGMENT_SHADER                0x8B30
#define GL_VERTEX_SHADER                  0x8B31
#define GL_SHADING_LANGUAGE_VERSION       0x8B8C
#define GL_LINK_STATUS                    0x8B82
#define GL_STATIC_DRAW                    0x88E4

typedef GLuint(APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
typedef GLuint(APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);

static PFNGLCREATESHADERPROC glCreateShader = NULL;
static PFNGLSHADERSOURCEPROC glShaderSource = NULL;
static PFNGLCOMPILESHADERPROC glCompileShader = NULL;
static PFNGLGETSHADERIVPROC glGetShaderiv = NULL;
static PFNGLATTACHSHADERPROC glAttachShader = NULL;
static PFNGLCREATEPROGRAMPROC glCreateProgram = NULL;
static PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog = NULL;
static PFNGLLINKPROGRAMPROC glLinkProgram = NULL;
static PFNGLVALIDATEPROGRAMPROC glValidateProgram = NULL;
static PFNGLGETPROGRAMIVPROC glGetProgramiv = NULL;
static PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog = NULL;
static PFNGLDELETESHADERPROC glDeleteShader = NULL;
static PFNGLUSEPROGRAMPROC glUseProgram = NULL;

#define GL_ARRAY_BUFFER                   0x8892

typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);

static PFNGLGENVERTEXARRAYSPROC glGenVertexArrays = NULL;
static PFNGLBINDVERTEXARRAYPROC glBindVertexArray = NULL;
static PFNGLGENBUFFERSPROC glGenBuffers = NULL;
static PFNGLBINDBUFFERPROC glBindBuffer = NULL;
static PFNGLBUFFERDATAPROC glBufferData = NULL;
static PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = NULL;
static PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray = NULL;
static PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = NULL;
static PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays = NULL;

#if defined(FPL_PLATFORM_WINDOWS)
static void *GLProcAddress(const char *name) {
    fpl__VideoState *videoState = (fpl__VideoState *)fpl__global__AppState->video.mem;
    (videoState != NULL);
    (videoState->win32.opengl.api.wglGetProcAddress != NULL);
    void *result = videoState->win32.opengl.api.wglGetProcAddress(name);
    return(result);
}
#else
static void *GLProcAddress(const char *name) {
    fpl__VideoState *videoState = (fpl__VideoState *)fpl__global__AppState->video.mem;
    (videoState != NULL);
    (videoState->x11.opengl.api.glXGetProcAddress != NULL);
    void *result = videoState->x11.opengl.api.glXGetProcAddress((const GLubyte *)name);
    return(result);
}
#endif

static void LoadGLExtensions() {
    glCreateShader = (PFNGLCREATESHADERPROC)GLProcAddress("glCreateShader");
    glShaderSource = (PFNGLSHADERSOURCEPROC)GLProcAddress("glShaderSource");
    glCompileShader = (PFNGLCOMPILESHADERPROC)GLProcAddress("glCompileShader");
    glGetShaderiv = (PFNGLGETSHADERIVPROC)GLProcAddress("glGetShaderiv");
    glAttachShader = (PFNGLATTACHSHADERPROC)GLProcAddress("glAttachShader");
    glCreateProgram = (PFNGLCREATEPROGRAMPROC)GLProcAddress("glCreateProgram");
    glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)GLProcAddress("glGetShaderInfoLog");
    glLinkProgram = (PFNGLLINKPROGRAMPROC)GLProcAddress("glLinkProgram");
    glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)GLProcAddress("glValidateProgram");
    glGetProgramiv = (PFNGLGETPROGRAMIVPROC)GLProcAddress("glGetProgramiv");
    glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)GLProcAddress("glGetProgramInfoLog");
    glDeleteShader = (PFNGLDELETESHADERPROC)GLProcAddress("glDeleteShader");
    glUseProgram = (PFNGLUSEPROGRAMPROC)GLProcAddress("glUseProgram");

    glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)GLProcAddress("glGenVertexArrays");
    glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)GLProcAddress("glBindVertexArray");
    glGenBuffers = (PFNGLGENBUFFERSPROC)GLProcAddress("glGenBuffers");
    glBindBuffer = (PFNGLBINDBUFFERPROC)GLProcAddress("glBindBuffer");
    glBufferData = (PFNGLBUFFERDATAPROC)GLProcAddress("glBufferData");
    glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)GLProcAddress("glEnableVertexAttribArray");
    glDisableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)GLProcAddress("glDisableVertexAttribArray");
    glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)GLProcAddress("glVertexAttribPointer");
    glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)GLProcAddress("glDeleteVertexArrays");
}

#define MODERN_OPENGL 1

static GLuint CreateShaderType(GLenum type, const char *source) {
    GLuint shaderId = glCreateShader(type);

    glShaderSource(shaderId, 1, &source, NULL);
    glCompileShader(shaderId);

    char info[1024 * 10] = ;

    GLint compileResult;
    glGetShaderiv(shaderId, GL_COMPILE_STATUS, &compileResult);
    if(!compileResult) {
        GLint infoLen;
        glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &infoLen);
        (infoLen <= (info));
        glGetShaderInfoLog(shaderId, infoLen, &infoLen, info);
        ("Failed compiling %s shader!\n", (type == GL_VERTEX_SHADER ? "vertex" : "fragment"));
        ("%s\n", info);
    }

    return(shaderId);
}

static GLuint CreateShaderProgram(const char *name, const char *vertexSource, const char *fragmentSource) {
    GLuint programId = glCreateProgram();

    GLuint vertexShader = CreateShaderType(GL_VERTEX_SHADER, vertexSource);
    GLuint fragmentShader = CreateShaderType(GL_FRAGMENT_SHADER, fragmentSource);

    glAttachShader(programId, vertexShader);
    glAttachShader(programId, fragmentShader);
    glLinkProgram(programId);
    glValidateProgram(programId);

    char info[1024 * 10] = ;

    GLint linkResult;
    glGetProgramiv(programId, GL_LINK_STATUS, &linkResult);
    if(!linkResult) {
        GLint infoLen;
        glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &infoLen);
        (infoLen <= (info));
        glGetProgramInfoLog(programId, infoLen, &infoLen, info);
        ("Failed linking '%s' shader!\n", name);
        ("%s\n", info);
    }

    glDeleteShader(fragmentShader);
    glDeleteShader(vertexShader);

    return(programId);
}

static bool RunModern() {
    LoadGLExtensions();

    GLuint vertexArrayID;
    glGenVertexArrays(1, &vertexArrayID);
    glBindVertexArray(vertexArrayID);

    const char *glslVersion = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
    ("OpenGL GLSL Version %s:\n", glslVersion);

    int profileMask;
    int contextFlags;
    glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profileMask);
    glGetIntegerv(GL_CONTEXT_FLAGS, &contextFlags);
    ("OpenGL supported profiles:\n");
    ("\tCore: %s\n", ((profileMask & GL_CONTEXT_CORE_PROFILE_BIT) ? "yes" : "no"));
    ("\tForward: %s\n", ((contextFlags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT) ? "yes" : "no"));

    ("Running modern OpenGL\n");

    const char vertexSource[] = {
        "#version 330 core\n"
        "\n"
        "layout(location = 0) in vec4 inPosition;\n"
        "\n"
        "void main() {\n"
        "\tgl_Position = inPosition;\n"
        "}\n"
    };

    const char fragmentSource[] = {
        "#version 330 core\n"
        "\n"
        "layout(location = 0) out vec4 outColor;\n"
        "\n"
        "void main() {\n"
        "\toutColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
        "}\n"
    };

    GLuint shaderProgram = CreateShaderProgram("Test", vertexSource, fragmentSource);

    float vertices[] = {
        0.0f, 0.5f,
        -0.5f, -0.5f,
        0.5f, -0.5f
    };
    GLuint buffer;
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glUseProgram(shaderProgram);

    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, NULL);

    glClearColor(0.39f, 0.58f, 0.93f, 1.0f);
    while(()) {
         ev;
        while((&ev)) {}

         windowArea;
        (&windowArea);
        glViewport(0, 0, windowArea., windowArea.);

        glClear(GL_COLOR_BUFFER_BIT);

        glDrawArrays(GL_TRIANGLES, 0, 3);

        ();
    }

    glDisableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glBindVertexArray(0);
    glDeleteVertexArrays(1, &vertexArrayID);

    return true;
}

int main(int argc, char **args) {
    int result = 0;
     settings = ();
    settings.. = ;
    ("FPL Modern OpenGL", settings.., (settings..));
    settings.... = ;
    settings.... = 3;
    settings.... = 3;
    settings.... = 4;
    if((, &settings)) {
        const char *version = (const char *)glGetString(GL_VERSION);
        const char *vendor = (const char *)glGetString(GL_VENDOR);
        const char *renderer = (const char *)glGetString(GL_RENDERER);
        ("OpenGL version: %s\n", version);
        ("OpenGL vendor: %s\n", vendor);
        ("OpenGL renderer: %s\n", renderer);
        RunModern();
        ();
        result = 0;
    } else {
        result = -1;
    }
    return(result);
}

Final Platform Layer

Pages

Topics

Data Structures

Clone this wiki locally