cache bounds with item ids in DrawTask

This commit is contained in:
ZappoMan 2015-06-08 09:01:12 -07:00
parent 08ea3368d7
commit 46a8b831fc
3 changed files with 57 additions and 94 deletions

View file

@ -58,7 +58,7 @@ void DrawSceneTask::run(const SceneContextPointer& sceneContext, const RenderCon
Job::~Job() { Job::~Job() {
} }
void render::cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDs& inItems, ItemIDs& outItems) { void render::cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) {
PerformanceTimer perfTimer("cullItems"); PerformanceTimer perfTimer("cullItems");
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->_viewFrustum); assert(renderContext->args->_viewFrustum);
@ -70,8 +70,8 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont
renderDetails->_considered += inItems.size(); renderDetails->_considered += inItems.size();
// Culling / LOD // Culling / LOD
for (auto id : inItems) { for (auto itemDetails : inItems) {
auto item = scene->getItem(id); auto item = scene->getItem(itemDetails.id);
AABox bound; AABox bound;
{ {
PerformanceTimer perfTimer("getBound"); PerformanceTimer perfTimer("getBound");
@ -80,7 +80,7 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont
} }
if (bound.isNull()) { if (bound.isNull()) {
outItems.push_back(id); // One more Item to render outItems.push_back(ItemIDAndBounds(itemDetails.id)); // One more Item to render
continue; continue;
} }
@ -98,7 +98,7 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont
bigEnoughToRender = (args->_shouldRender) ? args->_shouldRender(args, bound) : true; bigEnoughToRender = (args->_shouldRender) ? args->_shouldRender(args, bound) : true;
} }
if (bigEnoughToRender) { if (bigEnoughToRender) {
outItems.push_back(id); // One more Item to render outItems.push_back(ItemIDAndBounds(itemDetails.id, bound)); // One more Item to render
} else { } else {
renderDetails->_tooSmall++; renderDetails->_tooSmall++;
} }
@ -131,7 +131,7 @@ struct BackToFrontSort {
} }
}; };
void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDs& inItems, ItemIDs& outItems) { void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) {
PerformanceTimer perfTimer("depthSortItems"); PerformanceTimer perfTimer("depthSortItems");
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->_viewFrustum); assert(renderContext->args->_viewFrustum);
@ -144,95 +144,47 @@ void render::depthSortItems(const SceneContextPointer& sceneContext, const Rende
outItems.reserve(inItems.size()); outItems.reserve(inItems.size());
#if 0 /// NEW WAY // Make a local dataset of the center distance and closest point distance
{ std::vector<ItemBound> itemBounds;
PerformanceTimer perfTimer("newWay"); itemBounds.reserve(outItems.size());
// TODO: use a QMap<depth,item> which would give us automatic sorting.
QMap<float, ItemID> depths;
QList<ItemID> sortedItems;
{
PerformanceTimer perfTimer("part1");
for (auto id : inItems) { for (auto itemDetails : inItems) {
auto item = scene->getItem(id); auto item = scene->getItem(itemDetails.id);
auto bound = item.getBound(); auto bound = itemDetails.bounds; // item.getBound();
float distance = args->_viewFrustum->distanceToCamera(bound.calcCenter()); float distance = args->_viewFrustum->distanceToCamera(bound.calcCenter());
float key = frontToBack ? -distance : distance;
depths.insertMulti(key, id);
}
}
{
PerformanceTimer perfTimer("part2");
sortedItems = depths.values();
}
{
PerformanceTimer perfTimer("part3");
for ( auto sortedID : sortedItems) {
outItems.emplace_back(sortedID);
}
}
itemBounds.emplace_back(ItemBound(distance, distance, distance, itemDetails.id));
} }
#else /// OLD WAY
{
PerformanceTimer perfTimer("oldWay");
// Make a local dataset of the center distance and closest point distance // sort against Z
std::vector<ItemBound> itemBounds; if (frontToBack) {
{ FrontToBackSort frontToBackSort;
PerformanceTimer perfTimer("part1"); std::sort (itemBounds.begin(), itemBounds.end(), frontToBackSort);
itemBounds.reserve(outItems.size()); } else {
BackToFrontSort backToFrontSort;
for (auto id : inItems) { std::sort (itemBounds.begin(), itemBounds.end(), backToFrontSort);
auto item = scene->getItem(id); }
auto bound = item.getBound();
float distance = args->_viewFrustum->distanceToCamera(bound.calcCenter()); // FInally once sorted result to a list of itemID
for (auto& itemBound : itemBounds) {
itemBounds.emplace_back(ItemBound(distance, distance, distance, id)); outItems.emplace_back(itemBound._id);
}
}
{
PerformanceTimer perfTimer("part2");
// sort against Z
if (frontToBack) {
FrontToBackSort frontToBackSort;
std::sort (itemBounds.begin(), itemBounds.end(), frontToBackSort);
} else {
BackToFrontSort backToFrontSort;
std::sort (itemBounds.begin(), itemBounds.end(), backToFrontSort);
}
}
{
PerformanceTimer perfTimer("part3");
// FInally once sorted result to a list of itemID
for (auto& itemBound : itemBounds) {
outItems.emplace_back(itemBound._id);
}
}
} }
#endif
} }
void render::renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDs& inItems, int maxDrawnItems) { void render::renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, int maxDrawnItems) {
PerformanceTimer perfTimer("renderItems"); PerformanceTimer perfTimer("renderItems");
auto& scene = sceneContext->_scene; auto& scene = sceneContext->_scene;
RenderArgs* args = renderContext->args; RenderArgs* args = renderContext->args;
// render // render
if ((maxDrawnItems < 0) || (maxDrawnItems > inItems.size())) { if ((maxDrawnItems < 0) || (maxDrawnItems > inItems.size())) {
for (auto id : inItems) { for (auto itemDetails : inItems) {
auto item = scene->getItem(id); auto item = scene->getItem(itemDetails.id);
item.render(args); item.render(args);
} }
} else { } else {
int numItems = 0; int numItems = 0;
for (auto id : inItems) { for (auto itemDetails : inItems) {
auto item = scene->getItem(id); auto item = scene->getItem(itemDetails.id);
item.render(args); item.render(args);
numItems++; numItems++;
if (numItems >= maxDrawnItems) { if (numItems >= maxDrawnItems) {
@ -294,16 +246,16 @@ template <> void render::jobRun(const DrawOpaque& job, const SceneContextPointer
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape()); auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape());
auto& renderDetails = renderContext->args->_details; auto& renderDetails = renderContext->args->_details;
ItemIDs inItems; ItemIDsBounds inItems;
inItems.reserve(items.size()); inItems.reserve(items.size());
for (auto id : items) { for (auto id : items) {
inItems.push_back(id); inItems.push_back(ItemIDAndBounds(id));
} }
ItemIDs& renderedItems = inItems; ItemIDsBounds& renderedItems = inItems;
renderContext->_numFeedOpaqueItems = renderedItems.size(); renderContext->_numFeedOpaqueItems = renderedItems.size();
ItemIDs culledItems; ItemIDsBounds culledItems;
if (renderContext->_cullOpaque) { if (renderContext->_cullOpaque) {
renderDetails.pointTo(RenderDetails::OPAQUE_ITEM); renderDetails.pointTo(RenderDetails::OPAQUE_ITEM);
cullItems(sceneContext, renderContext, renderedItems, culledItems); cullItems(sceneContext, renderContext, renderedItems, culledItems);
@ -314,7 +266,7 @@ template <> void render::jobRun(const DrawOpaque& job, const SceneContextPointer
renderContext->_numDrawnOpaqueItems = renderedItems.size(); renderContext->_numDrawnOpaqueItems = renderedItems.size();
ItemIDs sortedItems; ItemIDsBounds sortedItems;
if (renderContext->_sortOpaque) { if (renderContext->_sortOpaque) {
depthSortItems(sceneContext, renderContext, true, renderedItems, sortedItems); // Sort Front to back opaque items! depthSortItems(sceneContext, renderContext, true, renderedItems, sortedItems); // Sort Front to back opaque items!
renderedItems = sortedItems; renderedItems = sortedItems;
@ -360,16 +312,16 @@ template <> void render::jobRun(const DrawTransparent& job, const SceneContextPo
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::transparentShape()); auto& items = scene->getMasterBucket().at(ItemFilter::Builder::transparentShape());
auto& renderDetails = renderContext->args->_details; auto& renderDetails = renderContext->args->_details;
ItemIDs inItems; ItemIDsBounds inItems;
inItems.reserve(items.size()); inItems.reserve(items.size());
for (auto id : items) { for (auto id : items) {
inItems.push_back(id); inItems.push_back(id);
} }
ItemIDs& renderedItems = inItems; ItemIDsBounds& renderedItems = inItems;
renderContext->_numFeedTransparentItems = renderedItems.size(); renderContext->_numFeedTransparentItems = renderedItems.size();
ItemIDs culledItems; ItemIDsBounds culledItems;
if (renderContext->_cullTransparent) { if (renderContext->_cullTransparent) {
renderDetails.pointTo(RenderDetails::TRANSLUCENT_ITEM); renderDetails.pointTo(RenderDetails::TRANSLUCENT_ITEM);
cullItems(sceneContext, renderContext, inItems, culledItems); cullItems(sceneContext, renderContext, inItems, culledItems);
@ -379,7 +331,7 @@ template <> void render::jobRun(const DrawTransparent& job, const SceneContextPo
renderContext->_numDrawnTransparentItems = renderedItems.size(); renderContext->_numDrawnTransparentItems = renderedItems.size();
ItemIDs sortedItems; ItemIDsBounds sortedItems;
if (renderContext->_sortTransparent) { if (renderContext->_sortTransparent) {
depthSortItems(sceneContext, renderContext, false, renderedItems, sortedItems); // Sort Back to front transparent items! depthSortItems(sceneContext, renderContext, false, renderedItems, sortedItems); // Sort Back to front transparent items!
renderedItems = sortedItems; renderedItems = sortedItems;
@ -440,13 +392,13 @@ template <> void render::jobRun(const DrawLight& job, const SceneContextPointer&
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::light()); auto& items = scene->getMasterBucket().at(ItemFilter::Builder::light());
ItemIDs inItems; ItemIDsBounds inItems;
inItems.reserve(items.size()); inItems.reserve(items.size());
for (auto id : items) { for (auto id : items) {
inItems.push_back(id); inItems.push_back(id);
} }
ItemIDs culledItems; ItemIDsBounds culledItems;
cullItems(sceneContext, renderContext, inItems, culledItems); cullItems(sceneContext, renderContext, inItems, culledItems);
RenderArgs* args = renderContext->args; RenderArgs* args = renderContext->args;
@ -467,7 +419,7 @@ template <> void render::jobRun(const DrawBackground& job, const SceneContextPoi
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::background()); auto& items = scene->getMasterBucket().at(ItemFilter::Builder::background());
ItemIDs inItems; ItemIDsBounds inItems;
inItems.reserve(items.size()); inItems.reserve(items.size());
for (auto id : items) { for (auto id : items) {
inItems.push_back(id); inItems.push_back(id);

View file

@ -57,9 +57,9 @@ protected:
typedef std::vector<Job> Jobs; typedef std::vector<Job> Jobs;
void cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDs& inItems, ItemIDs& outITems); void cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outITems);
void depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDs& inItems, ItemIDs& outITems); void depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDsBounds& inItems, ItemIDsBounds& outITems);
void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDs& inItems, int maxDrawnItems = -1); void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1);
class DrawOpaque { class DrawOpaque {

View file

@ -333,6 +333,17 @@ typedef Item::ID ItemID;
typedef std::vector<ItemID> ItemIDs; typedef std::vector<ItemID> ItemIDs;
typedef std::set<ItemID> ItemIDSet; typedef std::set<ItemID> ItemIDSet;
class ItemIDAndBounds {
public:
ItemIDAndBounds(ItemID id) : id(id) { }
ItemIDAndBounds(ItemID id, const AABox& bounds) : id(id), bounds(bounds) { }
ItemID id;
AABox bounds;
};
typedef std::vector< ItemIDAndBounds > ItemIDsBounds;
// A map of ItemIDSets allowing to create bucket lists of items which are filtering correctly // A map of ItemIDSets allowing to create bucket lists of items which are filtering correctly
class ItemBucketMap : public std::map<ItemFilter, ItemIDSet, ItemFilter::Less> { class ItemBucketMap : public std::map<ItemFilter, ItemIDSet, ItemFilter::Less> {
public: public: