Nimbin[12]?Games / Entropie / entropie/src/render/shader.c

Entropie git · main

Entropie festival game; first steps

sdl c game entropie cmake · first commit 2026-10-10 · last commit 2026-11-02 (18 hours ago) · synced 10 hours ago

C 88.5% Markdown 9.1% GLSL 2.3%
git clone https://git.christianimmanuel.de/games/Entropie.gitwget https://git.christianimmanuel.de/games/Entropie/archive/Entropie.tar.gz
entropie/src/render/shader.c 2.3 KB · 76 lines raw
#include "render/shader.h"
#include "core/platform.h"

#include <SDL3/SDL.h>

static char *readAsset(const char *asset) {
    char path[1024];
    if (!Platform_assetPath(asset, path, sizeof(path))) {
        SDL_Log("Asset path too long: %s", asset);
        return NULL;
    }
    char *data = SDL_LoadFile(path, NULL); /* null-terminated */
    if (!data) SDL_Log("Cannot read %s: %s", path, SDL_GetError());
    return data;
}

#define GLSL_VERSION "#version 330 core\n"
#define COMMON_ASSET "shaders/common.glsl"

static GLuint compile(GLenum type, const char *common, const char *source, const char *name) {
    const char *parts[] = { GLSL_VERSION, common, "\n#line 1\n", source };
    GLuint shader = glCreateShader(type);
    glShaderSource(shader, 4, parts, NULL);
    glCompileShader(shader);

    GLint ok = GL_FALSE;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
    if (!ok) {
        char log[1024];
        glGetShaderInfoLog(shader, sizeof(log), NULL, log);
        SDL_Log("Shader compile error in %s:\n%s", name, log);
        glDeleteShader(shader);
        return 0;
    }
    return shader;
}

GLuint Shader_load(const char *vert_asset, const char *frag_asset) {
    GLuint program = 0, vert = 0, frag = 0;
    char *common   = readAsset(COMMON_ASSET);
    char *vert_src = readAsset(vert_asset);
    char *frag_src = readAsset(frag_asset);
    if (!common || !vert_src || !frag_src) goto done;

    vert = compile(GL_VERTEX_SHADER, common, vert_src, vert_asset);
    frag = compile(GL_FRAGMENT_SHADER, common, frag_src, frag_asset);
    if (!vert || !frag) goto done;

    program = glCreateProgram();
    glAttachShader(program, vert);
    glAttachShader(program, frag);
    glLinkProgram(program);

    GLint ok = GL_FALSE;
    glGetProgramiv(program, GL_LINK_STATUS, &ok);
    if (!ok) {
        char log[1024];
        glGetProgramInfoLog(program, sizeof(log), NULL, log);
        SDL_Log("Shader link error (%s + %s):\n%s", vert_asset, frag_asset, log);
        glDeleteProgram(program);
        program = 0;
    }

done:
    if (vert) glDeleteShader(vert);
    if (frag) glDeleteShader(frag);
    SDL_free(common);
    SDL_free(vert_src);
    SDL_free(frag_src);
    return program;
}

void Shader_destroy(GLuint *program) {
    if (*program) glDeleteProgram(*program);
    *program = 0;
}