diff options
| author | Thomas Guillermo Albers Raviola <thomas@thomaslabs.org> | 2026-01-16 23:02:32 +0100 |
|---|---|---|
| committer | Thomas Guillermo Albers Raviola <thomas@thomaslabs.org> | 2026-01-16 23:02:32 +0100 |
| commit | 6b8af9cf83851c075c6c9514b1deaa931c2b19a4 (patch) | |
| tree | 428986b49c32e21d3f7a3c2dfa41858ae0153209 /09-september/tomcat/renderer/shader.c | |
Initial commit
Diffstat (limited to '09-september/tomcat/renderer/shader.c')
| -rw-r--r-- | 09-september/tomcat/renderer/shader.c | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/09-september/tomcat/renderer/shader.c b/09-september/tomcat/renderer/shader.c new file mode 100644 index 0000000..3f6a5d7 --- /dev/null +++ b/09-september/tomcat/renderer/shader.c @@ -0,0 +1,187 @@ +#include "renderer.h" +#include "../util/util.h" + +#include <stdlib.h> +#include <string.h> + +#define MAX_HASH_SHADER 16 +static Shader *shader_hash_table[MAX_HASH_SHADER]; + +static void CompileShader(const char *source, GLuint shaderID) +{ + glShaderSource(shaderID, 1, &source, 0); + glCompileShader(shaderID); + GLint error; + glGetShaderiv(shaderID, GL_COMPILE_STATUS, &error); + if(error != GL_TRUE) + { + GLint logLenth; + glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &logLenth); + GLchar buffer[logLenth]; + glGetShaderInfoLog(shaderID, logLenth, &logLenth, buffer); + glDeleteShader(shaderID); + Util_FatalError("Some shader failed to compile:\n%s", buffer); + } +} + +Shader *shader_new(const char *name, const char *vertexShaderPath, const char *fragShaderPath) +{ + if(strlen(name) >= MAX_PATH_LENGTH) + Util_FatalError("File following shader name is too long: %s", name); + + Shader *s; + s = shader_get(name); + if(s != NULL) + return s; + + char *vertexShaderSource = Util_LoadFile(vertexShaderPath); + char *fragmentShaderSource = Util_LoadFile(fragShaderPath); + + GLuint vs = 0, fs = 0, program; + vs = glCreateShader(GL_VERTEX_SHADER); + fs = glCreateShader(GL_FRAGMENT_SHADER); + + if(vs == 0 || fs == 0) + Util_FatalError("Shaders could not be created\n"); + + program = glCreateProgram(); + + CompileShader(vertexShaderSource, vs); + CompileShader(fragmentShaderSource, fs); + + glAttachShader(program, vs); + glAttachShader(program, fs); + + glLinkProgram(program); + + GLint error; + glGetProgramiv(program, GL_LINK_STATUS, &error); + + if(error != GL_TRUE) + { + GLint logLength; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength); + + GLchar buffer[logLength]; + glGetProgramInfoLog(program, logLength, &logLength, buffer); + + glDeleteProgram(program); + glDeleteShader(vs); + glDeleteShader(fs); + + Util_FatalError("Shader program failed to link!:\n%s", buffer); + } + /** Free some usless resources **/ + glDetachShader(program, vs); + glDetachShader(program, fs); + glDeleteShader(vs); + glDeleteShader(fs); + + free(vertexShaderSource); + free(fragmentShaderSource); + + /** Alloc the new texture **/ + s = malloc( sizeof(Shader) ); + memset(s, 0, sizeof(Shader) ); + s->id = program; + + /** Register inside the resource manager **/ + unsigned int hash_ = Util_Hash( name ); + hash_ %= MAX_HASH_SHADER; + + render.shaders[render.num_shaders] = s; + render.num_shaders += 1; + + strcpy(s->name, name); + s->_hash_next = shader_hash_table[hash_]; + shader_hash_table[hash_] = s; + + s->_hash = hash_; + + /** Return the final result **/ + return s; +} + +Shader *shader_get(const char *name) +{ + Shader *s; + + unsigned int hash_ = Util_Hash( name ); + hash_ %= MAX_HASH_SHADER; + + if(shader_hash_table[hash_] != NULL) + { + for(s = shader_hash_table[hash_]; s; s = s->_hash_next) + { + if( s->_hash == hash_ ) + return s; + } + } + return NULL; +} + +void shader_purge(Shader *shader) +{ + /** Purge the opengl data **/ + if(shader->id != 0) + { + glUseProgram(0); + glDeleteProgram(shader->id); + shader->id = 0; + } +} + +GLint shader_get_uniform_location( Shader *s, const char *uniformName ) +{ + GLint u = glGetUniformLocation(s->id, uniformName); + if(u == GL_INVALID_INDEX) + Util_FatalError("Uniform \"%s\" could not be found!", uniformName); + else + return u; + + return 0; +} + +GLint shader_get_attrib_location( Shader *s, const char *attributeName ) +{ + GLint attrLocation = glGetAttribLocation(s->id, attributeName); + if(attrLocation < 0) + Util_FatalError("Attribute \"%s\" could not be found!\n", attributeName); + return attrLocation; +} + +void shader_set_uniform_mat4( Shader *s, const char *name, const float matrix[16] ) +{ + GLint location = shader_get_uniform_location(s, name); + glUniformMatrix4fv(location, 1, GL_FALSE, matrix); +} + +void shader_set_uniform_float( Shader *s, const char *name, const float val ) +{ + GLint location = shader_get_uniform_location(s, name); + glUniform1f(location, val); +} + +void shader_set_uniform_vec2( Shader *s, const char *name, const float vec[2] ) +{ + GLint location = shader_get_uniform_location(s, name); + glUniform2fv(location, 1, vec); +} + +void shader_set_uniform_vec3( Shader *s, const char *name, const float vec[3] ) +{ + GLint location = shader_get_uniform_location(s, name); + glUniform3fv(location, 1, vec); +} + +void shader_set_uniform_vec4( Shader *s, const char *name, const float vec[4] ) +{ + GLint location = shader_get_uniform_location(s, name); + glUniform4fv(location, 1, vec); +} + +void shader_set_uniform_int( Shader *s, const char *name, const int val ) +{ + GLint location = shader_get_uniform_location(s, name); + glUniform1i(location, val); +} |
