mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 10:49:33 +02:00
Cleaned up orthographic shadow culling functor
This commit is contained in:
parent
3804917cf4
commit
1f4671ba17
4 changed files with 32 additions and 23 deletions
|
@ -19,7 +19,7 @@
|
||||||
using RenderArgsPointer = std::shared_ptr<RenderArgs>;
|
using RenderArgsPointer = std::shared_ptr<RenderArgs>;
|
||||||
|
|
||||||
void MainRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred) {
|
void MainRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred) {
|
||||||
task.addJob<RenderShadowTask>("RenderShadowTask", cullFunctor);
|
task.addJob<RenderShadowTask>("RenderShadowTask");
|
||||||
const auto items = task.addJob<RenderFetchCullSortTask>("FetchCullSort", cullFunctor);
|
const auto items = task.addJob<RenderFetchCullSortTask>("FetchCullSort", cullFunctor);
|
||||||
assert(items.canCast<RenderFetchCullSortTask::Output>());
|
assert(items.canCast<RenderFetchCullSortTask::Output>());
|
||||||
if (!isDeferred) {
|
if (!isDeferred) {
|
||||||
|
|
|
@ -200,8 +200,10 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, con
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderShadowTask::build(JobModel& task, const render::Varying& input, render::Varying& output, CullFunctor cullFunctor) {
|
void RenderShadowTask::build(JobModel& task, const render::Varying& input, render::Varying& output) {
|
||||||
cullFunctor = cullFunctor ? cullFunctor : [](const RenderArgs*, const AABox&) { return true; };
|
::CullFunctor cullFunctor = [this](const RenderArgs* args, const AABox& bounds) {
|
||||||
|
return _cullFunctor(args, bounds);
|
||||||
|
};
|
||||||
|
|
||||||
// Prepare the ShapePipeline
|
// Prepare the ShapePipeline
|
||||||
ShapePlumberPointer shapePlumber = std::make_shared<ShapePlumber>();
|
ShapePlumberPointer shapePlumber = std::make_shared<ShapePlumber>();
|
||||||
|
@ -229,7 +231,7 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende
|
||||||
for (auto i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) {
|
for (auto i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) {
|
||||||
char jobName[64];
|
char jobName[64];
|
||||||
sprintf(jobName, "ShadowCascadeSetup%d", i);
|
sprintf(jobName, "ShadowCascadeSetup%d", i);
|
||||||
const auto shadowFilter = task.addJob<RenderShadowCascadeSetup>(jobName, i);
|
const auto shadowFilter = task.addJob<RenderShadowCascadeSetup>(jobName, i, _cullFunctor);
|
||||||
|
|
||||||
// CPU jobs: finer grained culling
|
// CPU jobs: finer grained culling
|
||||||
const auto cullInputs = CullShapeBounds::Inputs(sortedShapes, shadowFilter).asVarying();
|
const auto cullInputs = CullShapeBounds::Inputs(sortedShapes, shadowFilter).asVarying();
|
||||||
|
@ -281,8 +283,7 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, O
|
||||||
RenderArgs* args = renderContext->args;
|
RenderArgs* args = renderContext->args;
|
||||||
|
|
||||||
output.edit0() = args->_renderMode;
|
output.edit0() = args->_renderMode;
|
||||||
output.edit1() = args->_sizeScale;
|
output.edit1() = glm::ivec2(0, 0);
|
||||||
output.edit2() = glm::ivec2(0, 0);
|
|
||||||
|
|
||||||
const auto globalShadow = lightStage->getCurrentKeyShadow();
|
const auto globalShadow = lightStage->getCurrentKeyShadow();
|
||||||
if (globalShadow) {
|
if (globalShadow) {
|
||||||
|
@ -347,7 +348,7 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, O
|
||||||
glm::ivec2 queryResolution = firstCascade.framebuffer->getSize();
|
glm::ivec2 queryResolution = firstCascade.framebuffer->getSize();
|
||||||
queryResolution.x = int(queryResolution.x * _coarseShadowFrustum->getWidth() / firstCascadeFrustum->getWidth());
|
queryResolution.x = int(queryResolution.x * _coarseShadowFrustum->getWidth() / firstCascadeFrustum->getWidth());
|
||||||
queryResolution.y = int(queryResolution.y * _coarseShadowFrustum->getHeight() / firstCascadeFrustum->getHeight());
|
queryResolution.y = int(queryResolution.y * _coarseShadowFrustum->getHeight() / firstCascadeFrustum->getHeight());
|
||||||
output.edit2() = queryResolution;
|
output.edit1() = queryResolution;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,11 +366,12 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon
|
||||||
auto& cascade = globalShadow->getCascade(_cascadeIndex);
|
auto& cascade = globalShadow->getCascade(_cascadeIndex);
|
||||||
auto& cascadeFrustum = cascade.getFrustum();
|
auto& cascadeFrustum = cascade.getFrustum();
|
||||||
args->pushViewFrustum(*cascadeFrustum);
|
args->pushViewFrustum(*cascadeFrustum);
|
||||||
// Set the cull threshold to 2 shadow texels.
|
auto texelSize = glm::min(cascadeFrustum->getHeight(), cascadeFrustum->getWidth()) / cascade.framebuffer->getSize().x;
|
||||||
auto texelSize = glm::max(cascadeFrustum->getHeight(), cascadeFrustum->getWidth()) / cascade.framebuffer->getSize().x;
|
// Set the cull threshold to 16 shadow texels.
|
||||||
texelSize *= 2.0f;
|
const auto minTexelCount = 16.0f;
|
||||||
// SizeScale is used in the shadow cull function defined ine RenderViewTask
|
// TODO : maybe adapt that with LOD management system?
|
||||||
args->_sizeScale = texelSize * texelSize;
|
texelSize *= minTexelCount;
|
||||||
|
_cullFunctor._minSquareSize = texelSize * texelSize;
|
||||||
} else {
|
} else {
|
||||||
output = ItemFilter::Builder::nothing();
|
output = ItemFilter::Builder::nothing();
|
||||||
}
|
}
|
||||||
|
@ -393,5 +395,4 @@ void RenderShadowTeardown::run(const render::RenderContextPointer& renderContext
|
||||||
assert(args->hasViewFrustum());
|
assert(args->hasViewFrustum());
|
||||||
// Reset the render args
|
// Reset the render args
|
||||||
args->_renderMode = input.get0();
|
args->_renderMode = input.get0();
|
||||||
args->_sizeScale = input.get1();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,9 +50,22 @@ public:
|
||||||
using JobModel = render::Task::Model<RenderShadowTask, Config>;
|
using JobModel = render::Task::Model<RenderShadowTask, Config>;
|
||||||
|
|
||||||
RenderShadowTask() {}
|
RenderShadowTask() {}
|
||||||
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor shouldRender);
|
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs);
|
||||||
|
|
||||||
void configure(const Config& configuration);
|
void configure(const Config& configuration);
|
||||||
|
|
||||||
|
struct CullFunctor {
|
||||||
|
float _minSquareSize{ 0.0f };
|
||||||
|
|
||||||
|
bool operator()(const RenderArgs* args, const AABox& bounds) const {
|
||||||
|
// Cull only objects that are too small relatively to shadow frustum
|
||||||
|
const auto boundsSquareRadius = glm::dot(bounds.getDimensions(), bounds.getDimensions());
|
||||||
|
return boundsSquareRadius > _minSquareSize;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CullFunctor _cullFunctor;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class RenderShadowSetupConfig : public render::Job::Config {
|
class RenderShadowSetupConfig : public render::Job::Config {
|
||||||
|
@ -82,7 +95,7 @@ signals:
|
||||||
|
|
||||||
class RenderShadowSetup {
|
class RenderShadowSetup {
|
||||||
public:
|
public:
|
||||||
using Outputs = render::VaryingSet3<RenderArgs::RenderMode, float, glm::ivec2>;
|
using Outputs = render::VaryingSet2<RenderArgs::RenderMode, glm::ivec2>;
|
||||||
using Config = RenderShadowSetupConfig;
|
using Config = RenderShadowSetupConfig;
|
||||||
using JobModel = render::Job::ModelO<RenderShadowSetup, Outputs, Config>;
|
using JobModel = render::Job::ModelO<RenderShadowSetup, Outputs, Config>;
|
||||||
|
|
||||||
|
@ -107,12 +120,13 @@ public:
|
||||||
using Outputs = render::ItemFilter;
|
using Outputs = render::ItemFilter;
|
||||||
using JobModel = render::Job::ModelO<RenderShadowCascadeSetup, Outputs>;
|
using JobModel = render::Job::ModelO<RenderShadowCascadeSetup, Outputs>;
|
||||||
|
|
||||||
RenderShadowCascadeSetup(unsigned int cascadeIndex) : _cascadeIndex{ cascadeIndex } {}
|
RenderShadowCascadeSetup(unsigned int cascadeIndex, RenderShadowTask::CullFunctor& cullFunctor) : _cascadeIndex{ cascadeIndex }, _cullFunctor{ cullFunctor } {}
|
||||||
void run(const render::RenderContextPointer& renderContext, Outputs& output);
|
void run(const render::RenderContextPointer& renderContext, Outputs& output);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
unsigned int _cascadeIndex;
|
unsigned int _cascadeIndex;
|
||||||
|
RenderShadowTask::CullFunctor& _cullFunctor;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RenderShadowCascadeTeardown {
|
class RenderShadowCascadeTeardown {
|
||||||
|
|
|
@ -17,13 +17,7 @@
|
||||||
void RenderViewTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, bool isDeferred) {
|
void RenderViewTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, bool isDeferred) {
|
||||||
// auto items = input.get<Input>();
|
// auto items = input.get<Input>();
|
||||||
|
|
||||||
// Shadows use an orthographic projection because they are linked to sunlights
|
task.addJob<RenderShadowTask>("RenderShadowTask");
|
||||||
// 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
|
|
||||||
const auto boundsSquareRadius = glm::dot(bounds.getDimensions(), bounds.getDimensions());
|
|
||||||
return boundsSquareRadius > args->_sizeScale;
|
|
||||||
});
|
|
||||||
|
|
||||||
const auto items = task.addJob<RenderFetchCullSortTask>("FetchCullSort", cullFunctor);
|
const auto items = task.addJob<RenderFetchCullSortTask>("FetchCullSort", cullFunctor);
|
||||||
assert(items.canCast<RenderFetchCullSortTask::Output>());
|
assert(items.canCast<RenderFetchCullSortTask::Output>());
|
||||||
|
|
Loading…
Reference in a new issue