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:
parent
3804917cf4
commit
1f4671ba17
4 changed files with 32 additions and 23 deletions
interface/src
libraries/render-utils/src
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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>());
|
||||
|
|
Loading…
Reference in a new issue