void __shaderStuff(Shader& s) { s.Link(); s.Use(); glBindFragDataLocation(s.ProgramHandle, 0, "outColor"); glUniform1i(glGetUniformLocation(s.ProgramHandle, "tex"), 0); GLint posAttrib = glGetAttribLocation(s.ProgramHandle, "position"); glEnableVertexAttribArray(posAttrib); checkGL; glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 9, 0); checkGL; GLint tposAttrib = glGetAttribLocation(s.ProgramHandle, "texpos"); checkGL; glEnableVertexAttribArray(tposAttrib); checkGL; glVertexAttribPointer(tposAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 9, (void*)(sizeof(float) * 3)); checkGL; GLint colAttrib = glGetAttribLocation(s.ProgramHandle, "color"); checkGL; glEnableVertexAttribArray(colAttrib); checkGL; glVertexAttribPointer(colAttrib, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 9, (void*)(sizeof(float) * 5)); }
FPS_UINT32 MaterialManager::CreateShader( const MATERIAL_SHADER &p_ShaderInfo, std::list< std::string > &p_ShaderParameters, MD5_DIGEST &p_ShaderDigest ) { Shader *pMaterialShader = new Shader( ); if( p_ShaderInfo.Types & SHADER_TYPE_VERTEX ) { if( pMaterialShader->CreateShaderFromSource( p_ShaderInfo.VertexSource, SHADER_TYPE_VERTEX, p_ShaderInfo.VertexFile ) != FPS_OK ) { std::cout << "[FPS::MaterialManager::CreateShader] <ERROR> " "Failed to compile the vertex shader" << std::endl; return FPS_FAIL; } } if( p_ShaderInfo.Types & SHADER_TYPE_FRAGMENT ) { if( pMaterialShader->CreateShaderFromSource( p_ShaderInfo.FragmentSource, SHADER_TYPE_FRAGMENT, p_ShaderInfo.FragmentFile ) != FPS_OK ) { std::cout << "[FPS::MaterialManager::CreateShader] <ERROR> " "Failed to compile the vertex shader" << std::endl; return FPS_FAIL; } } if( p_ShaderInfo.Types & SHADER_TYPE_GEOMETRY ) { if( pMaterialShader->CreateShaderFromSource( p_ShaderInfo.GeometrySource, SHADER_TYPE_GEOMETRY, p_ShaderInfo.GeometryFile ) != FPS_OK ) { std::cout << "[FPS::MaterialManager::CreateShader] <ERROR> " "Failed to compile the vertex shader" << std::endl; return FPS_FAIL; } } pMaterialShader->GetShaderParameters( p_ShaderParameters ); pMaterialShader->Link( ); pMaterialShader->GetDigest( p_ShaderDigest ); std::pair< std::map< MD5_DIGEST, Shader * >::iterator, bool > ShaderMapResult; ShaderMapResult = m_Shaders.insert( std::pair< MD5_DIGEST, Shader * >( p_ShaderDigest, pMaterialShader ) ); if( ShaderMapResult.second == false ) { // The shader wasn't added, so delete it std::cout << "[FPS::MaterialManager::CreateShader] <INFO> " "Duplicate shader detected, not adding" << std::endl; SafeDelete< Shader >( pMaterialShader ); } return FPS_OK; }
Shader* ShadersLoader::LoadFromFile(const std::string& Filename) { TiXmlDocument doc(Filename.c_str()); if (!doc.LoadFile()) { Logger::Log() << "[ERROR] TinyXML error : " << doc.ErrorDesc() << "\n"; throw CLoadingFailed(Filename, "unable to load xml with TinyXML"); } // Get the root TiXmlHandle hdl(&doc); TiXmlElement *root = hdl.FirstChild("Shader").Element(); // Problem to find the root if (!root) { throw CLoadingFailed(Filename, "unable to find root (Shader)"); } // Get the shader name and display it std::string name; std::string shaderTypeName; TinyXMLGetAttributeValue<std::string>(root, "name", &name); TinyXMLGetAttributeValue<std::string>(root, "type", &shaderTypeName); Logger::Log() << "[INFO] Load shader : " << name << " ( " << shaderTypeName << " ) ... \n"; ShaderType shaderType; if (shaderTypeName == "Basic") shaderType = BASIC_SHADER; else if (shaderTypeName == "GBuffer") shaderType = GBUFFER_SHADER; else throw CException("unknow shader type"); // Load the shader compiler config ShaderCompilerConfig config = LoadShaderCompilerConfig(root); // Get the 2 files name // * Vertex shader TiXmlElement *shadername = root->FirstChildElement("VertexShader"); if (!shadername) { throw CLoadingFailed(Filename, "unable to find VertexShader (Shader)"); } std::string vertexShadername = std::string( shadername->Attribute("filename")); Logger::Log() << " * Vertex shader : " << vertexShadername << "\n"; // * Fragment shader shadername = root->FirstChildElement("FragmentShader"); if (!shadername) { throw CLoadingFailed(Filename, "unable to find VertexShader (Shader)"); } std::string fragmentShadername = std::string( shadername->Attribute("filename")); Logger::Log() << " * Fragment shader : " << fragmentShadername << "\n"; /* * Find full path */ vertexShadername = CMediaManager::Instance().FindMedia(vertexShadername).Fullname(); fragmentShadername = CMediaManager::Instance().FindMedia(fragmentShadername).Fullname(); Shader* shader = 0; shadername = root->FirstChildElement("GeometryShader"); if (shadername != 0) { std::string geometryShadername = std::string( shadername->Attribute("filename")); Logger::Log() << " * Geometry shader : " << geometryShadername << "\n"; geometryShadername = CMediaManager::Instance().FindMedia( geometryShadername).Fullname(); std::string in, out; TinyXMLGetAttributeValue(shadername, "in", &in); TinyXMLGetAttributeValue(shadername, "out", &out); shader = CShaderManager::Instance().loadfromFile( vertexShadername.c_str(), fragmentShadername.c_str(), geometryShadername.c_str(), shaderType, config); shader->SetGeometryShaderParameters(OpenGLEnumFromString(in), OpenGLEnumFromString(out)); } else { Logger::Log() << " * No Geometry shader\n"; // Shader creation .... shader = CShaderManager::Instance().loadfromFile( vertexShadername.c_str(), fragmentShadername.c_str(), shaderType, config); } shader->Link(); // Attrib blinding ... LoadShaderAttributs(shader, root); // Textures uniform LoadShaderTextures(shader, root); // Matrix uniform LoadShaderMatrix(shader, root); // FBO LoadShaderFBO(shader, root); // Materials LoadMaterials(shader, root); // Update all bindings // * Warning : Need to relink after shader->UpdateAll(); return shader; }
Shader* ShaderManager::LoadShader(const string& aVertexShader, const string& aFragmentShader, vector<string> aAttributes) { //Safety check the filenames if(aVertexShader.length() == 0 || aFragmentShader.length() == 0) { Error(false, "Failed to load the shader, either the Vertex shader or fragment shader length is 0"); return nullptr; } //If the asserts are hit either the vertex shader or the fragment shader files have no length assert(aVertexShader.length() > 0); assert(aFragmentShader.length() > 0); //Check to see if they v and f are the same string key = aVertexShader == aFragmentShader ? aVertexShader : aVertexShader + aFragmentShader; //Get the pair from the texture map Shader* shader = m_ShaderMap[key]; //Is the shader pointer null? if(shader == nullptr) { //Determine if GLSL version 140 is supported by this context. //We'll use this info to generate a GLSL shader source string //with the proper version preprocessor string prepended float glLanguageVersion; if(ServiceLocator::GetPlatformLayer()->GetPlatformType() == PlatformType_iOS) { sscanf((char *)glGetString(GL_SHADING_LANGUAGE_VERSION), "OpenGL ES GLSL ES %f", &glLanguageVersion); } else { sscanf((char *)glGetString(GL_SHADING_LANGUAGE_VERSION), "%f", &glLanguageVersion); } //GL_SHADING_LANGUAGE_VERSION returns the version standard version form //with decimals, but the GLSL version preprocessor directive simply //uses integers (thus 1.10 should 110 and 1.40 should be 140, etc.) //We multiply the floating point number by 100 to get a proper //number for the GLSL preprocessor directive GLuint version = (GLuint)(100 * glLanguageVersion); //Get the size of the version preprocessor string info so we know //how much memory to allocate for our sourceString GLsizei versionStringSize = sizeof("#version 123\n"); // if(ServiceLocator::GetPlatformLayer()->GetPlatformType() == PlatformType_iOS) { versionStringSize = sizeof("#version 123 es\n"); } //Was .vsh appended to the filename? If it was, remove it string vertexShader = string(aVertexShader); size_t found = vertexShader.find(".vsh"); if(found != std::string::npos) { vertexShader.erase(found, 4); } //Which directory do we load? bool appendVersion = true; string directory = "Shaders"; if(ServiceLocator::GetPlatformLayer()->GetPlatformType() == PlatformType_iOS && version < 300) { directory = "Shaders/ES2"; appendVersion = false; } //Get the path for the vertex shader file string vertexPath = ServiceLocator::GetPlatformLayer()->GetPathForResourceInDirectory(vertexShader.c_str(), "vsh", directory.c_str()); //Load the vertex shader File vertexShaderFile(vertexPath); //Safety check the vertex shader if(vertexShaderFile.GetBufferSize() == 0) { Error(false, "Failed to load the vertex shader"); return nullptr; } //Allocate memory for the source string including the version preprocessor information GLchar* vertexSource = nullptr; //Do we append a version to the vertex source? if(appendVersion == true) { vertexSource = (GLchar*)malloc(vertexShaderFile.GetBufferSize() + versionStringSize); //Prepend our vertex shader source string with the supported GLSL version so //the shader will work on ES, Legacy, and OpenGL 3.2 Core Profile contexts if(ServiceLocator::GetPlatformLayer()->GetPlatformType() == PlatformType_iOS) { sprintf(vertexSource, "#version %d es\n%s", version, vertexShaderFile.GetBuffer()); } else { sprintf(vertexSource, "#version %d\n%s", version, vertexShaderFile.GetBuffer()); } } else { vertexSource = (GLchar*)malloc(vertexShaderFile.GetBufferSize()); sprintf(vertexSource, "%s", vertexShaderFile.GetBuffer()); } //Was .fsh appended to the filename? If it was, remove it string fragmentShader = string(aFragmentShader); found = fragmentShader.find(".fsh"); if(found != std::string::npos) { fragmentShader.erase(found, 4); } //Get the path for the fragment shader file string fragmentPath = ServiceLocator::GetPlatformLayer()->GetPathForResourceInDirectory(fragmentShader.c_str(), "fsh", directory.c_str()); //Load the fragment shader File fragmentShaderFile(fragmentPath); //Safety check the fragment shader if(fragmentShaderFile.GetBufferSize() == 0) { Error(false, "Failed to load the fragment shader"); return nullptr; } //Allocate memory for the source string including the version preprocessor information GLchar* fragmentSource = nullptr; //Do we append a version to the fragment source? if(appendVersion == true) { fragmentSource = (GLchar*)malloc(fragmentShaderFile.GetBufferSize() + versionStringSize); //Prepend our fragment shader source string with the supported GLSL version so //the shader will work on ES, Legacy, and OpenGL 3.2 Core Profile contexts if(ServiceLocator::GetPlatformLayer()->GetPlatformType() == PlatformType_iOS) { sprintf(fragmentSource, "#version %d es\n%s", version, fragmentShaderFile.GetBuffer()); } else { sprintf(fragmentSource, "#version %d\n%s", version, fragmentShaderFile.GetBuffer()); } } else { fragmentSource = (GLchar*)malloc(fragmentShaderFile.GetBufferSize()); sprintf(fragmentSource, "%s", fragmentShaderFile.GetBuffer()); } //Create a new shader with the vertex and fragment shaders Shader* shader = new Shader(vertexSource, fragmentSource); shader->SetKey(key); //Cycle through the attributes and add them to the shader for(unsigned int i = 0; i < aAttributes.size(); i++) { shader->AddAttribute(aAttributes.at(i).c_str()); } //Link the shader shader->Link(); //Set the shader map pair for the filename key m_ShaderMap[key] = shader; //Free the memory for the vertex and fragment sources free(vertexSource); free(fragmentSource); } //Return the shader object return shader; }