// 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;
}