diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index bfa6f5e5d1..5456453d8a 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -61,12 +61,11 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende // FIXME: calling this here before the zones/lights are drawn during the deferred/forward passes means we're actually using the frames from the previous draw // Fetch the current frame stacks from all the stages // Starting with the Light Frame genreated in previous tasks - - const auto& lightFrame = input.getN(0); const auto setupOutput = task.addJob("ShadowSetup", input); const auto queryResolution = setupOutput.getN(1); const auto shadowFrame = setupOutput.getN(3); + const auto currentKeyLight = setupOutput.getN(4); // Fetch and cull the items from the scene static const auto shadowCasterReceiverFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask); @@ -108,7 +107,7 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende antiFrustum = cascadeFrustums[i - 2]; } - const auto cullInputs = CullShadowBounds::Inputs(sortedShapes, shadowFilter, antiFrustum, lightFrame, cascadeSetupOutput.getN(2)).asVarying(); + const auto cullInputs = CullShadowBounds::Inputs(sortedShapes, shadowFilter, antiFrustum, currentKeyLight, cascadeSetupOutput.getN(2)).asVarying(); sprintf(jobName, "CullShadowCascade%d", i); const auto culledShadowItemsAndBounds = task.addJob(jobName, cullInputs); @@ -356,16 +355,17 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, c _shadowFrameCache->_objects.clear(); output.edit3() = _shadowFrameCache; - if (!lightingModel->isShadowEnabled() || !lightStage->getCurrentKeyLight(lightFrame) || !lightStage->getCurrentKeyLight(lightFrame)->getCastShadows()) { + const auto currentKeyLight = lightStage->getCurrentKeyLight(lightFrame); + if (!lightingModel->isShadowEnabled() || !currentKeyLight || !currentKeyLight->getCastShadows()) { renderContext->taskFlow.abortTask(); return; } + output.edit4() = currentKeyLight; // Cache old render args RenderArgs* args = renderContext->args; output.edit0() = args->_renderMode; - output.edit1() = glm::ivec2(0, 0); // Save main camera frustum *_cameraFrustum = args->getViewFrustum(); output.edit2() = _cameraFrustum; @@ -373,75 +373,72 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, c if (!_globalShadowObject) { _globalShadowObject = std::make_shared(graphics::LightPointer(), SHADOW_MAX_DISTANCE, SHADOW_CASCADE_COUNT); } - - const auto theGlobalLight = lightStage->getCurrentKeyLight(lightFrame); - if (theGlobalLight && theGlobalLight->getCastShadows()) { - _globalShadowObject->setLight(theGlobalLight); - _globalShadowObject->setKeylightFrustum(args->getViewFrustum(), SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR); - auto& firstCascade = _globalShadowObject->getCascade(0); - auto& firstCascadeFrustum = firstCascade.getFrustum(); - unsigned int cascadeIndex; + _globalShadowObject->setLight(currentKeyLight); + _globalShadowObject->setKeylightFrustum(args->getViewFrustum(), SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR); - // Adjust each cascade frustum - for (cascadeIndex = 0; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) { - auto& bias = _bias[cascadeIndex]; - _globalShadowObject->setKeylightCascadeFrustum(cascadeIndex, args->getViewFrustum(), - SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR, - bias._constant, bias._slope); - } + auto& firstCascade = _globalShadowObject->getCascade(0); + auto& firstCascadeFrustum = firstCascade.getFrustum(); + unsigned int cascadeIndex; - _shadowFrameCache->pushShadow(_globalShadowObject); - - // Now adjust coarse frustum bounds - auto frustumPosition = firstCascadeFrustum->getPosition(); - auto farTopLeft = firstCascadeFrustum->getFarTopLeft() - frustumPosition; - auto farBottomRight = firstCascadeFrustum->getFarBottomRight() - frustumPosition; - - auto left = glm::dot(farTopLeft, firstCascadeFrustum->getRight()); - auto right = glm::dot(farBottomRight, firstCascadeFrustum->getRight()); - auto top = glm::dot(farTopLeft, firstCascadeFrustum->getUp()); - auto bottom = glm::dot(farBottomRight, firstCascadeFrustum->getUp()); - auto near = firstCascadeFrustum->getNearClip(); - auto far = firstCascadeFrustum->getFarClip(); - - for (cascadeIndex = 1; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) { - auto& cascadeFrustum = _globalShadowObject->getCascade(cascadeIndex).getFrustum(); - - farTopLeft = cascadeFrustum->getFarTopLeft() - frustumPosition; - farBottomRight = cascadeFrustum->getFarBottomRight() - frustumPosition; - - auto cascadeLeft = glm::dot(farTopLeft, cascadeFrustum->getRight()); - auto cascadeRight = glm::dot(farBottomRight, cascadeFrustum->getRight()); - auto cascadeTop = glm::dot(farTopLeft, cascadeFrustum->getUp()); - auto cascadeBottom = glm::dot(farBottomRight, 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); - top = glm::max(top, cascadeTop); - near = glm::min(near, cascadeNear); - far = glm::max(far, cascadeFar); - } - - _coarseShadowFrustum->setPosition(firstCascadeFrustum->getPosition()); - _coarseShadowFrustum->setOrientation(firstCascadeFrustum->getOrientation()); - _coarseShadowFrustum->setProjection(glm::ortho(left, right, bottom, top, near, far)); - _coarseShadowFrustum->calculate(); - - // Push frustum for further culling and selection - args->pushViewFrustum(*_coarseShadowFrustum); - - args->_renderMode = RenderArgs::SHADOW_RENDER_MODE; - - // We want for the octree query enough resolution to catch the details in the lowest cascade. So compute - // the desired resolution for the first cascade frustum and extrapolate it to the coarse frustum. - 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.edit1() = queryResolution; + // Adjust each cascade frustum + for (cascadeIndex = 0; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) { + auto& bias = _bias[cascadeIndex]; + _globalShadowObject->setKeylightCascadeFrustum(cascadeIndex, args->getViewFrustum(), + SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR, + bias._constant, bias._slope); } + + _shadowFrameCache->pushShadow(_globalShadowObject); + + // Now adjust coarse frustum bounds + auto frustumPosition = firstCascadeFrustum->getPosition(); + auto farTopLeft = firstCascadeFrustum->getFarTopLeft() - frustumPosition; + auto farBottomRight = firstCascadeFrustum->getFarBottomRight() - frustumPosition; + + auto left = glm::dot(farTopLeft, firstCascadeFrustum->getRight()); + auto right = glm::dot(farBottomRight, firstCascadeFrustum->getRight()); + auto top = glm::dot(farTopLeft, firstCascadeFrustum->getUp()); + auto bottom = glm::dot(farBottomRight, firstCascadeFrustum->getUp()); + auto near = firstCascadeFrustum->getNearClip(); + auto far = firstCascadeFrustum->getFarClip(); + + for (cascadeIndex = 1; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) { + auto& cascadeFrustum = _globalShadowObject->getCascade(cascadeIndex).getFrustum(); + + farTopLeft = cascadeFrustum->getFarTopLeft() - frustumPosition; + farBottomRight = cascadeFrustum->getFarBottomRight() - frustumPosition; + + auto cascadeLeft = glm::dot(farTopLeft, cascadeFrustum->getRight()); + auto cascadeRight = glm::dot(farBottomRight, cascadeFrustum->getRight()); + auto cascadeTop = glm::dot(farTopLeft, cascadeFrustum->getUp()); + auto cascadeBottom = glm::dot(farBottomRight, 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); + top = glm::max(top, cascadeTop); + near = glm::min(near, cascadeNear); + far = glm::max(far, cascadeFar); + } + + _coarseShadowFrustum->setPosition(firstCascadeFrustum->getPosition()); + _coarseShadowFrustum->setOrientation(firstCascadeFrustum->getOrientation()); + _coarseShadowFrustum->setProjection(glm::ortho(left, right, bottom, top, near, far)); + _coarseShadowFrustum->calculate(); + + // Push frustum for further culling and selection + args->pushViewFrustum(*_coarseShadowFrustum); + + args->_renderMode = RenderArgs::SHADOW_RENDER_MODE; + + // We want for the octree query enough resolution to catch the details in the lowest cascade. So compute + // the desired resolution for the first cascade frustum and extrapolate it to the coarse frustum. + 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.edit1() = queryResolution; } void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderContext, const Inputs& input, Outputs& output) { @@ -539,20 +536,20 @@ void CullShadowBounds::run(const render::RenderContextPointer& renderContext, co outShapes.clear(); outBounds = AABox(); - const auto& lightFrame = *inputs.get3(); + const auto currentKeyLight = inputs.get3(); auto cullFunctor = inputs.get4(); render::CullFunctor shadowCullFunctor = [cullFunctor](const RenderArgs* args, const AABox& bounds) { return cullFunctor(args, bounds); }; - if (!filter.selectsNothing()) { + if (!filter.selectsNothing() && currentKeyLight) { auto& details = args->_details.edit(RenderDetails::SHADOW); render::CullTest test(shadowCullFunctor, args, details, antiFrustum); auto scene = args->_scene; auto lightStage = renderContext->_scene->getStage(); assert(lightStage); - const auto globalLightDir = lightStage->getCurrentKeyLight(lightFrame)->getDirection(); + const auto globalLightDir = currentKeyLight->getDirection(); auto castersFilter = render::ItemFilter::Builder(filter).withShadowCaster().build(); const auto& receiversFilter = filter; diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index 271c3e8200..7e7d59763e 100644 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -104,7 +104,7 @@ signals: class RenderShadowSetup { public: using Input = RenderShadowTask::Input; - using Output = render::VaryingSet4; + using Output = render::VaryingSet5; using Config = RenderShadowSetupConfig; using JobModel = render::Job::ModelIO; @@ -161,7 +161,7 @@ public: class CullShadowBounds { public: - using Inputs = render::VaryingSet5; + using Inputs = render::VaryingSet5; using Outputs = render::VaryingSet2; using JobModel = render::Job::ModelIO;