// shader handling // Author: Supakorn "Jamie" Rassameemasmuang #include "common.h" #ifdef HAVE_GL #include #include #include #include #include #include "shaders.h" GLuint compileAndLinkShader(std::vector const& shaders, size_t Nlights, size_t NMaterials, std::vector const& defineflags) { GLuint shader = glCreateProgram(); std::vector compiledShaders; size_t n=shaders.size(); for(size_t i=0; i < n; ++i) { GLint newshader=createShaderFile(shaders[i].first,shaders[i].second, Nlights,NMaterials,defineflags); glAttachShader(shader,newshader); compiledShaders.push_back(newshader); } glBindAttribLocation(shader,positionAttrib,"position"); glBindAttribLocation(shader,normalAttrib,"normal"); glBindAttribLocation(shader,materialAttrib,"material"); glBindAttribLocation(shader,colorAttrib,"color"); glBindAttribLocation(shader,widthAttrib,"width"); glLinkProgram(shader); for(size_t i=0; i < n; ++i) { glDetachShader(shader,compiledShaders[i]); glDeleteShader(compiledShaders[i]); } return shader; } GLuint createShaders(GLchar const* src, int shaderType, std::string const& filename) { GLuint shader=glCreateShader(shaderType); glShaderSource(shader, 1, &src, NULL); glCompileShader(shader); GLint status; glGetShaderiv(shader, GL_COMPILE_STATUS, &status); if(status != GL_TRUE) { GLint length; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); std::vector msg(length); glGetShaderInfoLog(shader, length, &length, msg.data()); size_t n=msg.size(); for(size_t i=0; i < n; ++i) { std::cerr << msg[i]; } std::cerr << std::endl << "GL Compile error" << std::endl; std::cerr << src << std::endl; throw 1; } return shader; } GLuint createShaderFile(std::string file, int shaderType, size_t Nlights, size_t Nmaterials, std::vector const& defineflags) { std::ifstream shaderFile; shaderFile.open(file.c_str()); std::stringstream shaderSrc; #ifdef __APPLE__ #define GLSL_VERSION "410" #else #define GLSL_VERSION "130" #endif shaderSrc << "#version " << GLSL_VERSION << "\n"; shaderSrc << "#extension GL_ARB_uniform_buffer_object : enable" << "\n"; size_t n=defineflags.size(); for(size_t i=0; i < n; ++i) { shaderSrc << "#define " << defineflags[i] << "\n"; } shaderSrc << "#define Nlights " << Nlights << "\n"; shaderSrc << "const int Nmaterials=" << Nmaterials << ";\n"; if(shaderFile) { shaderSrc << shaderFile.rdbuf(); shaderFile.close(); } else { throw 1; } return createShaders(shaderSrc.str().data(), shaderType, file); } #endif