#include "Material.h" #include "Texture.h" #include "RenderState.h" #include "ShaderProgram.h" #include "ShaderManager.h" #include "Matrix4x4.h" #include #include #ifdef _CRT_SET #define _CRTDBG_MAP_ALLOC #include #include // redefine new operator #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) #define new DEBUG_NEW #endif using namespace std; namespace CHCDemoEngine { // only instance of the shader manager ShaderManager *ShaderManager::sShaderManager = NULL; ///////// //-- cg stuff static CGcontext sCgContext = NULL; static CGprofile sCgFragmentProfile; static CGprofile sCgVertexProfile; static void cgErrorCallback() { CGerror lastError = cgGetError(); if (lastError) { printf("Cg error, exiting...\n"); //Debug << "\n" << cgGetErrorString(lastError) << endl; //Debug << "\n" << cgGetLastListing(sCgContext) << endl; printf("%s\n\n", cgGetErrorString(lastError)); printf("%s\n", cgGetLastListing(sCgContext)); exit(0); } } ShaderManager::ShaderManager() { // setup cg cgSetErrorCallback(cgErrorCallback); // create context. sCgContext = cgCreateContext(); // get the optimal fragment profile sCgFragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); //sCgFragmentProfile = CG_PROFILE_GPU_FP; if (sCgFragmentProfile == CG_PROFILE_FP40) cout << "cg profile: fp40" << endl; else cout << "cg profile " << sCgFragmentProfile << endl; cgGLSetOptimalOptions(sCgFragmentProfile); // get the optimal vertex profile sCgVertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX); cgGLSetOptimalOptions(sCgVertexProfile); // set textures to auto load cgGLSetManageTextureParameters(sCgContext, false); /////////////// //-- load the defaul programs for mrt (used if not defined by the user) ShaderProgram *vertexProgMrt, *fragmentProgMrt, *fragmentProgMrtTex; vertexProgMrt = CreateVertexProgram("mrt", "vtx", "defaultVertexMrt"); fragmentProgMrt = CreateFragmentProgram("mrt", "frag", "defaultFragmentMrt"); fragmentProgMrtTex = CreateFragmentProgram("mrt", "fragtex", "defaultFragmentTexMrt"); // provide the current view matrix: // this is an automatic parameter that is updated each frame fragmentProgMrt->AddParameter("viewMatrix", 0); fragmentProgMrtTex->AddParameter("viewMatrix", 0); // vertex program vertexProgMrt->AddParameter("viewMatrix", 0); // needed for for ssao vertexProgMrt->AddParameter("modelMatrix", 1); vertexProgMrt->AddParameter("oldModelMatrix", 2); ////////////////////////// //-- hack: use hardcoded tree animation (should be provided with a material script!) ShaderProgram *treeAnimProg, *treeAnimProgMrt; treeAnimProg = CreateVertexProgram("treeanimation", "animateVtx", "treeAnimation"); treeAnimProgMrt = CreateVertexProgram("treeanimation", "animateVtxMrt", "treeAnimationMrt"); treeAnimProg->AddParameter("timer", 0); treeAnimProg->AddParameter("windDir", 1); treeAnimProg->AddParameter("windStrength", 2); treeAnimProg->AddParameter("minMaxPos", 3); treeAnimProg->AddParameter("frequency", 4); treeAnimProg->AddParameter("lightDir", 5); treeAnimProgMrt->AddParameter("timer", 0); treeAnimProgMrt->AddParameter("windDir", 1); treeAnimProgMrt->AddParameter("windStrength", 2); treeAnimProgMrt->AddParameter("minMaxPos", 3); treeAnimProgMrt->AddParameter("frequency", 4); treeAnimProgMrt->AddParameter("oldTimer", 5); ShaderProgram *normalMappingVertexMrt, *normalMappingFragmentMrt; normalMappingVertexMrt = CreateVertexProgram("normalMapping", "vtx", "normalMappingVertexMrt"); normalMappingFragmentMrt = CreateFragmentProgram("normalMapping", "frag", "normalMappingFragmentMrt"); // provide the current view matrix: // this is an automatic parameter that is updated each frame normalMappingFragmentMrt->AddParameter("viewMatrix", 0); // vertex program normalMappingVertexMrt->AddParameter("viewMatrix", 0); // needed for for ssao normalMappingVertexMrt->AddParameter("modelMatrix", 1); normalMappingVertexMrt->AddParameter("oldModelMatrix", 2); cout << "cg initialization successful" << endl; } void ShaderManager::DelSingleton() { DEL_PTR(sShaderManager); } ShaderManager::~ShaderManager() { CLEAR_CONTAINER(mShaders); if (sCgContext) cgDestroyContext(sCgContext); } ShaderProgram *ShaderManager::CreateFragmentProgram(const std::string &filename, const std::string &funcName, const std::string &name) { return CreateShaderProgram(filename, funcName, name, true); } ShaderProgram *ShaderManager::CreateVertexProgram(const std::string &filename, const std::string &funcName, const std::string &name) { return CreateShaderProgram(filename, funcName, name, false); } void ShaderManager::EnableFragmentProfile() { cgGLEnableProfile(sCgFragmentProfile); } void ShaderManager::EnableVertexProfile() { cgGLEnableProfile(sCgVertexProfile); } void ShaderManager::DisableFragmentProfile() { cgGLDisableProfile(sCgFragmentProfile); } void ShaderManager::DisableVertexProfile() { cgGLDisableProfile(sCgVertexProfile); } ShaderProgram *ShaderManager::CreateShaderProgram(const std::string &filename, const std::string &funcName, const std::string &name, bool isFragment) { const string fullName = "src/shaders/" + filename + ".cg"; ShaderProgram *p; if (isFragment) { p = new ShaderProgram(sCgContext, fullName, sCgFragmentProfile, funcName, ShaderProgram::FRAGMENT_PROGRAM); } else { p = new ShaderProgram(sCgContext, fullName, sCgVertexProfile, funcName, ShaderProgram::VERTEX_PROGRAM); } if (GetShaderProgram(name)) { cerr << "Program name " << name << "already chosen" << endl; DEL_PTR(p); return p; } if (!p->IsValid()) { cerr << "Program " << funcName << " in " << fullName << " failed to load" << endl; DEL_PTR(p); return p; } // everything ok cout << "Program " << funcName << " in " << fullName << " loaded" << endl; mShaders.push_back(p); mShaderMap[name] = p; return p; } ShaderProgram *ShaderManager::GetShaderProgram(const std::string &name) { ShaderMap::const_iterator it = mShaderMap.find(name); if (it == mShaderMap.end()) return NULL; return (*it).second; } }