diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index 5db34c9441..c4199f15b2 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -19,7 +19,7 @@ using RenderArgsPointer = std::shared_ptr; void MainRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred) { - task.addJob("RenderShadowTask", cullFunctor); + task.addJob("RenderShadowTask"); const auto items = task.addJob("FetchCullSort", cullFunctor); assert(items.canCast()); if (!isDeferred) { diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index b576bf774c..da7f6d97fa 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -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(); @@ -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(jobName, i); + const auto shadowFilter = task.addJob(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(); } diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index ce4c3047d8..15651354f1 100644 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -50,9 +50,22 @@ public: using JobModel = render::Task::Model; 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; + using Outputs = render::VaryingSet2; using Config = RenderShadowSetupConfig; using JobModel = render::Job::ModelO; @@ -107,12 +120,13 @@ public: using Outputs = render::ItemFilter; using JobModel = render::Job::ModelO; - 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 { diff --git a/libraries/render-utils/src/RenderViewTask.cpp b/libraries/render-utils/src/RenderViewTask.cpp index c2e43582cd..68585ac437 100644 --- a/libraries/render-utils/src/RenderViewTask.cpp +++ b/libraries/render-utils/src/RenderViewTask.cpp @@ -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(); - // 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", [](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"); const auto items = task.addJob("FetchCullSort", cullFunctor); assert(items.canCast());