Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "stdafx.h"
- #include "ShaderManager.h"
- #include "TextFileReader.h"
- namespace key{
- // Opengl Shader API
- static PFNGLACTIVETEXTUREPROC glActiveTexture = nullptr;
- static PFNGLATTACHSHADERPROC glAttachShader = nullptr;
- static PFNGLCOMPILESHADERPROC glCompileShader = nullptr;
- static PFNGLCREATESHADERPROC glCreateShader = nullptr;
- static PFNGLCREATEPROGRAMPROC glCreateProgram = nullptr;
- static PFNGLDELETEPROGRAMPROC glDeleteProgram = nullptr;
- static PFNGLDELETESHADERPROC glDeleteShader = nullptr;
- static PFNGLDETACHSHADERPROC glDetachShader = nullptr;
- static PFNGLGETACTIVEATTRIBPROC glGetActiveAttrib = nullptr;
- static PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform = nullptr;
- static PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation = nullptr;
- static PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog = nullptr;
- static PFNGLGETPROGRAMIVPROC glGetProgramiv = nullptr;
- static PFNGLGETSHADERIVPROC glGetShaderiv = nullptr;
- static PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog = nullptr;
- static PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation= nullptr;
- static PFNGLLINKPROGRAMPROC glLinkProgram = nullptr;
- static PFNGLSHADERSOURCEPROC glShaderSource = nullptr;
- static PFNGLUNIFORM1FPROC glUniform1f = nullptr;
- static PFNGLUNIFORM1IPROC glUniform1i = nullptr;
- static PFNGLUNIFORM3FVPROC glUniform3fv = nullptr;
- static PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv = nullptr;
- static PFNGLUSEPROGRAMPROC glUseProgram = nullptr;
- static const Program NO_SHADER_PROGRAM = static_cast<Program>(-1);
- template<typename T>
- static int getSize(T t){
- switch(t){
- case AT_FLOAT_VEC2:
- return 2;
- case AT_FLOAT_VEC3:
- return 3;
- case AT_FLOAT_VEC4:
- return 4;
- default:
- {
- std::ostringstream str;
- str << __FUNCTION__ << " invalid type("<<t<<")\n";
- throw ExceptionHandler(str);
- return 0;
- }
- }
- }
- ShaderManager::AttributeVariable::AttributeVariable(AttributeType eTypeIn, unsigned uLocIn):
- uLocation(uLocIn),
- eType(eTypeIn),
- iSize(getSize(eTypeIn))
- {}
- ShaderManager::UniformVariable::UniformVariable(UniformType eTypeIn, unsigned uLocIn):
- uLocation(uLocIn),
- eType(eTypeIn)
- {}
- ShaderManager::InfoProgram::InfoProgram():
- uId(glCreateProgram())
- {
- aShaderIndex.assign(INVALID_UNSIGNED);
- }
- ShaderManager::InfoShader::InfoShader(int iglId, std::string filename):
- uId(glCreateShader(iglId)),
- strFilename(filename)
- {}
- static void DefineOpenGLAPI(){
- std::ostringstream strStream;
- strStream << __FUNCTION__ << " can not initialize function pointer named: ";
- // OpenGL 2.1
- if((glActiveTexture = (PFNGLACTIVETEXTUREPROC) wglGetProcAddress("glActiveTexture" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glActiveTexture" ));
- if((glAttachShader = (PFNGLATTACHSHADERPROC) wglGetProcAddress("glAttachShader" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glAttachShader" ));
- if((glCompileShader = (PFNGLCOMPILESHADERPROC) wglGetProcAddress("glCompileShader" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glCompileShader" ));
- if((glCreateProgram = (PFNGLCREATEPROGRAMPROC) wglGetProcAddress("glCreateProgram" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glCreateProgram" ));
- if((glCreateShader = (PFNGLCREATESHADERPROC) wglGetProcAddress("glCreateShader" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glCreateShader" ));
- if((glDeleteProgram = (PFNGLDELETEPROGRAMPROC) wglGetProcAddress("glDeleteProgram" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glDeleteProgram" ));
- if((glDeleteShader = (PFNGLDELETESHADERPROC) wglGetProcAddress("glDeleteShader" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glDeleteShader" ));
- if((glDetachShader = (PFNGLDETACHSHADERPROC) wglGetProcAddress("glDetachShader" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glDetachShader" ));
- if((glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC) wglGetProcAddress("glGetActiveAttrib" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glGetActiveAttrib" ));
- if((glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC) wglGetProcAddress("glGetActiveUniform" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glGetActiveUniform" ));
- if((glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) wglGetProcAddress("glGetAttribLocation" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glGetAttribLocation" ));
- if((glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) wglGetProcAddress("glGetShaderInfoLog" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glGetShaderInfoLog"));
- if((glGetShaderiv = (PFNGLGETSHADERIVPROC) wglGetProcAddress("glGetShaderiv" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glGetShaderiv" ));
- if((glGetProgramiv = (PFNGLGETPROGRAMIVPROC) wglGetProcAddress("glGetProgramiv" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glGetProgramiv" ));
- if((glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) wglGetProcAddress("glGetProgramInfoLog" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glGetProgramInfoLog" ));
- if((glGetUniformLocation= (PFNGLGETUNIFORMLOCATIONPROC) wglGetProcAddress("glGetUniformLocation"))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glGetUniformLocation" ));
- if((glLinkProgram = (PFNGLLINKPROGRAMPROC) wglGetProcAddress("glLinkProgram" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glLinkProgram" ));
- if((glShaderSource = (PFNGLSHADERSOURCEPROC) wglGetProcAddress("glShaderSource" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glShaderSource" ));
- if((glUseProgram = (PFNGLUSEPROGRAMPROC) wglGetProcAddress("glUseProgram" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glUseProgram" ));
- if((glUniform1f = (PFNGLUNIFORM1FPROC) wglGetProcAddress("glUniform1f" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glUniform1f"));
- if((glUniform1i = (PFNGLUNIFORM1IPROC) wglGetProcAddress("glUniform1i" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glUniform1i"));
- if((glUniform3fv = (PFNGLUNIFORM3FVPROC) wglGetProcAddress("glUniform3fv" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glUniform3fv"));
- if((glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) wglGetProcAddress("glUniformMatrix4fv" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glUniformMatrix4fv"));
- if((glUseProgram = (PFNGLUSEPROGRAMPROC) wglGetProcAddress("glUseProgram" ))==nullptr)throw ExceptionHandler(std::string(strStream.str() +"glUseProgram" ));
- }
- ShaderManager::ShaderManager():
- Singleton(TYPE_SHADER_MANAGER),
- _vPrograms(NUMBER_OF_PROGRAM_IDS),
- _eEnableShaderProgram(NO_SHADER_PROGRAM)
- {
- DefineOpenGLAPI();
- }
- ShaderManager::~ShaderManager(){
- _eEnableShaderProgram = NO_SHADER_PROGRAM;
- if(glUseProgram){
- glUseProgram(0);
- }
- // Detach/Delete programs/shaders
- unsigned uShaderIndex = 0;
- for(unsigned uProgramIndex = 0; uProgramIndex < _vPrograms.size(); ++uProgramIndex){
- SharedInfoProgram pInfoProgram = _vPrograms[uProgramIndex];
- if(pInfoProgram){
- for(unsigned uShaderType = 0; uShaderType < pInfoProgram->aShaderIndex.size(); ++uShaderType){
- uShaderIndex = pInfoProgram->aShaderIndex[uShaderType];
- if(uShaderIndex != INVALID_UNSIGNED){
- try{
- glDetachShader(pInfoProgram->uId, _avShaders[uShaderType].at(uShaderIndex)->uId);
- } catch(std::exception&){
- std::ostringstream str;
- str << __FUNCTION__ << "Shader Index{" << uShaderIndex << "} is out of range for ShaderManager::_avShaders["
- << uShaderType << "] there are onle " << _avShaders[uShaderType].size()
- << " InfoShader* stored in vector for ShaderProgramId[" << uProgramIndex << "]";
- Logger::log(str, Logger::TYPE_ERROR);
- }
- }
- }
- glDeleteProgram(pInfoProgram->uId);
- }
- }
- _vPrograms.clear();
- // Free memory used by shaders
- for(unsigned uShaderType = 0; uShaderType < _avShaders.size(); ++uShaderType){
- for each(const SharedInfoShader& pInfoShader in _avShaders[uShaderType]){
- glDeleteShader(pInfoShader->uId);
- }
- _avShaders[uShaderType].clear();
- }
- }
- void ShaderManager::Create(ShaderProgramSettings& shaderProgramSettings){
- SharedInfoProgram pInfoProgram;
- try {
- pInfoProgram = _vPrograms.at(shaderProgramSettings._eShaderProgram);
- if(pInfoProgram){
- std::ostringstream str;
- str << __FUNCTION__ << " failed. ShaderProgram [" << shaderProgramSettings._eShaderProgram << "] has already been created.";
- throw ExceptionHandler(str);
- }
- } catch(...){
- std::ostringstream str;
- str << __FUNCTION__ << " failed. ShaderProgram [" << shaderProgramSettings._eShaderProgram << "] is not valid.";
- throw ExceptionHandler(str);
- }
- // Create a new program if a previous was not found
- pInfoProgram.reset(new InfoProgram());
- if(pInfoProgram->uId == 0){
- std::ostringstream str;
- str << __FUNCTION__ << " failed. glCreateProgram returned 0 for ShaderProg["<< shaderProgramSettings._eShaderProgram << "]";
- throw ExceptionHandler(str);
- }
- pInfoProgram->aShaderIndex[TYPE_VERTEX] = _InitializeShader(TYPE_VERTEX, shaderProgramSettings._strVertexShaderFilename);
- pInfoProgram->aShaderIndex[TYPE_FRAGMENT] = _InitializeShader(TYPE_FRAGMENT, shaderProgramSettings._strFragmentShaderFilename);
- glAttachShader(pInfoProgram->uId, _avShaders[TYPE_VERTEX].at( pInfoProgram->aShaderIndex[TYPE_VERTEX])->uId);
- glAttachShader(pInfoProgram->uId, _avShaders[TYPE_FRAGMENT].at( pInfoProgram->aShaderIndex[TYPE_FRAGMENT])->uId);
- glLinkProgram(pInfoProgram->uId);
- int iStatus;
- glGetProgramiv(pInfoProgram->uId, GL_LINK_STATUS, &iStatus);
- if(!iStatus){
- std::ostringstream str;
- str << __FUNCTION__ << " failed. \nLink program failed for ShaderProgram[" << shaderProgramSettings._eShaderProgram << "]";
- str << "\n";
- int iLength = 0;
- glGetProgramiv(pInfoProgram->uId, GL_INFO_LOG_LENGTH, &iLength);
- if(iLength > 0){
- str << "Log Message:\n - ";
- std::unique_ptr<char[]> pLogInfo(new char[iLength]);
- int iWritten = 0;
- glGetProgramInfoLog(pInfoProgram->uId, iLength, &iWritten, pLogInfo.get());
- str << pLogInfo.get();
- }
- throw ExceptionHandler(str);
- }
- // Verify and process attribute and uniform variables
- _ProcessAttributes(pInfoProgram->uId, shaderProgramSettings._eShaderProgram, shaderProgramSettings._vAttributes, pInfoProgram->mAttributes);
- _ProcessUniforms(pInfoProgram->uId, shaderProgramSettings._eShaderProgram, shaderProgramSettings._vUniforms, pInfoProgram->mUniforms);
- _vPrograms[shaderProgramSettings._eShaderProgram] = pInfoProgram;
- }
- unsigned ShaderManager::_InitializeShader(ShaderType eType, const std::string& filename){
- int iOpenglShaderId = 0;
- switch(eType){
- case TYPE_VERTEX:
- iOpenglShaderId = GL_VERTEX_SHADER;
- break;
- case TYPE_FRAGMENT:
- iOpenglShaderId = GL_FRAGMENT_SHADER;
- break;
- default:
- throw ExceptionHandler(__FUNCTION__ + std::string(" Invalid type passed in."));
- } // switch
- VectorInfoShaders& vectorInfoShaders = _avShaders[eType];
- for(unsigned u = 0; u < vectorInfoShaders.size(); ++u){
- if(vectorInfoShaders[u]->strFilename == filename){
- // Already loaded shader file
- return u;
- }
- }
- // Create new shader
- SharedInfoShader pInfoShader(new InfoShader(iOpenglShaderId, filename));
- if(pInfoShader->uId==0)
- throw ExceptionHandler(__FUNCTION__ + std::string(" glCreateShader failed for ") + filename);
- // Get source code
- TextFileReader file(filename.c_str());
- std::string contents = file.readAll();
- const char* szContents = contents.c_str();
- glShaderSource(pInfoShader->uId, 1, &szContents, nullptr);
- // Compile shader
- glCompileShader(pInfoShader->uId);
- int iStatus;
- glGetShaderiv(pInfoShader->uId, GL_COMPILE_STATUS, &iStatus);
- if(!iStatus){
- std::ostringstream str;
- str << __FUNCTION__ << " failed. Compile shader failed for Shader[" << filename << "]";
- str << "\n";
- int iLength = 0;
- glGetShaderiv(pInfoShader->uId, GL_INFO_LOG_LENGTH, &iLength);
- if(iLength > 0){
- str << "Log Message:\n";
- std::unique_ptr<char[]> pLogInfo(new char[iLength]);
- int iWritten = 0;
- glGetShaderInfoLog(pInfoShader->uId, iLength, &iWritten, pLogInfo.get());
- str << pLogInfo.get();
- }
- throw ExceptionHandler(str);
- }
- vectorInfoShaders.push_back(pInfoShader);
- return (vectorInfoShaders.size()-1);
- }
- void ShaderManager::_ProcessAttributes(unsigned uInfo, Program prog, std::vector<ShaderProgramSettings::AttributeInfo>& vAttribs, MapAttributes& mAttribs) const {
- bool bError = false;
- std::ostringstream str;
- str << __FUNCTION__ << "\nErrors were found with ATTRIBUTE variables in ShaderProg " << prog << "\n";
- int iNumVariables = 0;
- glGetProgramiv(uInfo, GL_ACTIVE_ATTRIBUTES, &iNumVariables);
- if(iNumVariables == 0 && !vAttribs.empty()){
- for each(const ShaderProgramSettings::AttributeInfo& attrib in vAttribs){
- str << attrib.strName << " " << attrib.shaderVariable << " is not used in shader.\n";
- }
- throw ExceptionHandler(str);
- }
- int iMaxLen = 0;
- glGetProgramiv(uInfo, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &iMaxLen);
- std::unique_ptr<char[]> pAttributeName(new char[iMaxLen]);
- for(int i=0; i<iNumVariables; ++i){
- int iSize;
- GLenum eType;
- glGetActiveAttrib(uInfo, i, iMaxLen, NULL, &iSize, &eType, pAttributeName.get());
- AttributeType eAttributeType = static_cast<AttributeType>(eType);
- bool bFound = false;
- for(auto it = vAttribs.begin(); it!=vAttribs.end(); it++){
- if(it->strName == pAttributeName.get()){
- bFound = true;
- if(it->shaderVariable._eType != eAttributeType){
- str << "Type missmatch in " << pAttributeName.get() << ". "
- << it->shaderVariable << " was defined, but shader used type{" << GetShaderTypeName(eAttributeType) << "}.\n";
- } else {
- it->isVerified = true;
- }
- }
- }
- if(!bFound){
- str << pAttributeName.get() << " of type{" << GetShaderTypeName(eAttributeType) << "} is used in the shader but was not added to the ShaderProgramSettings.\n";
- bError = true;
- }
- // Check to ensure all variables were verified
- for each(const ShaderProgramSettings::AttributeInfo& attrib in vAttribs){
- if(!attrib.isVerified){
- str<< attrib.strName << " " << attrib.shaderVariable << " is not verified.\n";
- bError = true;
- } else {
- unsigned uiLoc = glGetAttribLocation(uInfo, attrib.strName.c_str());
- if(uiLoc == INVALID_UNSIGNED){
- str << " Can not find attribute locaton for {" << attrib.strName << "}\n";
- throw ExceptionHandler(str);
- }
- mAttribs.insert(MapAttributes::value_type(attrib.shaderVariable._eVariable,
- AttributeVariable(attrib.shaderVariable._eType, uiLoc)));
- }
- }
- if(bError)
- throw ExceptionHandler(str);
- }
- }
- void ShaderManager::_ProcessUniforms(unsigned uInfo, Program prog, std::vector<ShaderProgramSettings::UniformInfo>& vUniforms, MapUniforms& mUniforms) const {
- bool bError = false;
- std::ostringstream str;
- str << __FUNCTION__ << " Errors were found with UNIFORM variables in ShaderProg " << prog << "\n";
- int iNumVariables = 0;
- glGetProgramiv(uInfo, GL_ACTIVE_UNIFORMS, &iNumVariables);
- if(iNumVariables == 0 && !vUniforms.empty()){
- for each(const ShaderProgramSettings::UniformInfo& uni in vUniforms){
- str << uni.strName << " " << uni.shaderVariable << " is not used in shader.\n";
- }
- throw ExceptionHandler(str);
- }
- int iMaxLen = 0;
- glGetProgramiv(uInfo, GL_ACTIVE_UNIFORM_MAX_LENGTH, &iMaxLen);
- std::unique_ptr<char[]> pUniformName(new char[iMaxLen]);
- for(int i=0; i<iNumVariables; ++i){
- int iSize;
- GLenum eType;
- glGetActiveUniform(uInfo, i, iMaxLen, NULL, &iSize, &eType, pUniformName.get());
- UniformType eUniformType = static_cast<UniformType>(eType);
- bool bFound = false;
- for(auto it = vUniforms.begin(); it!=vUniforms.end(); it++){
- if(it->strName == pUniformName.get()){
- bFound = true;
- if(it->shaderVariable._eType != eUniformType){
- str << "Type missmatch in " << pUniformName.get() << ". "
- << it->shaderVariable << " was defined, but shader used type{" << GetShaderTypeName(eUniformType) << "}.\n";
- } else {
- it->isVerified = true;
- }
- }
- }
- if(!bFound){
- str << pUniformName.get() << " of type{" << GetShaderTypeName(eUniformType) << "} is used in the shader but was not added to the ShaderProgramSettings.\n";
- bError = true;
- }
- // Check to ensure all variables were verified
- for each(const ShaderProgramSettings::UniformInfo& uni in vUniforms){
- if(!uni.isVerified){
- str<< uni.strName << " " << uni.shaderVariable << " is not verified.\n";
- bError = true;
- } else {
- unsigned uiLoc = glGetUniformLocation(uInfo, uni.strName.c_str());
- if(uiLoc == INVALID_UNSIGNED){
- str << " Can not find uniform locaton for {" << uni.strName << "}\n";
- throw ExceptionHandler(str);
- }
- mUniforms.insert(MapUniforms::value_type(uni.shaderVariable._eVariable,
- UniformVariable(uni.shaderVariable._eType, uiLoc)));
- }
- }
- if(bError)
- throw ExceptionHandler(str);
- }
- }
- void ShaderManager::Enable(Program eProg){
- try{
- glUseProgram(_vPrograms.at(eProg)->uId);
- _eEnableShaderProgram = eProg;
- } catch (std::exception&){
- std::ostringstream str;
- str << __FUNCTION__ << " ShaderProgram[" << eProg << "] is out of range in _avProgram\n";
- throw ExceptionHandler(str);
- }
- }
- void ShaderManager::EnableAttribute(Attribute eAttrib, unsigned stride, unsigned offset, bool normalize) const{
- _SetVertexAttribute(eAttrib, reinterpret_cast<const void* const>(0), true, stride, offset, normalize);
- }
- void ShaderManager::DisableAttribute(Attribute eAttrib) const{
- _SetVertexAttribute(eAttrib, reinterpret_cast<const void* const>(0), false, 0, 0, false);
- }
- void ShaderManager::_SetVertexAttribute(AttributeVariable a,const void* const p, bool b, unsigned s, unsigned o, bool n)const{
- if(b){
- glVertexAttribPointer(a.uLocation, a.iSize, GL_FLOAT, (n?GL_TRUE:GL_FALSE),s, reinterpret_cast<const void*>(o));
- glEnableVertexAttribArray(a.uLocation);
- } else {
- glDisableVertexAttribArray(a.uLocation);
- }
- }
- void ShaderManager::_SetVertexAttribute(AttributeVariable a, const float* const p, bool _x1_, unsigned _x2_, unsigned _x3_, bool _x4_) const{
- //glVertexAttrib4fv(a.uLocation, p);
- }
- void ShaderManager::SetUniform(Uniform eShaderUniform, const glm::mat4& m4Matrix) const{
- try{
- SharedInfoProgram pInfo = _vPrograms.at(_eEnableShaderProgram);
- MapUniforms::const_iterator it = pInfo->mUniforms.find(eShaderUniform);
- if(it==pInfo->mUniforms.cend()){
- std::ostringstream str;
- str << __FUNCTION__ << " Can not find Uniform location for Uniform{" << eShaderUniform<<"} in the active program {" << _eEnableShaderProgram <<"}\n";
- throw ExceptionHandler(str);
- }
- if( !(it->second.eType == UT_FLOAT_MAT4))
- {
- std::ostringstream str;
- str << __FUNCTION__ << " Invalid type passed into function.\n";
- throw ExceptionHandler(str);
- }
- glUniformMatrix4fv(it->second.uLocation, 1, false, &m4Matrix[0][0]);
- } catch(std::exception&){
- std::ostringstream str;
- str << __FUNCTION__ << " failed.\n";
- if(_eEnableShaderProgram == NO_SHADER_PROGRAM){
- str << "ShaderManager::Enable has not been called.\n";
- } else {
- str << "ShaderProgram is out of ranged. (" << _eEnableShaderProgram << std::endl;
- }
- throw ExceptionHandler(str);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement