//load, compile and link void Program::LoadShaders(const std::string &name, const std::string &defines) { const std::string filename = std::string("shaders/opengl/") + name; //load, create and compile shaders Shader vs(GL_VERTEX_SHADER, filename + ".vert", defines); Shader fs(GL_FRAGMENT_SHADER, filename + ".frag", defines); //create program, attach shaders and link m_program = glCreateProgram(); if(glIsProgram(m_program)!=GL_TRUE) throw ProgramException(); glAttachShader(m_program, vs.shader); glAttachShader(m_program, fs.shader); //extra attribs, if they exist glBindAttribLocation(m_program, 0, "a_vertex"); glBindAttribLocation(m_program, 1, "a_normal"); glBindAttribLocation(m_program, 2, "a_color"); glBindAttribLocation(m_program, 3, "a_uv0"); glBindAttribLocation(m_program, 4, "a_transform"); glBindFragDataLocation(m_program, 0, "frag_color"); glLinkProgram(m_program); check_glsl_errors(name.c_str(), m_program); //shaders may now be deleted by Shader destructor }
Shader(GLenum type, const std::string &filename, const std::string &defines) { RefCountedPtr<FileSystem::FileData> code = FileSystem::gameDataFiles.ReadFile(filename); if (!code) OS::Error("Could not load %s", filename.c_str()); // Load some common code RefCountedPtr<FileSystem::FileData> logzCode = FileSystem::gameDataFiles.ReadFile("shaders/gl2/logz.glsl"); assert(logzCode); RefCountedPtr<FileSystem::FileData> libsCode = FileSystem::gameDataFiles.ReadFile("shaders/gl2/lib.glsl"); assert(libsCode); AppendSource(s_glslVersion); AppendSource(defines.c_str()); if (type == GL_VERTEX_SHADER) AppendSource("#define VERTEX_SHADER\n"); else AppendSource("#define FRAGMENT_SHADER\n"); AppendSource(logzCode->AsStringRange().StripUTF8BOM()); AppendSource(libsCode->AsStringRange().StripUTF8BOM()); AppendSource(code->AsStringRange().StripUTF8BOM()); shader = glCreateShader(type); Compile(shader); // CheckGLSL may use OS::Warning instead of OS::Error so the game may still (attempt to) run if (!check_glsl_errors(filename.c_str(), shader)) throw ShaderException(); };
Shader(GLenum type, const std::string &filename, const std::string &defines) { RefCountedPtr<FileSystem::FileData> code = FileSystem::gameDataFiles.ReadFile(filename); if (!code.Valid()) Error("Could not load %s", filename.c_str()); // Load some common code RefCountedPtr<FileSystem::FileData> attributesCode = FileSystem::gameDataFiles.ReadFile("shaders/opengl/attributes.glsl"); assert(attributesCode.Valid()); RefCountedPtr<FileSystem::FileData> logzCode = FileSystem::gameDataFiles.ReadFile("shaders/opengl/logz.glsl"); assert(logzCode.Valid()); RefCountedPtr<FileSystem::FileData> libsCode = FileSystem::gameDataFiles.ReadFile("shaders/opengl/lib.glsl"); assert(libsCode.Valid()); AppendSource(s_glslVersion); AppendSource(defines.c_str()); if (type == GL_VERTEX_SHADER) { AppendSource("#define VERTEX_SHADER\n"); } else { AppendSource("#define FRAGMENT_SHADER\n"); } AppendSource(attributesCode->AsStringRange().StripUTF8BOM()); AppendSource(logzCode->AsStringRange().StripUTF8BOM()); AppendSource(libsCode->AsStringRange().StripUTF8BOM()); AppendSource(code->AsStringRange().StripUTF8BOM()); #if 0 static bool s_bDumpShaderSource = true; if (s_bDumpShaderSource) { const char SHADER_OUT_DIR_NAME[] = "shaders"; const char SHADER_OGL_OUT_DIR_NAME[] = "shaders/opengl"; FileSystem::userFiles.MakeDirectory(SHADER_OUT_DIR_NAME); FileSystem::userFiles.MakeDirectory(SHADER_OGL_OUT_DIR_NAME); const std::string outFilename(FileSystem::GetUserDir() + "/" + filename); FILE *tmp = fopen(outFilename.c_str(), "wb"); if(tmp) { Output("%s", filename); for( Uint32 i=0; i<blocks.size(); i++ ) { const char *block = blocks[i]; const GLint sizes = block_sizes[i]; if(block && sizes>0) { fprintf(tmp, "%.*s", sizes, block); } } fclose(tmp); } else { Output("Could not open file %s", outFilename.c_str()); } } #endif shader = glCreateShader(type); if(glIsShader(shader)!=GL_TRUE) throw ShaderException(); Compile(shader); // CheckGLSL may use OS::Warning instead of Error so the game may still (attempt to) run if (!check_glsl_errors(filename.c_str(), shader)) throw ShaderException(); };
//load, compile and link void Program::LoadShaders(const std::string &name, const std::string &defines) { const std::string filename = std::string("shaders/gl2/") + name; //load, create and compile shaders Shader vs(GL_VERTEX_SHADER, filename + ".vert", defines); Shader fs(GL_FRAGMENT_SHADER, filename + ".frag", defines); //create program, attach shaders and link m_program = glCreateProgram(); glAttachShader(m_program, vs.shader); glAttachShader(m_program, fs.shader); glLinkProgram(m_program); check_glsl_errors(name.c_str(), m_program); //shaders may now be deleted by Shader destructor }
Shader(GLenum type, const std::string &filename, const std::string &defines) { RefCountedPtr<FileSystem::FileData> filecode = FileSystem::gameDataFiles.ReadFile(filename); if (!filecode.Valid()) Error("Could not load %s", filename.c_str()); std::string strCode(filecode->AsStringRange().ToString()); size_t found = strCode.find("#include"); while (found != std::string::npos) { // find the name of the file to include const size_t begFilename = strCode.find_first_of("\"", found + 8) + 1; const size_t endFilename = strCode.find_first_of("\"", begFilename + 1); const std::string incFilename = strCode.substr(begFilename, endFilename - begFilename); // check we haven't it already included it (avoids circular dependencies) const std::set<std::string>::const_iterator foundIt = previousIncludes.find(incFilename); if (foundIt != previousIncludes.end()) { Error("Circular, or multiple, include of %s\n", incFilename.c_str()); } else { previousIncludes.insert(incFilename); } // build path for include const std::string incPathBuffer = stringf("shaders/opengl/%0", incFilename); // read included file RefCountedPtr<FileSystem::FileData> incCode = FileSystem::gameDataFiles.ReadFile(incPathBuffer); assert(incCode.Valid()); if (incCode.Valid()) { // replace the #include and filename with the included files text strCode.replace(found, (endFilename + 1) - found, incCode->GetData(), incCode->GetSize()); found = strCode.find("#include"); } else { Error("Could not load %s", incPathBuffer.c_str()); } } // Store the modified text with the included files (if any) const StringRange code(strCode.c_str(), strCode.size()); // Build the final shader text to be compiled AppendSource(s_glslVersion); AppendSource(defines.c_str()); if (type == GL_VERTEX_SHADER) { AppendSource("#define VERTEX_SHADER\n"); } else { AppendSource("#define FRAGMENT_SHADER\n"); } AppendSource(code.StripUTF8BOM()); #if 0 static bool s_bDumpShaderSource = true; if (s_bDumpShaderSource) { const char SHADER_OUT_DIR_NAME[] = "shaders"; const char SHADER_OGL_OUT_DIR_NAME[] = "shaders/opengl"; FileSystem::userFiles.MakeDirectory(SHADER_OUT_DIR_NAME); FileSystem::userFiles.MakeDirectory(SHADER_OGL_OUT_DIR_NAME); const std::string outFilename(FileSystem::GetUserDir() + "/" + filename); FILE *tmp = fopen(outFilename.c_str(), "wb"); if(tmp) { Output("%s", filename); for( Uint32 i=0; i<blocks.size(); i++ ) { const char *block = blocks[i]; const GLint sizes = block_sizes[i]; if(block && sizes>0) { fprintf(tmp, "%.*s", sizes, block); } } fclose(tmp); } else { Output("Could not open file %s", outFilename.c_str()); } } #endif shader = glCreateShader(type); if(glIsShader(shader)!=GL_TRUE) throw ShaderException(); Compile(shader); // CheckGLSL may use OS::Warning instead of Error so the game may still (attempt to) run if (!check_glsl_errors(filename.c_str(), shader)) throw ShaderException(); };