RyanHub - file viewer
filename: src/render/shader.c
branch: main
back to repo
// shader.c

#include "shader.h"
#include <stdio.h>
#include <stdlib.h>

static char* read_file(const char* path) {
    FILE* file = fopen(path, "rb");
    if (!file) {
        printf("Failed to open file: %s\n", path);
        return NULL;
    }

    fseek(file, 0, SEEK_END);
    long length = ftell(file);
    rewind(file);

    if (length < 0) {
        printf("Invalid file length: %s\n", path);
        fclose(file);
        return NULL;
    }

    char* buffer = malloc(length + 1);
    if (!buffer) {
        fclose(file);
        return NULL;
    }

    size_t read_size = fread(buffer, 1, length, file);
    if (read_size != (size_t)length) {
        printf("Failed to read the entire file: %s\n", path);
        free(buffer);
        fclose(file);
        return NULL;
    }

    buffer[length] = '\0';
    fclose(file);
    return buffer;
}

static void check_shader_errors(GLuint shader, const char* type) {
    int success;
    char infoLog[1024];
    if (type && strcmp(type, "PROGRAM") == 0) {
        glGetProgramiv(shader, GL_LINK_STATUS, &success);
        if (!success) {
            glGetProgramInfoLog(shader, 1024, NULL, infoLog);
            printf("PROGRAM LINK ERROR: %s\n", infoLog);
        }
    }
    else {
        glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
        if (!success) {
            glGetShaderInfoLog(shader, 1024, NULL, infoLog);
            printf("SHADER COMPILE ERROR (%s): %s\n", type, infoLog);
        }
    }
}

GLuint create_shader_program(const char* vertex_path, const char* fragment_path) {
    char* vertex_code = read_file(vertex_path);
    char* fragment_code = read_file(fragment_path);
    if (!vertex_code || !fragment_code) return 0;

    GLuint vertex = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex, 1, (const char**)&vertex_code, NULL);
    glCompileShader(vertex);
    check_shader_errors(vertex, "VERTEX");

    GLuint fragment = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragment, 1, (const char**)&fragment_code, NULL);
    glCompileShader(fragment);
    check_shader_errors(fragment, "FRAGMENT");

    GLuint program = glCreateProgram();
    glAttachShader(program, vertex);
    glAttachShader(program, fragment);
    glLinkProgram(program);
    check_shader_errors(program, "PROGRAM");

    glDeleteShader(vertex);
    glDeleteShader(fragment);
    free(vertex_code);
    free(fragment_code);

    return program;
}