mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 17:10:41 +02:00
fix light crash?
This commit is contained in:
parent
4c6b14bf72
commit
928ea55d95
2 changed files with 72 additions and 75 deletions
|
@ -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
|
// 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
|
// Fetch the current frame stacks from all the stages
|
||||||
// Starting with the Light Frame genreated in previous tasks
|
// Starting with the Light Frame genreated in previous tasks
|
||||||
|
|
||||||
const auto& lightFrame = input.getN<Input>(0);
|
|
||||||
|
|
||||||
const auto setupOutput = task.addJob<RenderShadowSetup>("ShadowSetup", input);
|
const auto setupOutput = task.addJob<RenderShadowSetup>("ShadowSetup", input);
|
||||||
const auto queryResolution = setupOutput.getN<RenderShadowSetup::Output>(1);
|
const auto queryResolution = setupOutput.getN<RenderShadowSetup::Output>(1);
|
||||||
const auto shadowFrame = setupOutput.getN<RenderShadowSetup::Output>(3);
|
const auto shadowFrame = setupOutput.getN<RenderShadowSetup::Output>(3);
|
||||||
|
const auto currentKeyLight = setupOutput.getN<RenderShadowSetup::Output>(4);
|
||||||
// Fetch and cull the items from the scene
|
// Fetch and cull the items from the scene
|
||||||
|
|
||||||
static const auto shadowCasterReceiverFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask);
|
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];
|
antiFrustum = cascadeFrustums[i - 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto cullInputs = CullShadowBounds::Inputs(sortedShapes, shadowFilter, antiFrustum, lightFrame, cascadeSetupOutput.getN<RenderShadowCascadeSetup::Outputs>(2)).asVarying();
|
const auto cullInputs = CullShadowBounds::Inputs(sortedShapes, shadowFilter, antiFrustum, currentKeyLight, cascadeSetupOutput.getN<RenderShadowCascadeSetup::Outputs>(2)).asVarying();
|
||||||
sprintf(jobName, "CullShadowCascade%d", i);
|
sprintf(jobName, "CullShadowCascade%d", i);
|
||||||
const auto culledShadowItemsAndBounds = task.addJob<CullShadowBounds>(jobName, cullInputs);
|
const auto culledShadowItemsAndBounds = task.addJob<CullShadowBounds>(jobName, cullInputs);
|
||||||
|
|
||||||
|
@ -356,16 +355,17 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, c
|
||||||
_shadowFrameCache->_objects.clear();
|
_shadowFrameCache->_objects.clear();
|
||||||
output.edit3() = _shadowFrameCache;
|
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();
|
renderContext->taskFlow.abortTask();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
output.edit4() = currentKeyLight;
|
||||||
|
|
||||||
// Cache old render args
|
// Cache old render args
|
||||||
RenderArgs* args = renderContext->args;
|
RenderArgs* args = renderContext->args;
|
||||||
|
|
||||||
output.edit0() = args->_renderMode;
|
output.edit0() = args->_renderMode;
|
||||||
output.edit1() = glm::ivec2(0, 0);
|
|
||||||
// Save main camera frustum
|
// Save main camera frustum
|
||||||
*_cameraFrustum = args->getViewFrustum();
|
*_cameraFrustum = args->getViewFrustum();
|
||||||
output.edit2() = _cameraFrustum;
|
output.edit2() = _cameraFrustum;
|
||||||
|
@ -373,75 +373,72 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, c
|
||||||
if (!_globalShadowObject) {
|
if (!_globalShadowObject) {
|
||||||
_globalShadowObject = std::make_shared<LightStage::Shadow>(graphics::LightPointer(), SHADOW_MAX_DISTANCE, SHADOW_CASCADE_COUNT);
|
_globalShadowObject = std::make_shared<LightStage::Shadow>(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);
|
_globalShadowObject->setLight(currentKeyLight);
|
||||||
auto& firstCascadeFrustum = firstCascade.getFrustum();
|
_globalShadowObject->setKeylightFrustum(args->getViewFrustum(), SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR);
|
||||||
unsigned int cascadeIndex;
|
|
||||||
|
|
||||||
// Adjust each cascade frustum
|
auto& firstCascade = _globalShadowObject->getCascade(0);
|
||||||
for (cascadeIndex = 0; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) {
|
auto& firstCascadeFrustum = firstCascade.getFrustum();
|
||||||
auto& bias = _bias[cascadeIndex];
|
unsigned int cascadeIndex;
|
||||||
_globalShadowObject->setKeylightCascadeFrustum(cascadeIndex, args->getViewFrustum(),
|
|
||||||
SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR,
|
|
||||||
bias._constant, bias._slope);
|
|
||||||
}
|
|
||||||
|
|
||||||
_shadowFrameCache->pushShadow(_globalShadowObject);
|
// Adjust each cascade frustum
|
||||||
|
for (cascadeIndex = 0; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) {
|
||||||
// Now adjust coarse frustum bounds
|
auto& bias = _bias[cascadeIndex];
|
||||||
auto frustumPosition = firstCascadeFrustum->getPosition();
|
_globalShadowObject->setKeylightCascadeFrustum(cascadeIndex, args->getViewFrustum(),
|
||||||
auto farTopLeft = firstCascadeFrustum->getFarTopLeft() - frustumPosition;
|
SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR,
|
||||||
auto farBottomRight = firstCascadeFrustum->getFarBottomRight() - frustumPosition;
|
bias._constant, bias._slope);
|
||||||
|
|
||||||
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<float>(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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_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<float>(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) {
|
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();
|
outShapes.clear();
|
||||||
outBounds = AABox();
|
outBounds = AABox();
|
||||||
|
|
||||||
const auto& lightFrame = *inputs.get3();
|
const auto currentKeyLight = inputs.get3();
|
||||||
auto cullFunctor = inputs.get4();
|
auto cullFunctor = inputs.get4();
|
||||||
|
|
||||||
render::CullFunctor shadowCullFunctor = [cullFunctor](const RenderArgs* args, const AABox& bounds) {
|
render::CullFunctor shadowCullFunctor = [cullFunctor](const RenderArgs* args, const AABox& bounds) {
|
||||||
return cullFunctor(args, bounds);
|
return cullFunctor(args, bounds);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!filter.selectsNothing()) {
|
if (!filter.selectsNothing() && currentKeyLight) {
|
||||||
auto& details = args->_details.edit(RenderDetails::SHADOW);
|
auto& details = args->_details.edit(RenderDetails::SHADOW);
|
||||||
render::CullTest test(shadowCullFunctor, args, details, antiFrustum);
|
render::CullTest test(shadowCullFunctor, args, details, antiFrustum);
|
||||||
auto scene = args->_scene;
|
auto scene = args->_scene;
|
||||||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||||
assert(lightStage);
|
assert(lightStage);
|
||||||
const auto globalLightDir = lightStage->getCurrentKeyLight(lightFrame)->getDirection();
|
const auto globalLightDir = currentKeyLight->getDirection();
|
||||||
auto castersFilter = render::ItemFilter::Builder(filter).withShadowCaster().build();
|
auto castersFilter = render::ItemFilter::Builder(filter).withShadowCaster().build();
|
||||||
const auto& receiversFilter = filter;
|
const auto& receiversFilter = filter;
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ signals:
|
||||||
class RenderShadowSetup {
|
class RenderShadowSetup {
|
||||||
public:
|
public:
|
||||||
using Input = RenderShadowTask::Input;
|
using Input = RenderShadowTask::Input;
|
||||||
using Output = render::VaryingSet4<RenderArgs::RenderMode, glm::ivec2, ViewFrustumPointer, LightStage::ShadowFramePointer>;
|
using Output = render::VaryingSet5<RenderArgs::RenderMode, glm::ivec2, ViewFrustumPointer, LightStage::ShadowFramePointer, graphics::LightPointer>;
|
||||||
using Config = RenderShadowSetupConfig;
|
using Config = RenderShadowSetupConfig;
|
||||||
using JobModel = render::Job::ModelIO<RenderShadowSetup, Input, Output, Config>;
|
using JobModel = render::Job::ModelIO<RenderShadowSetup, Input, Output, Config>;
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ public:
|
||||||
|
|
||||||
class CullShadowBounds {
|
class CullShadowBounds {
|
||||||
public:
|
public:
|
||||||
using Inputs = render::VaryingSet5<render::ShapeBounds, render::ItemFilter, ViewFrustumPointer, LightStage::FramePointer, RenderShadowTask::CullFunctor>;
|
using Inputs = render::VaryingSet5<render::ShapeBounds, render::ItemFilter, ViewFrustumPointer, graphics::LightPointer, RenderShadowTask::CullFunctor>;
|
||||||
using Outputs = render::VaryingSet2<render::ShapeBounds, AABox>;
|
using Outputs = render::VaryingSet2<render::ShapeBounds, AABox>;
|
||||||
using JobModel = render::Job::ModelIO<CullShadowBounds, Inputs, Outputs>;
|
using JobModel = render::Job::ModelIO<CullShadowBounds, Inputs, Outputs>;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue