mirror of
https://github.com/overte-org/overte.git
synced 2025-04-19 15:43:50 +02:00
Changed shadow task to do a single octree query as well as pipeline/depth sort for all cascades. Still issue with disapearing objects from shadow map with viewpoint
This commit is contained in:
parent
3fa2babec2
commit
d422545c78
6 changed files with 273 additions and 107 deletions
|
@ -213,28 +213,34 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende
|
|||
initZPassPipelines(*shapePlumber, state);
|
||||
}
|
||||
|
||||
const auto coarseFrustum = task.addJob<RenderShadowSetup>("ShadowSetup");
|
||||
const auto setupOutput = task.addJob<RenderShadowSetup>("ShadowSetup");
|
||||
// Fetch and cull the items from the scene
|
||||
static const auto shadowCasterFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered();
|
||||
const auto fetchInput = render::Varying(shadowCasterFilter);
|
||||
const auto shadowSelection = task.addJob<FetchSpatialTree>("FetchShadowTree", fetchInput);
|
||||
const auto selectionInputs = FetchSpatialSelection::Inputs(shadowSelection, shadowCasterFilter).asVarying();
|
||||
const auto shadowItems = task.addJob<FetchSpatialSelection>("FetchShadowSelection", selectionInputs);
|
||||
|
||||
// Sort
|
||||
const auto sortedPipelines = task.addJob<PipelineSortShapes>("PipelineSortShadow", shadowItems);
|
||||
const auto sortedShapes = task.addJob<DepthSortShapes>("DepthSortShadow", sortedPipelines, true);
|
||||
|
||||
for (auto i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) {
|
||||
char jobName[64];
|
||||
sprintf(jobName, "ShadowCascadeSetup%d", i);
|
||||
const auto setupOutput = task.addJob<RenderShadowCascadeSetup>(jobName, i);
|
||||
const auto shadowFilter = setupOutput.getN<RenderShadowCascadeSetup::Outputs>(1);
|
||||
const auto shadowFilter = task.addJob<RenderShadowCascadeSetup>(jobName, i);
|
||||
|
||||
// CPU jobs:
|
||||
// Fetch and cull the items from the scene
|
||||
const auto shadowSelection = task.addJob<FetchSpatialTree>("FetchShadowSelection", shadowFilter);
|
||||
const auto cullInputs = CullSpatialSelection::Inputs(shadowSelection, shadowFilter).asVarying();
|
||||
const auto culledShadowSelection = task.addJob<CullSpatialSelection>("CullShadowSelection", cullInputs, cullFunctor, RenderDetails::SHADOW);
|
||||
|
||||
// Sort
|
||||
const auto sortedPipelines = task.addJob<PipelineSortShapes>("PipelineSortShadowSort", culledShadowSelection);
|
||||
const auto sortedShapesAndBounds = task.addJob<DepthSortShapesAndComputeBounds>("DepthSortShadowMap", sortedPipelines, true);
|
||||
// CPU jobs: finer grained culling
|
||||
const auto cullInputs = CullShapeBounds::Inputs(sortedShapes, shadowFilter).asVarying();
|
||||
const auto culledShadowItemsAndBounds = task.addJob<CullShapeBounds>("CullShadowCascade", cullInputs, cullFunctor, RenderDetails::SHADOW);
|
||||
|
||||
// GPU jobs: Render to shadow map
|
||||
task.addJob<RenderShadowMap>("RenderShadowMap", sortedShapesAndBounds, shapePlumber, i);
|
||||
task.addJob<RenderShadowCascadeTeardown>("ShadowCascadeTeardown", setupOutput);
|
||||
sprintf(jobName, "RenderShadowMap%d", i);
|
||||
task.addJob<RenderShadowMap>(jobName, culledShadowItemsAndBounds, shapePlumber, i);
|
||||
task.addJob<RenderShadowCascadeTeardown>("ShadowCascadeTeardown", shadowFilter);
|
||||
}
|
||||
|
||||
task.addJob<RenderShadowTeardown>("ShadowTeardown", setupOutput);
|
||||
}
|
||||
|
||||
void RenderShadowTask::configure(const Config& configuration) {
|
||||
|
@ -267,16 +273,19 @@ void RenderShadowSetup::setSlopeBias(int cascadeIndex, float value) {
|
|||
_bias[cascadeIndex]._slope = value * value * value * 0.01f;
|
||||
}
|
||||
|
||||
void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, Output& output) {
|
||||
void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, Outputs& output) {
|
||||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||
assert(lightStage);
|
||||
// Cache old render args
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
output.edit0() = args->_renderMode;
|
||||
output.edit1() = args->_sizeScale;
|
||||
|
||||
const auto globalShadow = lightStage->getCurrentKeyShadow();
|
||||
if (globalShadow) {
|
||||
globalShadow->setKeylightFrustum(args->getViewFrustum(), SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR);
|
||||
auto firstCascadeFrustum = globalShadow->getCascade(0).getFrustum();
|
||||
auto& firstCascadeFrustum = globalShadow->getCascade(0).getFrustum();
|
||||
unsigned int cascadeIndex;
|
||||
_coarseShadowFrustum->setPosition(firstCascadeFrustum->getPosition());
|
||||
_coarseShadowFrustum->setOrientation(firstCascadeFrustum->getOrientation());
|
||||
|
@ -296,12 +305,13 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, O
|
|||
auto near = firstCascadeFrustum->getNearClip();
|
||||
auto far = firstCascadeFrustum->getFarClip();
|
||||
for (cascadeIndex = 1; cascadeIndex < globalShadow->getCascadeCount(); ++cascadeIndex) {
|
||||
auto cascadeLeft = glm::dot(firstCascadeFrustum->getFarTopLeft(), firstCascadeFrustum->getRight());
|
||||
auto cascadeRight = glm::dot(firstCascadeFrustum->getFarTopRight(), firstCascadeFrustum->getRight());
|
||||
auto cascadeTop = glm::dot(firstCascadeFrustum->getFarTopLeft(), firstCascadeFrustum->getUp());
|
||||
auto cascadeBottom = glm::dot(firstCascadeFrustum->getFarBottomRight(), firstCascadeFrustum->getUp());
|
||||
auto cascadeNear = firstCascadeFrustum->getNearClip();
|
||||
auto cascadeFar = firstCascadeFrustum->getFarClip();
|
||||
auto& cascadeFrustum = globalShadow->getCascade(cascadeIndex).getFrustum();
|
||||
auto cascadeLeft = glm::dot(cascadeFrustum->getFarTopLeft(), cascadeFrustum->getRight());
|
||||
auto cascadeRight = glm::dot(cascadeFrustum->getFarTopRight(), cascadeFrustum->getRight());
|
||||
auto cascadeTop = glm::dot(cascadeFrustum->getFarTopLeft(), cascadeFrustum->getUp());
|
||||
auto cascadeBottom = glm::dot(cascadeFrustum->getFarBottomRight(), cascadeFrustum->getUp());
|
||||
auto cascadeNear = cascadeFrustum->getNearClip();
|
||||
auto cascadeFar = cascadeFrustum->getFarClip();
|
||||
left = glm::min(left, cascadeLeft);
|
||||
right = glm::max(right, cascadeRight);
|
||||
bottom = glm::min(bottom, cascadeBottom);
|
||||
|
@ -312,9 +322,14 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, O
|
|||
_coarseShadowFrustum->setProjection(glm::ortho<float>(left, right, bottom, top, near, far));
|
||||
_coarseShadowFrustum->calculate();
|
||||
|
||||
output = _coarseShadowFrustum;
|
||||
} else {
|
||||
output = nullptr;
|
||||
// Push frustum for further culling and selection
|
||||
args->pushViewFrustum(*_coarseShadowFrustum);
|
||||
|
||||
args->_renderMode = RenderArgs::SHADOW_RENDER_MODE;
|
||||
if (lightStage->getCurrentKeyLight()->getType() == graphics::Light::SUN) {
|
||||
// Set to ridiculously high amount to prevent solid angle culling in octree selection
|
||||
args->_sizeScale = 1e16f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -324,37 +339,41 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon
|
|||
// Cache old render args
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
output.edit0() = args->_renderMode;
|
||||
output.edit2() = args->_sizeScale;
|
||||
|
||||
const auto globalShadow = lightStage->getCurrentKeyShadow();
|
||||
if (globalShadow && _cascadeIndex<globalShadow->getCascadeCount()) {
|
||||
output.edit1() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered();
|
||||
output = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered();
|
||||
|
||||
// Set the keylight render args
|
||||
args->pushViewFrustum(*(globalShadow->getCascade(_cascadeIndex).getFrustum()));
|
||||
args->_renderMode = RenderArgs::SHADOW_RENDER_MODE;
|
||||
if (lightStage->getCurrentKeyLight()->getType() == graphics::Light::SUN) {
|
||||
const float shadowSizeScale = 1e16f;
|
||||
// Set the size scale to a ridiculously high value to prevent small object culling which assumes
|
||||
// the view frustum is a perspective projection. But this isn't the case for the sun which
|
||||
// is an orthographic projection.
|
||||
args->_sizeScale = shadowSizeScale;
|
||||
}
|
||||
|
||||
auto& cascade = globalShadow->getCascade(_cascadeIndex);
|
||||
auto& cascadeFrustum = cascade.getFrustum();
|
||||
args->pushViewFrustum(*cascadeFrustum);
|
||||
// Set the cull threshold to 2 shadow texels.
|
||||
auto texelSize = glm::max(cascadeFrustum->getHeight(), cascadeFrustum->getWidth()) / cascade.framebuffer->getSize().x;
|
||||
texelSize *= 2.0f;
|
||||
// SizeScale is used in the shadow cull function defined ine RenderViewTask
|
||||
args->_sizeScale = texelSize * texelSize;
|
||||
} else {
|
||||
output.edit1() = ItemFilter::Builder::nothing();
|
||||
output = ItemFilter::Builder::nothing();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderShadowCascadeTeardown::run(const render::RenderContextPointer& renderContext, const Input& input) {
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
if (args->_renderMode == RenderArgs::SHADOW_RENDER_MODE && !input.get1().selectsNothing()) {
|
||||
if (args->_renderMode == RenderArgs::SHADOW_RENDER_MODE && !input.selectsNothing()) {
|
||||
args->popViewFrustum();
|
||||
}
|
||||
assert(args->hasViewFrustum());
|
||||
}
|
||||
|
||||
void RenderShadowTeardown::run(const render::RenderContextPointer& renderContext, const Input& input) {
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
if (args->_renderMode == RenderArgs::SHADOW_RENDER_MODE) {
|
||||
args->popViewFrustum();
|
||||
}
|
||||
assert(args->hasViewFrustum());
|
||||
// Reset the render args
|
||||
args->_renderMode = input.get0();
|
||||
args->_sizeScale = input.get2();
|
||||
};
|
||||
args->_sizeScale = input.get1();
|
||||
}
|
||||
|
|
|
@ -82,13 +82,13 @@ signals:
|
|||
|
||||
class RenderShadowSetup {
|
||||
public:
|
||||
using Output = ViewFrustumPointer;
|
||||
using Outputs = render::VaryingSet2<RenderArgs::RenderMode, float>;
|
||||
using Config = RenderShadowSetupConfig;
|
||||
using JobModel = render::Job::ModelO<RenderShadowSetup, Output, Config>;
|
||||
using JobModel = render::Job::ModelO<RenderShadowSetup, Outputs, Config>;
|
||||
|
||||
RenderShadowSetup();
|
||||
void configure(const Config& configuration);
|
||||
void run(const render::RenderContextPointer& renderContext, Output& output);
|
||||
void run(const render::RenderContextPointer& renderContext, Outputs& output);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -104,7 +104,7 @@ private:
|
|||
|
||||
class RenderShadowCascadeSetup {
|
||||
public:
|
||||
using Outputs = render::VaryingSet3<RenderArgs::RenderMode, render::ItemFilter, float>;
|
||||
using Outputs = render::ItemFilter;
|
||||
using JobModel = render::Job::ModelO<RenderShadowCascadeSetup, Outputs>;
|
||||
|
||||
RenderShadowCascadeSetup(unsigned int cascadeIndex) : _cascadeIndex{ cascadeIndex } {}
|
||||
|
@ -117,9 +117,16 @@ private:
|
|||
|
||||
class RenderShadowCascadeTeardown {
|
||||
public:
|
||||
using Input = RenderShadowCascadeSetup::Outputs;
|
||||
using Input = render::ItemFilter;
|
||||
using JobModel = render::Job::ModelI<RenderShadowCascadeTeardown, Input>;
|
||||
void run(const render::RenderContextPointer& renderContext, const Input& input);
|
||||
};
|
||||
|
||||
class RenderShadowTeardown {
|
||||
public:
|
||||
using Input = RenderShadowSetup::Outputs;
|
||||
using JobModel = render::Job::ModelI<RenderShadowTeardown, Input>;
|
||||
void run(const render::RenderContextPointer& renderContext, const Input& input);
|
||||
};
|
||||
|
||||
#endif // hifi_RenderShadowTask_h
|
||||
|
|
|
@ -21,13 +21,8 @@ void RenderViewTask::build(JobModel& task, const render::Varying& input, render:
|
|||
// but the cullFunctor passed is probably tailored for perspective projection and culls too much.
|
||||
task.addJob<RenderShadowTask>("RenderShadowTask", [](const RenderArgs* args, const AABox& bounds) {
|
||||
// Cull only objects that are too small relatively to shadow frustum
|
||||
auto& frustum = args->getViewFrustum();
|
||||
auto frustumSize = std::max(frustum.getHeight(), frustum.getWidth());
|
||||
const auto boundsRadius = bounds.getDimensions().length();
|
||||
const auto relativeBoundRadius = boundsRadius / frustumSize;
|
||||
const auto threshold = 1e-3f;
|
||||
return relativeBoundRadius > threshold;
|
||||
return true;
|
||||
const auto boundsSquareRadius = glm::dot(bounds.getDimensions(), bounds.getDimensions());
|
||||
return boundsSquareRadius > args->_sizeScale;
|
||||
});
|
||||
|
||||
const auto items = task.addJob<RenderFetchCullSortTask>("FetchCullSort", cullFunctor);
|
||||
|
|
|
@ -19,6 +19,50 @@
|
|||
|
||||
using namespace render;
|
||||
|
||||
// Culling Frustum / solidAngle test helper class
|
||||
struct Test {
|
||||
CullFunctor _functor;
|
||||
RenderArgs* _args;
|
||||
RenderDetails::Item& _renderDetails;
|
||||
glm::vec3 _eyePos;
|
||||
float _squareTanAlpha;
|
||||
|
||||
Test(CullFunctor& functor, RenderArgs* pargs, RenderDetails::Item& renderDetails) :
|
||||
_functor(functor),
|
||||
_args(pargs),
|
||||
_renderDetails(renderDetails) {
|
||||
// FIXME: Keep this code here even though we don't use it yet
|
||||
/*_eyePos = _args->getViewFrustum().getPosition();
|
||||
float a = glm::degrees(Octree::getAccuracyAngle(_args->_sizeScale, _args->_boundaryLevelAdjust));
|
||||
auto angle = std::min(glm::radians(45.0f), a); // no worse than 45 degrees
|
||||
angle = std::max(glm::radians(1.0f / 60.0f), a); // no better than 1 minute of degree
|
||||
auto tanAlpha = tan(angle);
|
||||
_squareTanAlpha = (float)(tanAlpha * tanAlpha);
|
||||
*/
|
||||
}
|
||||
|
||||
bool frustumTest(const AABox& bound) {
|
||||
if (!_args->getViewFrustum().boxIntersectsFrustum(bound)) {
|
||||
_renderDetails._outOfView++;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool solidAngleTest(const AABox& bound) {
|
||||
// FIXME: Keep this code here even though we don't use it yet
|
||||
//auto eyeToPoint = bound.calcCenter() - _eyePos;
|
||||
//auto boundSize = bound.getDimensions();
|
||||
//float test = (glm::dot(boundSize, boundSize) / glm::dot(eyeToPoint, eyeToPoint)) - squareTanAlpha;
|
||||
//if (test < 0.0f) {
|
||||
if (!_functor(_args, bound)) {
|
||||
_renderDetails._tooSmall++;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void render::cullItems(const RenderContextPointer& renderContext, const CullFunctor& cullFunctor, RenderDetails::Item& details,
|
||||
const ItemBounds& inItems, ItemBounds& outItems) {
|
||||
assert(renderContext->args);
|
||||
|
@ -82,18 +126,20 @@ void FetchSpatialTree::configure(const Config& config) {
|
|||
_lodAngle = config.lodAngle;
|
||||
}
|
||||
|
||||
void FetchSpatialTree::run(const RenderContextPointer& renderContext, const ItemFilter& filter, ItemSpatialTree::ItemSelection& outSelection) {
|
||||
void FetchSpatialTree::run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemSpatialTree::ItemSelection& outSelection) {
|
||||
// start fresh
|
||||
outSelection.clear();
|
||||
|
||||
auto& filter = inputs;
|
||||
|
||||
if (!filter.selectsNothing()) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
RenderArgs* args = renderContext->args;
|
||||
auto& scene = renderContext->_scene;
|
||||
|
||||
// Eventually use a frozen frustum
|
||||
auto queryFrustum = args->getViewFrustum();
|
||||
// Eventually use a frozen frustum
|
||||
if (_freezeFrustum) {
|
||||
if (_justFrozeFrustum) {
|
||||
_justFrozeFrustum = false;
|
||||
|
@ -134,50 +180,6 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext,
|
|||
args->pushViewFrustum(_frozenFrustum); // replace the true view frustum by the frozen one
|
||||
}
|
||||
|
||||
// Culling Frustum / solidAngle test helper class
|
||||
struct Test {
|
||||
CullFunctor _functor;
|
||||
RenderArgs* _args;
|
||||
RenderDetails::Item& _renderDetails;
|
||||
glm::vec3 _eyePos;
|
||||
float _squareTanAlpha;
|
||||
|
||||
Test(CullFunctor& functor, RenderArgs* pargs, RenderDetails::Item& renderDetails) :
|
||||
_functor(functor),
|
||||
_args(pargs),
|
||||
_renderDetails(renderDetails)
|
||||
{
|
||||
// FIXME: Keep this code here even though we don't use it yet
|
||||
/*_eyePos = _args->getViewFrustum().getPosition();
|
||||
float a = glm::degrees(Octree::getAccuracyAngle(_args->_sizeScale, _args->_boundaryLevelAdjust));
|
||||
auto angle = std::min(glm::radians(45.0f), a); // no worse than 45 degrees
|
||||
angle = std::max(glm::radians(1.0f / 60.0f), a); // no better than 1 minute of degree
|
||||
auto tanAlpha = tan(angle);
|
||||
_squareTanAlpha = (float)(tanAlpha * tanAlpha);
|
||||
*/
|
||||
}
|
||||
|
||||
bool frustumTest(const AABox& bound) {
|
||||
if (!_args->getViewFrustum().boxIntersectsFrustum(bound)) {
|
||||
_renderDetails._outOfView++;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool solidAngleTest(const AABox& bound) {
|
||||
// FIXME: Keep this code here even though we don't use it yet
|
||||
//auto eyeToPoint = bound.calcCenter() - _eyePos;
|
||||
//auto boundSize = bound.getDimensions();
|
||||
//float test = (glm::dot(boundSize, boundSize) / glm::dot(eyeToPoint, eyeToPoint)) - squareTanAlpha;
|
||||
//if (test < 0.0f) {
|
||||
if (!_functor(_args, bound)) {
|
||||
_renderDetails._tooSmall++;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
Test test(_cullFunctor, args, details);
|
||||
|
||||
// Now we have a selection of items to render
|
||||
|
@ -309,3 +311,112 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext,
|
|||
|
||||
std::static_pointer_cast<Config>(renderContext->jobConfig)->numItems = (int)outItems.size();
|
||||
}
|
||||
|
||||
void CullShapeBounds::run(const RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
const auto& inShapes = inputs.get0();
|
||||
const auto& filter = inputs.get1();
|
||||
auto& outShapes = outputs.edit0();
|
||||
auto& outBounds = outputs.edit1();
|
||||
|
||||
outShapes.clear();
|
||||
outBounds = AABox();
|
||||
|
||||
if (!filter.selectsNothing()) {
|
||||
auto& details = args->_details.edit(_detailType);
|
||||
Test test(_cullFunctor, args, details);
|
||||
|
||||
for (auto& inItems : inShapes) {
|
||||
auto key = inItems.first;
|
||||
auto outItems = outShapes.find(key);
|
||||
if (outItems == outShapes.end()) {
|
||||
outItems = outShapes.insert(std::make_pair(key, ItemBounds{})).first;
|
||||
outItems->second.reserve(inItems.second.size());
|
||||
}
|
||||
|
||||
details._considered += (int)inItems.second.size();
|
||||
|
||||
for (auto& item : inItems.second) {
|
||||
if (test.frustumTest(item.bound) && test.solidAngleTest(item.bound)) {
|
||||
outItems->second.emplace_back(item);
|
||||
outBounds += item.bound;
|
||||
}
|
||||
}
|
||||
|
||||
details._rendered += (int)outItems->second.size();
|
||||
}
|
||||
|
||||
for (auto& items : outShapes) {
|
||||
items.second.shrink_to_fit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FetchSpatialSelection::run(const RenderContextPointer& renderContext,
|
||||
const Inputs& inputs, ItemBounds& outItems) {
|
||||
assert(renderContext->args);
|
||||
RenderArgs* args = renderContext->args;
|
||||
auto& scene = renderContext->_scene;
|
||||
auto& inSelection = inputs.get0();
|
||||
|
||||
// Now we have a selection of items to render
|
||||
outItems.clear();
|
||||
outItems.reserve(inSelection.numItems());
|
||||
|
||||
const auto filter = inputs.get1();
|
||||
if (!filter.selectsNothing()) {
|
||||
// Now get the bound, and
|
||||
// filter individually against the _filter
|
||||
|
||||
// inside & fit items: filter only, culling is disabled
|
||||
{
|
||||
PerformanceTimer perfTimer("insideFitItems");
|
||||
for (auto id : inSelection.insideItems) {
|
||||
auto& item = scene->getItem(id);
|
||||
if (filter.test(item.getKey())) {
|
||||
ItemBound itemBound(id, item.getBound());
|
||||
outItems.emplace_back(itemBound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// inside & subcell items: filter only, culling is disabled
|
||||
{
|
||||
PerformanceTimer perfTimer("insideSmallItems");
|
||||
for (auto id : inSelection.insideSubcellItems) {
|
||||
auto& item = scene->getItem(id);
|
||||
if (filter.test(item.getKey())) {
|
||||
ItemBound itemBound(id, item.getBound());
|
||||
outItems.emplace_back(itemBound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// partial & fit items: filter only, culling is disabled
|
||||
{
|
||||
PerformanceTimer perfTimer("partialFitItems");
|
||||
for (auto id : inSelection.partialItems) {
|
||||
auto& item = scene->getItem(id);
|
||||
if (filter.test(item.getKey())) {
|
||||
ItemBound itemBound(id, item.getBound());
|
||||
outItems.emplace_back(itemBound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// partial & subcell items: filter only, culling is disabled
|
||||
{
|
||||
PerformanceTimer perfTimer("partialSmallItems");
|
||||
for (auto id : inSelection.partialSubcellItems) {
|
||||
auto& item = scene->getItem(id);
|
||||
if (filter.test(item.getKey())) {
|
||||
ItemBound itemBound(id, item.getBound());
|
||||
outItems.emplace_back(itemBound);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,12 +55,13 @@ namespace render {
|
|||
float _lodAngle;
|
||||
public:
|
||||
using Config = FetchSpatialTreeConfig;
|
||||
using JobModel = Job::ModelIO<FetchSpatialTree, ItemFilter, ItemSpatialTree::ItemSelection, Config>;
|
||||
using Inputs = ItemFilter;
|
||||
using JobModel = Job::ModelIO<FetchSpatialTree, Inputs, ItemSpatialTree::ItemSelection, Config>;
|
||||
|
||||
FetchSpatialTree() {}
|
||||
|
||||
void configure(const Config& config);
|
||||
void run(const RenderContextPointer& renderContext, const ItemFilter& filter, ItemSpatialTree::ItemSelection& outSelection);
|
||||
void run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemSpatialTree::ItemSelection& outSelection);
|
||||
};
|
||||
|
||||
class CullSpatialSelectionConfig : public Job::Config {
|
||||
|
@ -96,7 +97,8 @@ namespace render {
|
|||
_detailType(type) {}
|
||||
|
||||
CullSpatialSelection(CullFunctor cullFunctor) :
|
||||
_cullFunctor{ cullFunctor } {}
|
||||
_cullFunctor{ cullFunctor } {
|
||||
}
|
||||
|
||||
CullFunctor _cullFunctor;
|
||||
RenderDetails::Type _detailType{ RenderDetails::OTHER };
|
||||
|
@ -105,6 +107,38 @@ namespace render {
|
|||
void run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems);
|
||||
};
|
||||
|
||||
class CullShapeBounds {
|
||||
public:
|
||||
using Inputs = render::VaryingSet2<ShapeBounds, ItemFilter>;
|
||||
using Outputs = render::VaryingSet2<ShapeBounds, AABox>;
|
||||
using JobModel = Job::ModelIO<CullShapeBounds, Inputs, Outputs>;
|
||||
|
||||
CullShapeBounds(CullFunctor cullFunctor, RenderDetails::Type type) :
|
||||
_cullFunctor{ cullFunctor },
|
||||
_detailType(type) {}
|
||||
|
||||
CullShapeBounds(CullFunctor cullFunctor) :
|
||||
_cullFunctor{ cullFunctor } {
|
||||
}
|
||||
|
||||
void run(const RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs);
|
||||
|
||||
private:
|
||||
|
||||
CullFunctor _cullFunctor;
|
||||
RenderDetails::Type _detailType{ RenderDetails::OTHER };
|
||||
|
||||
};
|
||||
|
||||
class FetchSpatialSelection {
|
||||
public:
|
||||
using Inputs = render::VaryingSet2<ItemSpatialTree::ItemSelection, ItemFilter>;
|
||||
using JobModel = Job::ModelIO<FetchSpatialSelection, Inputs, ItemBounds>;
|
||||
|
||||
FetchSpatialSelection() {}
|
||||
void run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // hifi_render_CullTask_h;
|
|
@ -23,9 +23,9 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin
|
|||
// CPU jobs:
|
||||
// Fetch and cull the items from the scene
|
||||
const ItemFilter filter = ItemFilter::Builder::visibleWorldItems().withoutLayered();
|
||||
const auto spatialFilter = render::Varying(filter);
|
||||
const auto spatialSelection = task.addJob<FetchSpatialTree>("FetchSceneSelection", spatialFilter);
|
||||
const auto cullInputs = CullSpatialSelection::Inputs(spatialSelection, spatialFilter).asVarying();
|
||||
const auto fetchInput = render::Varying(filter);
|
||||
const auto spatialSelection = task.addJob<FetchSpatialTree>("FetchSceneSelection", fetchInput);
|
||||
const auto cullInputs = CullSpatialSelection::Inputs(spatialSelection, render::Varying(filter)).asVarying();
|
||||
const auto culledSpatialSelection = task.addJob<CullSpatialSelection>("CullSceneSelection", cullInputs, cullFunctor, RenderDetails::ITEM);
|
||||
|
||||
// Overlays are not culled
|
||||
|
|
Loading…
Reference in a new issue