aboutsummaryrefslogtreecommitdiff
path: root/09-september/tomcat/renderer/shader.c
diff options
context:
space:
mode:
Diffstat (limited to '09-september/tomcat/renderer/shader.c')
-rw-r--r--09-september/tomcat/renderer/shader.c187
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);
+}