#include "shader.h" #include "SDL3/SDL_iostream.h" #include "SDL3/SDL_log.h" #include "arena_allocator.h" #include wn_shader *wn_shader_init(Arena *arena, wn_shader_code_location shader_code_location) { wn_shader *shader = arena_alloc(arena, sizeof(wn_shader)); *shader = (wn_shader){.shaderProgram = 0, .success = false}; const char *vertexShaderSource = SDL_LoadFile(shader_code_location.vertex_shader_source_path, NULL); const char *fragmentShaderSource = SDL_LoadFile(shader_code_location.fragment_shader_source_path, NULL); // vertex shader unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); glCompileShader(vertexShader); // check for shader compile errors int success; char infoLog[512]; glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to compile vertex shader: %s", infoLog); return shader; } // fragment shader unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); glCompileShader(fragmentShader); // check for shader compile errors glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to compile fragment shader: %s", infoLog); return shader; } // Free source code memory SDL_free((void *)vertexShaderSource); SDL_free((void *)fragmentShaderSource); // link shaders unsigned int shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); glLinkProgram(shaderProgram); // check for linking errors glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to link shader program: %s", infoLog); return shader; } glDeleteShader(vertexShader); glDeleteShader(fragmentShader); shader->shaderProgram = shaderProgram; shader->success = true; arena_deinit_task_push(arena, (ArenaDeinitTask){.func_ptr = *wn_shader_deinit, .func_param = shader, .next = NULL}); return shader; } void wn_shader_deinit(void *shader) { wn_shader *cast_shader = (wn_shader *)shader; glDeleteProgram(cast_shader->shaderProgram); }