shader.c (4697B)
1 #include "shader.h" 2 #include "logger.h" 3 #include "memory.h" 4 5 #include <stdio.h> 6 7 static char* stringFromFile(const char* filename) 8 { 9 // Open file. 10 FILE* fp = fopen(filename, "r"); 11 if (!fp) 12 { 13 LOGE("Failed to open file '%s'", filename); 14 return NULL; 15 } 16 17 // Calculate the length of the file. 18 fseek(fp, 0, SEEK_END); 19 long size = ftell(fp); 20 rewind(fp); 21 22 // Read file to string. 23 char *string = (char *)s_alloc(size + 1, MEMORY_TAG_STRING); 24 if (string) 25 { 26 fread(string, 1, size, fp); 27 string[size] = '\0'; 28 } 29 else 30 { 31 LOGE("Failed to allocate string for file '%s'", filename); 32 } 33 fclose(fp); 34 return string; 35 } 36 37 static GLuint createAndCompileShader(const char* shader_string, 38 GLenum shader_type) 39 { 40 GLuint shader = glCreateShader(shader_type); 41 glShaderSource(shader, 1, &shader_string, NULL); 42 glCompileShader(shader); 43 44 // Handle errors. 45 GLint is_compiled; 46 glGetShaderiv(shader, GL_COMPILE_STATUS, &is_compiled); 47 if (is_compiled == GL_FALSE) 48 { 49 GLint size; 50 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size); 51 char *string = (char *)s_alloc(size, MEMORY_TAG_STRING); 52 glGetShaderInfoLog(shader, size, &size, string); 53 LOGE("Failed to compile shader: %s", string); 54 glDeleteShader(shader); 55 return 0; 56 } 57 58 return shader; 59 } 60 61 static GLuint createAndLinkProgram(GLuint vertex_shader, 62 GLuint fragment_shader) 63 { 64 GLuint program = glCreateProgram(); 65 glAttachShader(program, vertex_shader); 66 glAttachShader(program, fragment_shader); 67 glLinkProgram(program); 68 69 // Handle errors. 70 GLint is_linked; 71 glGetProgramiv(program, GL_LINK_STATUS, &is_linked); 72 if (is_linked == GL_FALSE) 73 { 74 GLint size; 75 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &size); 76 char *string = (char *)s_alloc(size, MEMORY_TAG_STRING); 77 glGetProgramInfoLog(program, size, &size, string); 78 LOGE("Failed to link program: %s", string); 79 glDeleteProgram(program); 80 return 0; 81 } 82 83 glDetachShader(program, vertex_shader); 84 glDetachShader(program, fragment_shader); 85 86 return program; 87 } 88 89 static GLuint createProgramFromFiles(const char* vertex_shader_filename, 90 const char* fragment_shader_filename) 91 { 92 char* vertex_shader_string = stringFromFile(vertex_shader_filename); 93 GLuint vertex_shader = createAndCompileShader(vertex_shader_string, 94 GL_VERTEX_SHADER); 95 if (vertex_shader == 0) return 0; 96 97 char* fragment_shader_string = stringFromFile(fragment_shader_filename); 98 GLuint fragment_shader = createAndCompileShader(fragment_shader_string, 99 GL_FRAGMENT_SHADER); 100 if (fragment_shader == 0) return 0; 101 102 GLuint program = createAndLinkProgram(vertex_shader, fragment_shader); 103 104 glDeleteShader(vertex_shader); 105 glDeleteShader(fragment_shader); 106 107 return program; 108 } 109 110 struct Shader { 111 GLuint program; 112 const char *vert_filename; 113 const char *frag_filename; 114 }; 115 116 Shader *Shader_make(const char* vert_filename, const char* frag_filename) 117 { 118 LOGI("Creating shader: %s %s", vert_filename, frag_filename); 119 120 GLuint program = createProgramFromFiles(vert_filename, frag_filename); 121 122 Shader *shader = s_alloc(sizeof *shader, MEMORY_TAG_RENDER); 123 shader->program = program; 124 shader->vert_filename = vert_filename; 125 shader->frag_filename = frag_filename; 126 127 return shader; 128 } 129 130 void Shader_free(Shader *shader) 131 { 132 if (shader) 133 { 134 s_free(shader, sizeof *shader, MEMORY_TAG_RENDER); 135 } 136 } 137 138 void Shader_use(Shader *shader) 139 { 140 glUseProgram(shader->program); 141 } 142 143 void Shader_reload(Shader* shader) 144 { 145 GLuint reloaded_program = createProgramFromFiles(shader->vert_filename, 146 shader->frag_filename); 147 148 if (reloaded_program != 0) 149 { 150 glDeleteProgram(shader->program); 151 shader->program = reloaded_program; 152 } 153 } 154 155 void Shader_setInt(const Shader *shader, const char *name, i32 i) 156 { 157 GLint uniform_loc = glGetUniformLocation(shader->program, name); 158 glUniform1i(uniform_loc, i); 159 } 160 161 void Shader_setFloat(const Shader *shader, const char *name, f32 f) 162 { 163 GLint uniform_loc = glGetUniformLocation(shader->program, name); 164 glUniform1f(uniform_loc, f); 165 } 166 167 void Shader_setVec3(const Shader *shader, const char *name, Vec3 v) 168 { 169 GLint uniform_loc = glGetUniformLocation(shader->program, name); 170 glUniform3fv(uniform_loc, 1, v); 171 } 172 173 void Shader_setMat4(const Shader *shader, const char *name, Mat4 m) 174 { 175 GLint uniform_loc = glGetUniformLocation(shader->program, name); 176 glUniformMatrix4fv(uniform_loc, 1, GL_FALSE, m[0]); 177 } 178