void GraphicsGL2::CullScenePass( const GraphicsConfigPass & pass, std::map <std::string, PtrVector <Drawable> > & culled_static_drawlist, std::ostream & error_output) { // for each pass, we have which camera and which draw layer to use // we want to do culling for each unique camera and draw layer combination // use camera/layer as the unique key assert(!pass.draw.empty()); if (pass.draw.back() == "postprocess" || !pass.conditions.Satisfied(conditions)) return; for (std::vector <std::string>::const_iterator d = pass.draw.begin(); d != pass.draw.end(); d++) { // determine if we're dealing with a cubemap render_output_map_type::iterator oi = render_outputs.find(pass.output); if (oi == render_outputs.end()) { ReportOnce(&pass, "Render output "+pass.output+" couldn't be found", error_output); return; } const bool cubemap = (oi->second.IsFBO() && oi->second.RenderToFBO().IsCubemap()); const int cubesides = cubemap ? 6 : 1; std::string cameraname = pass.camera; for (int cubeside = 0; cubeside < cubesides; cubeside++) { if (cubemap) { // build sub-camera // build a name for the sub camera { std::stringstream converter; converter << pass.camera << "_cubeside" << cubeside; cameraname = converter.str(); } // get the base camera camera_map_type::iterator bci = cameras.find(pass.camera); if (bci == cameras.end()) { ReportOnce(&pass, "Camera "+pass.camera+" couldn't be found", error_output); return; } // create our sub-camera GraphicsCamera & cam = cameras[cameraname]; cam = bci->second; // set the sub-camera's properties cam.rot = GetCubeSideOrientation(cubeside, cam.rot, error_output); cam.fov = 90; assert(oi->second.IsFBO()); const FrameBufferObject & fbo = oi->second.RenderToFBO(); cam.w = fbo.GetWidth(); cam.h = fbo.GetHeight(); } std::string key = BuildKey(cameraname, *d); if (pass.cull) { camera_map_type::iterator ci = cameras.find(cameraname); if (ci == cameras.end()) { ReportOnce(&pass, "Camera "+cameraname+" couldn't be found", error_output); return; } GraphicsCamera & cam = ci->second; if (culled_static_drawlist.find(key) == culled_static_drawlist.end()) { Frustum frustum; frustum.Extract(GetProjMatrix(cam).GetArray(), GetViewMatrix(cam).GetArray()); reseatable_reference <AabbTreeNodeAdapter <Drawable> > container = static_drawlist.GetDrawlist().GetByName(*d); if (!container) { ReportOnce(&pass, "Drawable container "+*d+" couldn't be found", error_output); return; } container->Query(frustum, culled_static_drawlist[key]); } } else { reseatable_reference <AabbTreeNodeAdapter <Drawable> > container = static_drawlist.GetDrawlist().GetByName(*d); if (!container) { ReportOnce(&pass, "Drawable container "+*d+" couldn't be found", error_output); return; } container->Query(Aabb<float>::IntersectAlways(), culled_static_drawlist[key]); } } } }
void GraphicsGL3::AssembleDrawMap(std::ostream & /*error_output*/) { //sort the two dimentional drawlist so we get correct ordering std::sort(dynamic_drawlist.twodim.begin(),dynamic_drawlist.twodim.end(),&SortDraworder); drawMap.clear(); // for each pass, we have which camera and which draw groups to use // we want to do culling for each unique camera and draw group combination // use "camera/group" as a unique key string // this is cached to avoid extra memory allocations each frame, so we need to clear old data for (std::map <std::string, std::vector <RenderModelExt*> >::iterator i = cameraDrawGroupDrawLists.begin(); i != cameraDrawGroupDrawLists.end(); i++) { i->second.clear(); } // because the cameraDrawGroupDrawLists are cached, this is how we keep track of which combinations // we have already generated std::set <std::string> cameraDrawGroupCombinationsGenerated; // for each pass, do culling of the dynamic and static drawlists and put the results into the cameraDrawGroupDrawLists std::vector <StringId> passes = renderer.getPassNames(); for (std::vector <StringId>::const_iterator i = passes.begin(); i != passes.end(); i++) { if (renderer.getPassEnabled(*i)) { const std::set <StringId> & passDrawGroups = renderer.getDrawGroups(*i); for (std::set <StringId>::const_iterator g = passDrawGroups.begin(); g != passDrawGroups.end(); g++) { StringId passName = *i; StringId drawGroupName = *g; std::string drawGroupString = stringMap.getString(drawGroupName); std::string cameraDrawGroupKey = getCameraDrawGroupKey(passName, drawGroupName); std::vector <RenderModelExt*> & outDrawList = cameraDrawGroupDrawLists[cameraDrawGroupKey]; // see if we have already generated this combination if (cameraDrawGroupCombinationsGenerated.find(cameraDrawGroupKey) == cameraDrawGroupCombinationsGenerated.end()) { // we need to generate this combination // extract frustum information RenderUniform proj, view; bool doCull = true; /*if (getCameraForPass(passName).empty()) { doCull = false; } else*/ { doCull = !(!doCull || !renderer.getPassUniform(passName, stringMap.addStringId("viewMatrix"), view)); doCull = !(!doCull || !renderer.getPassUniform(passName, stringMap.addStringId("projectionMatrix"), proj)); } Frustum frustum; Frustum * frustumPtr = NULL; if (doCull) { frustum.Extract(&proj.data[0], &view.data[0]); frustumPtr = &frustum; } // assemble dynamic entries reseatable_reference <PtrVector <Drawable> > dynamicDrawablesPtr = dynamic_drawlist.GetByName(drawGroupString); if (dynamicDrawablesPtr) { const std::vector <Drawable*> & dynamicDrawables = *dynamicDrawablesPtr; //AssembleDrawList(dynamicDrawables, outDrawList, frustumPtr, lastCameraPosition); AssembleDrawList(dynamicDrawables, outDrawList, NULL, lastCameraPosition); // TODO: the above line is commented out because frustum culling dynamic drawables doesen't work at the moment; is the object center in the drawable for the car in the correct space?? } // assemble static entries reseatable_reference <AabbTreeNodeAdapter <Drawable> > staticDrawablesPtr = static_drawlist.GetByName(drawGroupString); if (staticDrawablesPtr) { const AabbTreeNodeAdapter <Drawable> & staticDrawables = *staticDrawablesPtr; AssembleDrawList(staticDrawables, outDrawList, frustumPtr, lastCameraPosition); } // if it's requesting the full screen rect draw group, feed it our special drawable if (drawGroupString == "full screen rect") { std::vector <Drawable*> rect; rect.push_back(&fullscreenquad); AssembleDrawList(rect, outDrawList, NULL, lastCameraPosition); } } // use the generated combination in our drawMap drawMap[passName][drawGroupName] = &outDrawList; cameraDrawGroupCombinationsGenerated.insert(cameraDrawGroupKey); } } } /*for (std::map <std::string, std::vector <RenderModelExternal*> >::iterator i = cameraDrawGroupDrawLists.begin(); i != cameraDrawGroupDrawLists.end(); i++) { std::cout << i->first << ": " << i->second.size() << std::endl; } std::cout << "----------" << std::endl;*/ //if (enableContributionCull) std::cout << "Contribution cull count: " << assembler.contributionCullCount << std::endl; //std::cout << "normal_noblend: " << drawGroups[stringMap.addStringId("normal_noblend")].size() << "/" << static_drawlist.GetDrawList().GetByName("normal_noblend")->size() << std::endl; }
void GraphicsGL2::CullScenePass( const GraphicsConfigPass & pass, std::ostream & error_output) { // for each pass, we have which camera and which draw layer to use // we want to do culling for each unique camera and draw layer combination // use camera/layer as the unique key assert(!pass.draw.empty()); if (pass.draw.back() == "postprocess" || !pass.conditions.Satisfied(conditions)) return; for (std::vector <std::string>::const_iterator d = pass.draw.begin(); d != pass.draw.end(); d++) { // determine if we're dealing with a cubemap RenderOutputMap::iterator oi = render_outputs.find(pass.output); if (oi == render_outputs.end()) { ReportOnce(&pass, "Render output "+pass.output+" couldn't be found", error_output); return; } const bool cubemap = (oi->second.IsFBO() && oi->second.RenderToFBO().IsCubemap()); const int cubesides = cubemap ? 6 : 1; std::string cameraname = pass.camera; for (int cubeside = 0; cubeside < cubesides; cubeside++) { if (cubemap) { // build a name for the sub camera { std::ostringstream s; s << pass.camera << "_cubeside" << cubeside; cameraname = s.str(); } // get the base camera CameraMap::iterator bci = cameras.find(pass.camera); if (bci == cameras.end()) { ReportOnce(&pass, "Camera " + pass.camera + " couldn't be found", error_output); return; } // create our sub-camera GraphicsCamera & cam = cameras[cameraname]; cam = bci->second; // set the sub-camera's properties cam.rot = GetCubeSideOrientation(cubeside, cam.rot, error_output); cam.fov = 90; assert(oi->second.IsFBO()); const FrameBufferObject & fbo = oi->second.RenderToFBO(); cam.w = fbo.GetWidth(); cam.h = fbo.GetHeight(); } const std::string drawlist_name = BuildKey(cameraname, *d); CulledDrawList & drawlist = culled_drawlists[drawlist_name]; if (drawlist.valid) break; drawlist.valid = true; if (pass.cull) { // cull static drawlist reseatable_reference <AabbTreeNodeAdapter <Drawable> > container = static_drawlist.GetByName(*d); if (!container) { ReportOnce(&pass, "Drawable container " + *d + " couldn't be found", error_output); return; } CameraMap::iterator ci = cameras.find(cameraname); if (ci == cameras.end()) { ReportOnce(&pass, "Camera " + cameraname + " couldn't be found", error_output); return; } const GraphicsCamera & cam = ci->second; Frustum frustum; frustum.Extract(GetProjMatrix(cam).GetArray(), GetViewMatrix(cam).GetArray()); container->Query(frustum, drawlist.drawables); // cull dynamic drawlist reseatable_reference <PtrVector <Drawable> > container_dynamic = dynamic_drawlist.GetByName(*d); if (!container_dynamic) { ReportOnce(&pass, "Drawable container " + *d + " couldn't be found", error_output); return; } for (size_t i = 0; i < container_dynamic->size(); ++i) { if (!Cull(frustum, *(*container_dynamic)[i])) drawlist.drawables.push_back((*container_dynamic)[i]); } } else { // copy static drawlist reseatable_reference <AabbTreeNodeAdapter <Drawable> > container = static_drawlist.GetByName(*d); if (!container) { ReportOnce(&pass, "Drawable container " + *d + " couldn't be found", error_output); return; } container->Query(Aabb<float>::IntersectAlways(), drawlist.drawables); // copy dynamic drawlist reseatable_reference <PtrVector <Drawable> > container_dynamic = dynamic_drawlist.GetByName(*d); if (!container_dynamic) { ReportOnce(&pass, "Drawable container " + *d + " couldn't be found", error_output); return; } drawlist.drawables.insert( drawlist.drawables.end(), container_dynamic->begin(), container_dynamic->end()); } } } }