RenderModelExternal & DRAWABLE::generateRenderModelData(StringIdMap & stringMap) { // copy data over to the GL3V renderModel object // eventually this should only be done when we update the values, but for now // we call this every time we draw the drawable // cache off the stringId values static StringId diffuseId = stringMap.addStringId("diffuseTexture"); static StringId misc1Id = stringMap.addStringId("misc1Texture"); static StringId misc2Id = stringMap.addStringId("normalMapTexture"); static StringId transformId = stringMap.addStringId("modelMatrix"); static StringId colorId = stringMap.addStringId("colorTint"); // textures if (texturesChanged) { renderModel.clearTextureCache(); renderModel.textures.clear(); if (diffuse_map && !diffuse_map->IsCube()) // for right now, restrict the diffuse map to 2d textures { renderModel.textures.push_back(RenderTextureEntry(diffuseId, diffuse_map->GetID(), GL_TEXTURE_2D)); } if (misc_map1 && !misc_map1->IsCube()) { renderModel.textures.push_back(RenderTextureEntry(misc1Id, misc_map1->GetID(), GL_TEXTURE_2D)); } if (misc_map2 && !misc_map2->IsCube()) { renderModel.textures.push_back(RenderTextureEntry(misc2Id, misc_map2->GetID(), GL_TEXTURE_2D)); } texturesChanged = false; } // uniforms if (uniformsChanged) { renderModel.clearUniformCache(); renderModel.uniforms.clear(); if (transform != MATRIX4<float>()) // only add it if it's not the identity matrix renderModel.uniforms.push_back(RenderUniformEntry(transformId, transform.GetArray(), 16)); if (r != 1 || g != 1 || b != 1 || a != 1) // only add it if it's not the default { float srgb_alpha[4]; srgb_alpha[0] = r < 1 ? pow(r, 2.2f) : r; srgb_alpha[1] = g < 1 ? pow(g, 2.2f) : g; srgb_alpha[2] = b < 1 ? pow(b, 2.2f) : b; srgb_alpha[3] = a; renderModel.uniforms.push_back(RenderUniformEntry(colorId, srgb_alpha, 4)); } uniformsChanged = false; } return renderModel; }
void Renderer::render(unsigned int w, unsigned int h, StringIdMap & stringMap, const std::map <StringId, std::map <StringId, std::vector <RenderModelExternal*> *> > & externalModels, std::ostream & errorOutput) { for (std::vector <RenderPass>::iterator i = passes.begin(); i != passes.end(); i++) { // Extract the appropriate map and generate a drawlist. // A vector of pointers to vectors of RenderModelExternal pointers. std::vector <const std::vector <RenderModelExternal*>*> drawList; // Find the map appropriate to this pass. std::map <StringId, std::map <StringId, std::vector <RenderModelExternal*> *> >::const_iterator drawMapIter = externalModels.find(i->getNameId()); if (drawMapIter != externalModels.end()) // For each draw group that this pass uses, add its models to the draw list. for (std::set <StringId>::const_iterator dg = i->getDrawGroups().begin(); dg != i->getDrawGroups().end(); dg++) { std::map <StringId, std::vector <RenderModelExternal*> *>::const_iterator drawGroupIter = drawMapIter->second.find(*dg); if (drawGroupIter != drawMapIter->second.end()) drawList.push_back(drawGroupIter->second); } if (i->render(gl, w, h, stringMap, drawList, sharedTextures, errorOutput)) { // Render targets have been recreated due to display dimension change. // Call setGlobalTexture to update sharedTextures and let downstream passes know. const std::map <StringId, RenderTexture> & passRTs = passes.back().getRenderTargets(); for (std::map <StringId, RenderTexture>::const_iterator rt = passRTs.begin(); rt != passRTs.end(); rt++) setGlobalTexture(rt->first, RenderTextureEntry(rt->first, rt->second.handle, rt->second.target)); } } }
void Renderer::render(unsigned int w, unsigned int h, StringIdMap & stringMap, const std::map <StringId, std::map <StringId, std::vector <RenderModelExt*> *> > & externalModels, std::ostream & errorOutput) { for (auto & pass : passes) { // Extract the appropriate map and generate a drawlist. // A vector of pointers to vectors of RenderModelExternal pointers. std::vector <const std::vector <RenderModelExt*>*> drawList; // Find the map appropriate to this pass. auto drawMapIter = externalModels.find(pass.getNameId()); if (drawMapIter != externalModels.end()) // For each draw group that this pass uses, add its models to the draw list. for (auto dg : pass.getDrawGroups()) { auto drawGroupIter = drawMapIter->second.find(dg); if (drawGroupIter != drawMapIter->second.end()) drawList.push_back(drawGroupIter->second); } if (pass.render(gl, w, h, stringMap, drawList, sharedTextures, errorOutput)) { // Render targets have been recreated due to display dimension change. // Call setGlobalTexture to update sharedTextures and let downstream passes know. for (const auto & rt : passes.back().getRenderTargets()) setGlobalTexture(rt.first, RenderTextureEntry(rt.first, rt.second.handle, rt.second.target)); } } }
bool Renderer::initialize(const std::vector <RealtimeExportPassInfo> & config, StringIdMap & stringMap, const std::string & shaderPath, unsigned int w,unsigned int h, const std::set <std::string> & globalDefines, std::ostream & errorOutput) { // Clear existing passes. clear(); // Add new passes. int passCount = 0; for (std::vector <RealtimeExportPassInfo>::const_iterator i = config.begin(); i != config.end(); i++, passCount++) { // Create unique names based on the path and define list. std::string vertexShaderName = i->vertexShader; if (!i->vertexShaderDefines.empty()) vertexShaderName += " "+UTILS::implode(i->vertexShaderDefines," "); std::string fragmentShaderName = i->fragmentShader; if (!i->fragmentShaderDefines.empty()) fragmentShaderName += " "+UTILS::implode(i->fragmentShaderDefines," "); // Load shaders from the pass if necessary. if ((shaders.find(vertexShaderName) == shaders.end()) && (!loadShader(shaderPath.empty() ? i->vertexShader : shaderPath+"/"+i->vertexShader, vertexShaderName, mergeSets(i->vertexShaderDefines, globalDefines), GL_VERTEX_SHADER, errorOutput))) return false; if ((shaders.find(fragmentShaderName) == shaders.end()) && (!loadShader(shaderPath.empty() ? i->fragmentShader : shaderPath+"/"+i->fragmentShader, fragmentShaderName, mergeSets(i->fragmentShaderDefines, globalDefines), GL_FRAGMENT_SHADER, errorOutput))) return false; // Note which draw groups the pass uses. for (std::vector <std::string>::const_iterator g = i->drawGroups.begin(); g != i->drawGroups.end(); g++) drawGroupToPasses[stringMap.addStringId(*g)].push_back(passes.size()); // Initialize the pass. int passIdx = passes.size(); passes.push_back(RenderPass()); if (!passes.back().initialize(passCount, *i, stringMap, gl, shaders.find(vertexShaderName)->second, shaders.find(fragmentShaderName)->second, sharedTextures, w, h, errorOutput)) return false; // Put the pass's output render targets into a map so we can feed them to subsequent passes. const std::map <StringId, RenderTexture> & passRTs = passes.back().getRenderTargets(); for (std::map <StringId, RenderTexture>::const_iterator rt = passRTs.begin(); rt != passRTs.end(); rt++) { StringId nameId = rt->first; sharedTextures.insert(std::make_pair(nameId, RenderTextureEntry(nameId, rt->second.handle, rt->second.target))); } // Remember the pass index. passIndexMap[stringMap.addStringId(i->name)] = passIdx; } return true; }
bool GraphicsGL3::ReloadShaders(std::ostream & info_output, std::ostream & error_output) { // reinitialize the entire renderer std::vector <RealtimeExportPassInfo> passInfos; bool passInfosLoaded = joeserialize::LoadObjectFromFile("passList", shaderpath+"/"+rendercfg, passInfos, false, true, info_output, error_output); if (passInfosLoaded) { // strip pass infos from the list that we pass to the renderer if they are disabled int origPassInfoSize = passInfos.size(); for (int i = origPassInfoSize - 1; i >= 0; i--) { std::map <std::string, std::string> & fields = passInfos[i].userDefinedFields; std::map <std::string, std::string>::const_iterator field = fields.find("conditions"); if (field != fields.end()) { GraphicsConfigCondition condition; condition.Parse(field->second); if (!condition.Satisfied(conditions)) { passInfos.erase(passInfos.begin()+i); } } } std::set <std::string> allcapsConditions; for (std::set <std::string>::const_iterator i = conditions.begin(); i != conditions.end(); i++) { std::string s = *i; std::transform(s.begin(), s.end(), s.begin(), upper); allcapsConditions.insert(s); } bool initSuccess = renderer.initialize(passInfos, stringMap, shaderpath, w, h, allcapsConditions, error_output); if (initSuccess) { // assign cameras to each pass std::vector <StringId> passes = renderer.getPassNames(); for (std::vector <StringId>::const_iterator i = passes.begin(); i != passes.end(); i++) { std::map <std::string, std::string> fields = renderer.getUserDefinedFields(*i); std::map <std::string, std::string>::const_iterator field = fields.find("camera"); if (field != fields.end()) passNameToCameraName[stringMap.getString(*i)] = field->second; } // set viewport size float viewportSize[2] = {float(w), float(h)}; RenderUniformEntry viewportSizeUniform(stringMap.addStringId("viewportSize"), viewportSize, 2); renderer.setGlobalUniform(viewportSizeUniform); // set static reflection texture if (static_reflection.GetId()) { renderer.setGlobalTexture(stringMap.addStringId("reflectionCube"), RenderTextureEntry(stringMap.addStringId("reflectionCube"), static_reflection.GetId(), GL_TEXTURE_CUBE_MAP)); } if (initialized) renderer.printRendererStatus(VERBOSITY_MAXIMUM, stringMap, std::cout); } else { error_output << "Initialization of GL3 renderer failed; that's OK, falling back to GL 1 or 2" << std::endl; return false; } } else { error_output << "Unable to load GL3 pass information; that's OK, falling back to GL 1 or 2" << std::endl; return false; } info_output << "GL3 initialization successful" << std::endl; if (initialized) logNextGlFrame = true; return true; }