bool GraphicsGL3::Init( const std::string & shader_path, unsigned resx, unsigned resy, unsigned antialiasing, bool shadows, int /*shadow_distance*/, int /*shadow_quality*/, int reflection_type, const std::string & static_reflectionmap_file, const std::string & /*static_ambientmap_file*/, int anisotropy, int texturesize, int /*lighting_quality*/, bool bloom, bool normalmaps, bool /*dynamicsky*/, const std::string & render_config, std::ostream & info_output, std::ostream & error_output) { rendercfg = render_config; shaderpath = shader_path; // first, see if we support the required gl version by attempting to initialize the GL wrapper gl.setInfoOutput(info_output); gl.setErrorOutput(error_output); if (!gl.initialize()) { error_output << "Initialization of GL3 failed." << std::endl; return false; } #ifdef _WIN32 // workaround for broken vao implementation Intel/Windows { const std::string vendor = (const char*)glGetString(GL_VENDOR); if (vendor == "Intel") vertex_buffer.BindElementBufferExplicitly(); } #endif // set up our graphical configuration option conditions bool fsaa = (antialiasing > 1); // add the conditions to the set #define ADDCONDITION(x) if (x) conditions.insert(#x) ADDCONDITION(bloom); ADDCONDITION(normalmaps); ADDCONDITION(fsaa); ADDCONDITION(shadows); #undef ADDCONDITION if (reflection_type >= 1) conditions.insert("reflections_low"); if (reflection_type >= 2) conditions.insert("reflections_high"); // load the reflection cubemap if (!static_reflectionmap_file.empty()) { TextureInfo t; t.cube = true; t.verticalcross = true; t.mipmap = true; t.anisotropy = anisotropy; t.maxsize = TextureInfo::Size(texturesize); static_reflection.Load(static_reflectionmap_file, t, error_output); } // this information is needed to initialize the renderer in ReloadShaders w = resx; h = resy; // initialize the renderer bool success = ReloadShaders(info_output, error_output); initialized = success; return success; }
bool GraphicsGL2::EnableShaders(std::ostream & info_output, std::ostream & error_output) { CheckForOpenGLErrors("EnableShaders: start", error_output); // unload shaders glUseProgramObjectARB(0); shaders.clear(); CheckForOpenGLErrors("EnableShaders: shader unload", error_output); // unload inputs/outputs render_outputs.clear(); texture_outputs.clear(); texture_inputs.clear(); CheckForOpenGLErrors("EnableShaders: FBO deinit", error_output); // reload configuration config = GraphicsConfig(); std::string rcpath = shaderpath + "/" + renderconfigfile; if (!config.Load(rcpath, error_output)) { error_output << "EnableShaders: Error loading render configuration file: " << rcpath << std::endl; return false; } bool ssao = (lighting > 0); bool ssao_low = (lighting == 1); bool ssao_high = (lighting == 2); bool reflection_disabled = (reflection_status == REFLECTION_DISABLED); bool reflection_dynamic = (reflection_status == REFLECTION_DYNAMIC); bool shadows_near = shadows; bool shadows_medium = shadows && shadow_distance > 0; bool shadows_far = shadows && shadow_distance > 1; bool shadow_quality_low = shadows && (shadow_quality == 0); bool shadow_quality_medium = shadows && (shadow_quality == 1); bool shadow_quality_high = shadows && (shadow_quality == 2); bool shadow_quality_vhigh = shadows && (shadow_quality == 3); bool shadow_quality_ultra = shadows && (shadow_quality == 4); // for now, map vhigh and ultra to high shadow_quality_high = shadow_quality_high || shadow_quality_vhigh || shadow_quality_ultra; shadow_quality_vhigh = false; shadow_quality_ultra = true; conditions.clear(); if (fsaa > 1) conditions.insert("fsaa"); #define ADDCONDITION(x) if (x) conditions.insert(#x) ADDCONDITION(bloom); ADDCONDITION(normalmaps); ADDCONDITION(ssao); ADDCONDITION(ssao_low); ADDCONDITION(ssao_high); ADDCONDITION(reflection_disabled); ADDCONDITION(reflection_dynamic); ADDCONDITION(shadows_near); ADDCONDITION(shadows_medium); ADDCONDITION(shadows_far); ADDCONDITION(shadow_quality_low); ADDCONDITION(shadow_quality_medium); ADDCONDITION(shadow_quality_high); ADDCONDITION(shadow_quality_vhigh); // ADDCONDITION(shadow_quality_ultra); ADDCONDITION(sky_dynamic); #undef ADDCONDITION // add some common textures if (reflection_status == REFLECTION_STATIC) texture_inputs["reflection_cube"] = static_reflection; texture_inputs["ambient_cube"] = static_ambient; // setup frame buffer textures const bool has_texture_float = GLEW_ARB_texture_float && GLEW_ARB_half_float_pixel; for (std::vector <GraphicsConfigOutput>::const_iterator i = config.outputs.begin(); i != config.outputs.end(); i++) { if (!i->conditions.Satisfied(conditions)) continue; if (texture_outputs.find(i->name) != texture_outputs.end()) { error_output << "Ignore duplicate definiion of output: " << i->name << std::endl; continue; } if (i->type == "framebuffer") { render_outputs[i->name].RenderToFramebuffer(w, h); } else { FrameBufferTexture::Target target = TextureTargetFromString(i->type); FrameBufferTexture::Format format = TextureFormatFromString(i->format); if (!has_texture_float && (format == FrameBufferTexture::RGBA16 || format == FrameBufferTexture::RGB16)) { error_output << "Your video card doesn't support floating point textures." << std::endl; error_output << "Failed to load render output: " << i->name << " " << i->type << std::endl; return false; } // initialize fbtexture int multisampling = (i->multisample < 0) ? fsaa : 0; FrameBufferTexture & fbtex = texture_outputs[i->name]; fbtex.Init( i->width.GetSize(w), i->height.GetSize(h), target, format, (i->filter == "nearest"), i->mipmap, error_output, multisampling, (i->format == "depthshadow")); // register texture as input texture_inputs[i->name] = fbtex; } info_output << "Initialized render output: " << i->name; info_output << (i->type != "framebuffer" ? " (FBO)" : " (framebuffer alias)") << std::endl; } render_outputs["framebuffer"].RenderToFramebuffer(w, h); // gen graphics config shaders map typedef std::map <std::string, const GraphicsConfigShader *> ConfigShaderMap; ConfigShaderMap config_shaders; for (std::vector <GraphicsConfigShader>::const_iterator s = config.shaders.begin(); s != config.shaders.end(); s++) { std::pair <ConfigShaderMap::iterator, bool> result = config_shaders.insert(std::make_pair(s->name, &*s)); if (!result.second) error_output << "Ignore duplicate definition of shader: " << s->name << std::endl; } // setup frame buffer objects and shaders std::vector <std::string> shader_uniforms(Uniforms::str, end(Uniforms::str)); std::vector <std::string> shader_defines; GetShaderDefines(shader_defines); for (std::vector <GraphicsConfigPass>::const_iterator i = config.passes.begin(); i != config.passes.end(); i++) { // check conditions if (!i->conditions.Satisfied(conditions)) continue; // load pass output const std::string & outname = i->output; if (render_outputs.find(outname) == render_outputs.end()) { // collect a list of textures for the outputs std::vector <std::string> outputs = Tokenize(outname, " "); std::vector <FrameBufferTexture*> fbotex; for (std::vector <std::string>::const_iterator o = outputs.begin(); o != outputs.end(); o++) { texture_output_map_type::iterator to = texture_outputs.find(*o); if (to != texture_outputs.end()) { fbotex.push_back(&to->second); } } if (fbotex.empty()) { error_output << "None of these outputs are active: " << outname << std::endl; return false; } // initialize fbo FrameBufferObject & fbo = render_outputs[outname].RenderToFBO(); fbo.Init(glstate, fbotex, error_output); } // load pass shader const std::string & shadername = i->shader; if (shaders.find(shadername) == shaders.end()) { ConfigShaderMap::const_iterator csi = config_shaders.find(shadername); if (csi == config_shaders.end()) { error_output << "Shader not defined: " << shadername << std::endl; return false; } const GraphicsConfigShader * cs = csi->second; std::vector <std::string> defines = Tokenize(cs->defines, " "); defines.reserve(defines.size() + shader_defines.size()); defines.insert(defines.end(), shader_defines.begin(), shader_defines.end()); Shader & shader = shaders[cs->name]; if (!shader.Load( shaderpath + "/" + cs->vertex, shaderpath + "/" + cs->fragment, defines, shader_uniforms, info_output, error_output)) { return false; } } } return true; }