3
0
Fork 0
mirror of https://github.com/lubosz/overte.git synced 2025-04-26 17:15:37 +02:00

Cleaned up orthographic shadow culling functor

This commit is contained in:
Olivier Prat 2018-02-02 11:09:28 +01:00
parent 3804917cf4
commit 1f4671ba17
4 changed files with 32 additions and 23 deletions

View file

@ -19,7 +19,7 @@
using RenderArgsPointer = std::shared_ptr<RenderArgs>;
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);
assert(items.canCast<RenderFetchCullSortTask::Output>());
if (!isDeferred) {

View file

@ -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) {
cullFunctor = cullFunctor ? cullFunctor : [](const RenderArgs*, const AABox&) { return true; };
void RenderShadowTask::build(JobModel& task, const render::Varying& input, render::Varying& output) {
::CullFunctor cullFunctor = [this](const RenderArgs* args, const AABox& bounds) {
return _cullFunctor(args, bounds);
};
// Prepare the ShapePipeline
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++) {
char jobName[64];
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
const auto cullInputs = CullShapeBounds::Inputs(sortedShapes, shadowFilter).asVarying();
@ -281,8 +283,7 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, O
RenderArgs* args = renderContext->args;
output.edit0() = args->_renderMode;
output.edit1() = args->_sizeScale;
output.edit2() = glm::ivec2(0, 0);
output.edit1() = glm::ivec2(0, 0);
const auto globalShadow = lightStage->getCurrentKeyShadow();
if (globalShadow) {
@ -347,7 +348,7 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, O
glm::ivec2 queryResolution = firstCascade.framebuffer->getSize();
queryResolution.x = int(queryResolution.x * _coarseShadowFrustum->getWidth() / firstCascadeFrustum->getWidth());
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& 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;
auto texelSize = glm::min(cascadeFrustum->getHeight(), cascadeFrustum->getWidth()) / cascade.framebuffer->getSize().x;
// Set the cull threshold to 16 shadow texels.
const auto minTexelCount = 16.0f;
// TODO : maybe adapt that with LOD management system?
texelSize *= minTexelCount;
_cullFunctor._minSquareSize = texelSize * texelSize;
} else {
output = ItemFilter::Builder::nothing();
}
@ -393,5 +395,4 @@ void RenderShadowTeardown::run(const render::RenderContextPointer& renderContext
assert(args->hasViewFrustum());
// Reset the render args
args->_renderMode = input.get0();
args->_sizeScale = input.get1();
}

View file

@ -50,9 +50,22 @@ public:
using JobModel = render::Task::Model<RenderShadowTask, Config>;
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);
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 {
@ -82,7 +95,7 @@ signals:
class RenderShadowSetup {
public:
using Outputs = render::VaryingSet3<RenderArgs::RenderMode, float, glm::ivec2>;
using Outputs = render::VaryingSet2<RenderArgs::RenderMode, glm::ivec2>;
using Config = RenderShadowSetupConfig;
using JobModel = render::Job::ModelO<RenderShadowSetup, Outputs, Config>;
@ -107,12 +120,13 @@ public:
using Outputs = render::ItemFilter;
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);
private:
unsigned int _cascadeIndex;
RenderShadowTask::CullFunctor& _cullFunctor;
};
class RenderShadowCascadeTeardown {

View file

@ -17,13 +17,7 @@
void RenderViewTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, bool isDeferred) {
// auto items = input.get<Input>();
// Shadows use an orthographic projection because they are linked to sunlights
// 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;
});
task.addJob<RenderShadowTask>("RenderShadowTask");
const auto items = task.addJob<RenderFetchCullSortTask>("FetchCullSort", cullFunctor);
assert(items.canCast<RenderFetchCullSortTask::Output>());