#include #include #include #include "DynString.h" #include "pltf/gl_funcs.h" #include "log.h" static char read_buf[512] = { 0 }; static const size_t read_buf_len = sizeof(read_buf) / sizeof(read_buf[0]); static DynString read_shader_source(const char* path) { const DynString full_path = DynString_alloc_concat_c_strs( SHADERS_PATH, strlen(SHADERS_PATH), path, strlen(path) ); DynString source = DynString_alloc("", 0); FILE* shader_file = fopen(DynString_c_str(&full_path), "r"); if (shader_file == NULL) { LOG_ERRORF("Failed to open file %.*s. Errno: %d", DYN_STRING_FMT(full_path), errno); return source; } size_t bytes_read = 0; do { bytes_read = fread(read_buf, 1, read_buf_len - 1, shader_file); read_buf[bytes_read] = '\0'; DynString_concat_c_str(&source, read_buf, bytes_read); } while (bytes_read == read_buf_len - 1); if (fclose(shader_file) == EOF) { LOG_ERRORF("Failed to close file %s. Errno: %d", path, errno); } return source; } static unsigned int compile_shader(const DynString* shader_src, const GLenum shader_type) { const unsigned int shader = glCreateShader(shader_type); const char* shader_src_c_str = DynString_c_str(shader_src); const int len = (int) shader_src->len; glShaderSource(shader, 1, &shader_src_c_str, &len); glCompileShader(shader); int compile_status = 0; glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status); if (compile_status != GL_TRUE) { int info_log_len = 0; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_len); char* err_str = (char*) malloc(sizeof(char) * info_log_len); glGetShaderInfoLog(shader, info_log_len - 1, NULL, err_str); LOG_FATALF("Failed to compile vertex shader: %s", err_str); } return shader; } unsigned int shader_create( const char* vertex_shader_path, const char* fragment_shader_path ) { DynString vert_source = read_shader_source(vertex_shader_path); DynString frag_source = read_shader_source(fragment_shader_path); const unsigned int vert_shader = compile_shader(&vert_source, GL_VERTEX_SHADER); const unsigned int frag_shader = compile_shader(&frag_source, GL_FRAGMENT_SHADER); DynString_free(&vert_source); DynString_free(&frag_source); const unsigned int shader_program = glCreateProgram(); glAttachShader(shader_program, vert_shader); glAttachShader(shader_program, frag_shader); glLinkProgram(shader_program); int compile_status = 0; glGetProgramiv(shader_program, GL_LINK_STATUS, &compile_status); if (compile_status != GL_TRUE) { LOG_FATAL("Failed to link shader program."); } glDeleteShader(vert_shader); glDeleteShader(frag_shader); return shader_program; }