X-Git-Url: http://git.mutantstargoat.com?p=demo;a=blobdiff_plain;f=src%2Fopengl%2Fshader-gl.cc;h=c82a7d7e2cfa9e414a93d13ad3eef19bcadb3808;hp=c5b57a7954a30cce9e80ad6f91c9608a92f476be;hb=369d75c73bf926a6dbcf4d740c8664bbb401602a;hpb=0da7a98f74d00bfa6cf0d47fd7cf0f687eeba5f6 diff --git a/src/opengl/shader-gl.cc b/src/opengl/shader-gl.cc index c5b57a7..c82a7d7 100644 --- a/src/opengl/shader-gl.cc +++ b/src/opengl/shader-gl.cc @@ -2,8 +2,11 @@ #include #include +#include "state_manager.h" #include "opengl/shader-gl.h" +extern ShaderProgram *current_program; + ShaderGL::ShaderGL() { sdr = 0; @@ -73,17 +76,15 @@ void ShaderGL::destroy() type = SDR_UNKNOWN; } -void ShaderGL::attach(unsigned int prog) -{ - glAttachShader(prog, sdr); -} - /* Shader Program */ ShaderProgramGL::ShaderProgramGL() { prog = 0; memset(shaders, 0, sizeof shaders / sizeof *shaders); + + current_program = 0; + is_linked = false; } ShaderProgramGL::~ShaderProgramGL() @@ -91,14 +92,6 @@ ShaderProgramGL::~ShaderProgramGL() destroy(); } -void ShaderProgramGL::destroy() -{ - glDeleteProgram(prog); - prog = 0; - - delete_shaders(); -} - void ShaderProgramGL::delete_shaders() { for(unsigned int i=0; i<(sizeof shaders) / (sizeof *shaders); ++i) { @@ -106,14 +99,29 @@ void ShaderProgramGL::delete_shaders() } } +bool ShaderProgramGL::create() +{ + prog = glCreateProgram(); + if(!prog) { + fprintf(stderr, "Failed to create shader program.\n"); + return false; + } + return true; +} + bool ShaderProgramGL::link() { + if(is_linked) + return true; + glLinkProgram(prog); int status; glGetProgramiv(prog, GL_LINK_STATUS, &status); - if(status) + if(status) { printf("Successfully linked shader program.\n"); + is_linked = true; + } else printf("Failed to link shader program.\n"); @@ -131,44 +139,216 @@ bool ShaderProgramGL::link() return status ? true : false; } -bool ShaderProgramGL::load(const char *vfname, const char *ffname) +bool ShaderProgramGL::use() { - Shader *vsdr = new ShaderGL; - if(!vsdr->load(vfname, SDR_VERTEX)) { - delete vsdr; + if(!is_linked && !link()) { return false; } - Shader *fsdr = new ShaderGL; - if(!fsdr->load(ffname, SDR_FRAGMENT)) { - delete vsdr; - delete fsdr; - return false; + if(!prog) { + glUseProgram(0); + current_program = 0; } - prog = glCreateProgram(); + glUseProgram(prog); + current_program = this; + + static void (*const set_uniform[16])(GLint, GLsizei, const GLfloat *) = { + 0, glUniform1fv, glUniform2fv, glUniform3fv, glUniform4fv + }; + + for(size_t i=0; inum < 5) { + set_uniform[st->num](uniforms[i].location, 1, st->data); + } + else if(st->num == 16) { + glUniformMatrix4fv(uniforms[i].location, 1, GL_TRUE, st->data); + } + else { + fprintf(stderr, "Invalid number of floats in state %s: %d\n", st->name, st->num); + continue; + } + } + return true; +} - vsdr->attach(prog); - fsdr->attach(prog); +void ShaderProgramGL::destroy() +{ + glDeleteProgram(prog); + prog = 0; + is_linked = false; - if(!link()) { - delete vsdr; - delete fsdr; - glDeleteProgram(prog); - return false; + delete_shaders(); +} + +void ShaderProgramGL::attach_shader(Shader *shader) +{ + glAttachShader(prog, ((ShaderGL *)shader)->sdr); + is_linked = false; +} + +int ShaderProgramGL::get_uniform_location(const char *name) const +{ + if(!((ShaderProgramGL *)this)->use()) + return -1; + + return glGetUniformLocation(prog, name); +} + +int ShaderProgramGL::get_attribute_location(const char *name) const +{ + if(!((ShaderProgramGL *)this)->use()) + return -1; + + return glGetAttribLocation(prog, name); +} + +static int get_floats_num(unsigned int utype) +{ + switch(utype) { + case GL_FLOAT: + return 1; + case GL_FLOAT_VEC2: + return 2; + case GL_FLOAT_VEC3: + return 3; + case GL_FLOAT_VEC4: + return 4; + case GL_FLOAT_MAT2: + return 4; + case GL_FLOAT_MAT3: + return 9; + case GL_FLOAT_MAT4: + return 16; + default: + break; } - /* the order of shaders in the array is the order they have in - enum Type, so atm it goes like: VS, FS, ... because we have SDR_VERTEX, - SDR_FRAGMENT, ... */ + return -1; +} - shaders[0] = vsdr; - shaders[1] = fsdr; +void ShaderProgramGL::cache_uniforms() +{ + uniforms.clear(); - return true; + int num_uniforms; + glGetProgramiv(prog, GL_ACTIVE_UNIFORMS, &num_uniforms); + + int max_ulength; + glGetProgramiv(prog, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_ulength); + + char *name = new char[max_ulength + 1]; + name[max_ulength] = 0; + + for(int i=0; i