New Paste :: Recent Pastes:: No Line Numbers
A Paste by godecho
1
/* this is pretty rough, and far from finished. if you have any questions, catch me on irc to ask. i'll end up working this into a development guide or something. */ // glslang.h #ifndef _GLSLANG_H #define _GLSLANG_H #ifdef _WIN32 #include <windows.h> // If you dont have this, gl.h will not compile #define _snscanf snscanf #endif #include <GL/gl.h> #include <map> #include <string> #include <vector> #include "glextensions.h" using namespace std; struct ShaderObj { ShaderObj() : handle(0) {} ~ShaderObj(); inline bool operator < (const ShaderObj &right) const { return ((filename < right.filename) ? true : false); } inline bool operator > (const ShaderObj &right) const { return ((filename > right.filename) ? true : false); } string filename; GLenum type; GLhandleARB handle; }; struct ProgObj { ProgObj() : handle(0) {} ~ProgObj(); bool AttachAndLink(); vector<ShaderObj *> shaders; string filename; GLhandleARB handle; }; namespace GLslangMgr { static const GLhandleARB DISABLESHADERS = 0; typedef map<string, ShaderObj *>::iterator ShdrItr; typedef map<string, ShaderObj *>::const_iterator ShdrCItr; class GLslangHandler { public: GLslangHandler(); ~GLslangHandler(); GLhandleARB LoadProgram(const char *filename); ShaderObj *LoadShader(const char *filename, const GLenum &type); void Reload(); void UseProgram(const GLhandleARB &prog) const; inline void DisableShaders() const { glUseProgramObjectARB(0); } private: map <string, ShaderObj *> shaders; vector <ProgObj *> programs; mutable GLhandleARB currProg; void Flush(); }; inline GLslangHandler *Inst() { static GLslangHandler GLslangHandler; return &GLslangHandler; } void PrintInfoLog(const GLhandleARB &handle); } #endif // glslang.cpp #include "glslang.h" #include <cstdio> #include <cstring> #include <iostream> #include "console.h" #include "screen.h" // included temporarily for getting opengl errors ShaderObj::~ShaderObj() { if(handle) { glDeleteObjectARB(handle); } } ProgObj::~ProgObj() { if(handle) { glDeleteObjectARB(handle); } } bool ProgObj::AttachAndLink() { if(shaders.size() > 0) { handle = glCreateProgramObjectARB(); for(unsigned int x = 0; x < shaders.size(); ++x) { glAttachObjectARB(handle, shaders[x]->handle); } glLinkProgramARB(handle); GLint goodLink; glGetObjectParameterivARB(handle, GL_OBJECT_LINK_STATUS_ARB, &goodLink); if(goodLink == GL_TRUE) { return true; } else { GLslangMgr::PrintInfoLog(handle); ConsoleMgr::Inst()->AddText("* Error linking program object %s", filename.c_str()); return false; } } else { ConsoleMgr::Inst()->AddText("* Error, attempting to link program object %s, with no attached shaders.", filename.c_str()); return false; } } GLslangMgr::GLslangHandler::GLslangHandler() : currProg(0) { } GLslangMgr::GLslangHandler::~GLslangHandler() { for(unsigned int x = 0; x < programs.size(); ++x) { delete programs[x]; } for(ShdrItr itr = shaders.begin(); itr != shaders.end(); itr++) { delete itr->second; } //Flush(); // These will be lost when the context is destroyed, flushing them explicitly is unnecessary. } GLhandleARB GLslangMgr::GLslangHandler::LoadProgram(const char *filename) { FILE *file = fopen(filename, "rt"); if(file) { GLenum type; char buffer[128]; vector<ShaderObj *> shaders; ProgObj *prog = new ProgObj; if(!prog) { cerr << "Error allocating new ProgObj in GLslangHandler::LoadShader. This is Bad." << endl; exit(EXIT_FAILURE); } prog->filename = filename; cerr << "this fscanf is dangerous, possible overruns." << endl; while(fscanf(file, "%s\n", buffer) == 1) { char ftype = buffer[strlen(buffer)-3]; switch(ftype) { case 'v': type = GL_VERTEX_SHADER_ARB; break; case 'f': type = GL_FRAGMENT_SHADER_ARB; break; default: ConsoleMgr::Inst()->AddText("* Unknown shader type %s", buffer); return 0; } ShaderObj *shader = LoadShader(buffer, type); if(shader) { shaders.push_back(shader); } else { return 0; } } // If all goes well... prog->shaders = shaders; if(prog->AttachAndLink()) { programs.push_back(prog); return prog->handle; } else { delete prog; } } else { ConsoleMgr::Inst()->AddText("* Can't open shader propram object file %s.", filename); } return 0; } ShaderObj *GLslangMgr::GLslangHandler::LoadShader(const char *filename, const GLenum &type) { ShaderObj *shader = new ShaderObj; if(!shader) { cerr << "Error allocating new shader in GLslangHandler::LoadShader. This is Bad." << endl; exit(EXIT_FAILURE); } shader->handle = glCreateShaderObjectARB(type); FILE *stream; const GLcharARB *strings[1]; stream = fopen(filename, "rb"); if(stream) { fseek(stream, 0, SEEK_END); const GLint size = ftell(stream); fseek(stream, 0, SEEK_SET); if(size > 0) { GLcharARB *buffer = new GLcharARB[size]; if(!buffer) { cerr << "Error allocating new GLcharARB[] in GLslangHandler::LoadShader. This is Bad." << endl; exit(EXIT_FAILURE); } fread(buffer, sizeof(char), size, stream); fclose(stream); strings[0] = buffer; glShaderSourceARB(shader->handle, 1, strings, &size); delete [] buffer; glCompileShaderARB(shader->handle); GLint goodCompile; glGetObjectParameterivARB(shader->handle, GL_OBJECT_COMPILE_STATUS_ARB, &goodCompile); if(goodCompile == GL_TRUE) { shaders[filename] = shader; return shader; } else { GLslangMgr::PrintInfoLog(shader->handle); delete shader; ConsoleMgr::Inst()->AddText("* Error compiling shader %s", filename); } } else { ConsoleMgr::Inst()->AddText("* Error, attempting compiling an empty shader file %s.", filename); } } else { ConsoleMgr::Inst()->AddText("* Can't open shader file %s.", filename); } return 0; } void GLslangMgr::GLslangHandler::Reload() { } void GLslangMgr::GLslangHandler::UseProgram(const GLhandleARB &prog) const { if(prog != currProg) { glUseProgramObjectARB(prog); // If called with 0, the programmable processors will be disabled and fixed functionality will be used for both vertex and fragment processing. currProg = prog; } } void GLslangMgr::GLslangHandler::Flush() { } void GLslangMgr::PrintInfoLog(const GLhandleARB &handle) { GLint infoLength = 0; GLint charsWritten = 0; glGetObjectParameterivARB(handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infoLength); GLcharARB *info = new GLcharARB[infoLength]; if(!info) { cerr << "Error allocating new GLcharARB[] in GLslangMgr::PrintInfoLog. This is Bad." << endl; exit(EXIT_FAILURE); } glGetInfoLogARB(handle, infoLength, &charsWritten, info); ConsoleMgr::Inst()->AddText("%s", info); delete [] info; }