#include "ShaderManager.h" #include "Utilities/Log.h" #include "Utilities/CfgParser.h" // library includes #include "physfs.h" // system includes #include #include using namespace std; namespace BlueCore { ShaderManager::ShaderManager(RenderWindow* renderwindow) : _usingShaders(true), _RenderWindow(renderwindow) { glewInit(); if (GLEW_ARB_fragment_shader == false) _usingShaders = false; _RenderWindow->WindowCloseSignal.connect(this, &ShaderManager::WindowCloseSlot); clog << ">>> ShaderManager constructed ..."<< endline; if (_usingShaders) clog << " using shaders"<< endline; else clog << " shaders not supported!"<< endlog; } ShaderManager::~ShaderManager() { clog << ">>> ShaderManager destructed ..."<< endlog; } void ShaderManager::shutdown() { clog << ">>> ShaderManager shutting down ..."<< endlog; ShaderProgramMap::iterator prog_iter; for (prog_iter = shader_programs.begin(); prog_iter!= shader_programs.end(); prog_iter++) { glDeleteObjectARB(prog_iter->second); } shader_programs.clear(); VertexShaderMap::iterator vert_iter; for (vert_iter = vertex_shader.begin(); vert_iter != vertex_shader.end(); vert_iter++) { glDeleteObjectARB(vert_iter->second); } vertex_shader.clear(); FragmentShaderMap::iterator frag_iter; for (frag_iter = fragment_shader.begin(); frag_iter!= fragment_shader.end(); frag_iter++) { glDeleteObjectARB(frag_iter->second); } fragment_shader.clear(); } void ShaderManager::WindowCloseSlot() { shutdown(); } bool ShaderManager::usingShaders() { return _usingShaders; } void printInfoLog(GLhandleARB obj) { int infologLength = 0; int charsWritten = 0; char *infoLog; glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength); if (infologLength > 1) { infoLog = new char[infologLength+1]; glGetInfoLogARB(obj, infologLength, &charsWritten, infoLog); clog << " "<< infoLog << endline; delete [] infoLog; } } VertexShader ShaderManager::loadVertexShader(const string &name) { if ( !_usingShaders) return 0; // check if this mesh is already loaded VertexShaderMap::const_iterator result; result = vertex_shader.find(name); if (result != vertex_shader.end() ) { return result->second; } //string filename = name + ".vert"; PHYSFS_file *file = PHYSFS_openRead(name.c_str() ); if ( !file) { clog << "!!! VertexShader '"<< name << "' not found"<< endline; return 0; } char *buffer = new char[ PHYSFS_fileLength ( file ) ]; PHYSFS_read(file, buffer, 1, PHYSFS_fileLength(file) ); buffer[ PHYSFS_fileLength ( file ) - 1] = 0; PHYSFS_close(file); VertexShader shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); glShaderSourceARB(shader, 1, ( const GLcharARB** ) &buffer, NULL); delete [] buffer; glCompileShaderARB(shader); vertex_shader[name] = shader; clog << ">>> VertexShader '"<< name << "' loaded"<< endline; return shader; } FragmentShader ShaderManager::loadFragmentShader(const string &name) { if ( !_usingShaders) return 0; // check if this mesh is already loaded FragmentShaderMap::const_iterator result; result = fragment_shader.find(name); if (result != fragment_shader.end() ) { return result->second; } //string filename = name + ".frag"; PHYSFS_file *file = PHYSFS_openRead(name.c_str() ); if ( !file) { clog << "!!! FragmentShader '"<< name << "' not found"<< endline; return 0; } char *buffer = new char[ PHYSFS_fileLength ( file ) ]; PHYSFS_read(file, buffer, 1, PHYSFS_fileLength(file) ); buffer[ PHYSFS_fileLength ( file ) - 1] = 0; PHYSFS_close(file); FragmentShader shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); glShaderSourceARB(shader, 1, ( const GLcharARB** ) &buffer, NULL); delete [] buffer; glCompileShaderARB(shader); printInfoLog(shader); fragment_shader[name] = shader; clog << ">>> FragmentShader '"<< name << "' loaded"<< endline; return shader; } ShaderProgram ShaderManager::loadShaderProgram(const std::string &name) { if ( !_usingShaders) return 0; if (name.empty() ) return 0; // check if this mesh is already loaded ShaderProgramMap::const_iterator result; result = shader_programs.find(name); if (result != shader_programs.end() ) { return result->second; } string filename = name + ".prog"; PHYSFS_file *file = PHYSFS_openRead(filename.c_str() ); if ( !file) { clog << "!!! ShaderProgramm '"<< name << "' not found"<< endline; return 0; } unsigned int length = PHYSFS_fileLength(file); char *buffer = new char[length]; PHYSFS_read(file, buffer, 1, length); PHYSFS_close(file); CfgParser cfg; cfg.parse(buffer, length); delete [] buffer; ShaderProgram program = glCreateProgramObjectARB(); std::vector vertex_shaders; if (cfg.getStrings("vertex_shaders", vertex_shaders) ) { for (unsigned int i = 0; i < vertex_shaders.size(); i++) { VertexShader shader = loadVertexShader(vertex_shaders[i]); if (shader != 0) glAttachObjectARB(program, shader); } } std::vector fragment_shaders; if (cfg.getStrings("fragment_shaders", fragment_shaders) ) { for (unsigned int i = 0; i < fragment_shaders.size(); i++) { FragmentShader shader = loadFragmentShader(fragment_shaders[i]); if (shader != 0) glAttachObjectARB(program, shader); } } glLinkProgramARB(program); printInfoLog(program); shader_programs[name] = program; clog << ">>> ShaderProgramm '"<< name << "' loaded"<< endline; return program; } void ShaderManager::useShaderProgram(ShaderProgram shader_program) { if ( !_usingShaders) return; glUseProgramObjectARB(shader_program); } void ShaderManager::useTexture(ShaderProgram shader_program, unsigned int texture, const std::string &name) { if ( !_usingShaders) return; GLint location = glGetUniformLocationARB(shader_program, name.c_str() ); //if( location > 0 ) glUniform1iARB(location, texture); } /* void ShaderManager::useTangentBuffer ( ShaderProgram shader_program, TangentBuffer *tangent_buffer, const std::string &name ) { if ( !_usingShaders || !tangent_buffer ) return; GLuint location = glGetAttribLocationARB ( shader_program, name.c_str() ); glEnableVertexAttribArrayARB ( location ); tangent_buffer->bind(); glVertexAttribPointerARB ( location, 3, GL_FLOAT, 0, 0, 0 ); } void ShaderManager::disableTangentBuffer ( ShaderProgram shader_program, const std::string &name ) { if ( !_usingShaders ) return; GLuint location = glGetAttribLocationARB ( shader_program, name.c_str() ); glDisableVertexAttribArrayARB ( location ); } */ }