mirror of
https://github.com/lubosz/overte.git
synced 2025-08-08 04:08:13 +02:00
Added anti frustum test to remove lower cascade objects from higher shadow cascades
This commit is contained in:
parent
1f4671ba17
commit
234cb1e3e6
6 changed files with 63 additions and 14 deletions
|
@ -228,13 +228,26 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende
|
||||||
const auto sortedPipelines = task.addJob<PipelineSortShapes>("PipelineSortShadow", shadowItems);
|
const auto sortedPipelines = task.addJob<PipelineSortShapes>("PipelineSortShadow", shadowItems);
|
||||||
const auto sortedShapes = task.addJob<DepthSortShapes>("DepthSortShadow", sortedPipelines, true);
|
const auto sortedShapes = task.addJob<DepthSortShapes>("DepthSortShadow", sortedPipelines, true);
|
||||||
|
|
||||||
|
render::Varying cascadeFrustums[SHADOW_CASCADE_MAX_COUNT] = {
|
||||||
|
ViewFrustumPointer(),
|
||||||
|
ViewFrustumPointer(),
|
||||||
|
ViewFrustumPointer(),
|
||||||
|
ViewFrustumPointer()
|
||||||
|
};
|
||||||
|
|
||||||
for (auto i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) {
|
for (auto i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) {
|
||||||
char jobName[64];
|
char jobName[64];
|
||||||
sprintf(jobName, "ShadowCascadeSetup%d", i);
|
sprintf(jobName, "ShadowCascadeSetup%d", i);
|
||||||
const auto shadowFilter = task.addJob<RenderShadowCascadeSetup>(jobName, i, _cullFunctor);
|
const auto cascadeSetupOutput = task.addJob<RenderShadowCascadeSetup>(jobName, i, _cullFunctor);
|
||||||
|
const auto shadowFilter = cascadeSetupOutput.getN<RenderShadowCascadeSetup::Outputs>(0);
|
||||||
|
auto antiFrustum = render::Varying(ViewFrustumPointer());
|
||||||
|
cascadeFrustums[i] = cascadeSetupOutput.getN<RenderShadowCascadeSetup::Outputs>(1);
|
||||||
|
if (i > 1) {
|
||||||
|
antiFrustum = cascadeFrustums[i - 2];
|
||||||
|
}
|
||||||
|
|
||||||
// CPU jobs: finer grained culling
|
// CPU jobs: finer grained culling
|
||||||
const auto cullInputs = CullShapeBounds::Inputs(sortedShapes, shadowFilter).asVarying();
|
const auto cullInputs = CullShapeBounds::Inputs(sortedShapes, shadowFilter, antiFrustum).asVarying();
|
||||||
const auto culledShadowItemsAndBounds = task.addJob<CullShapeBounds>("CullShadowCascade", cullInputs, cullFunctor, RenderDetails::SHADOW);
|
const auto culledShadowItemsAndBounds = task.addJob<CullShapeBounds>("CullShadowCascade", cullInputs, cullFunctor, RenderDetails::SHADOW);
|
||||||
|
|
||||||
// GPU jobs: Render to shadow map
|
// GPU jobs: Render to shadow map
|
||||||
|
@ -360,7 +373,7 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon
|
||||||
|
|
||||||
const auto globalShadow = lightStage->getCurrentKeyShadow();
|
const auto globalShadow = lightStage->getCurrentKeyShadow();
|
||||||
if (globalShadow && _cascadeIndex<globalShadow->getCascadeCount()) {
|
if (globalShadow && _cascadeIndex<globalShadow->getCascadeCount()) {
|
||||||
output = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered();
|
output.edit0() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered();
|
||||||
|
|
||||||
// Set the keylight render args
|
// Set the keylight render args
|
||||||
auto& cascade = globalShadow->getCascade(_cascadeIndex);
|
auto& cascade = globalShadow->getCascade(_cascadeIndex);
|
||||||
|
@ -372,8 +385,11 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon
|
||||||
// TODO : maybe adapt that with LOD management system?
|
// TODO : maybe adapt that with LOD management system?
|
||||||
texelSize *= minTexelCount;
|
texelSize *= minTexelCount;
|
||||||
_cullFunctor._minSquareSize = texelSize * texelSize;
|
_cullFunctor._minSquareSize = texelSize * texelSize;
|
||||||
|
|
||||||
|
output.edit1() = cascadeFrustum;
|
||||||
} else {
|
} else {
|
||||||
output = ItemFilter::Builder::nothing();
|
output.edit0() = ItemFilter::Builder::nothing();
|
||||||
|
output.edit1() = ViewFrustumPointer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,7 @@ private:
|
||||||
|
|
||||||
class RenderShadowCascadeSetup {
|
class RenderShadowCascadeSetup {
|
||||||
public:
|
public:
|
||||||
using Outputs = render::ItemFilter;
|
using Outputs = render::VaryingSet2<render::ItemFilter, ViewFrustumPointer>;
|
||||||
using JobModel = render::Job::ModelO<RenderShadowCascadeSetup, Outputs>;
|
using JobModel = render::Job::ModelO<RenderShadowCascadeSetup, Outputs>;
|
||||||
|
|
||||||
RenderShadowCascadeSetup(unsigned int cascadeIndex, RenderShadowTask::CullFunctor& cullFunctor) : _cascadeIndex{ cascadeIndex }, _cullFunctor{ cullFunctor } {}
|
RenderShadowCascadeSetup(unsigned int cascadeIndex, RenderShadowTask::CullFunctor& cullFunctor) : _cascadeIndex{ cascadeIndex }, _cullFunctor{ cullFunctor } {}
|
||||||
|
|
|
@ -24,13 +24,15 @@ struct Test {
|
||||||
CullFunctor _functor;
|
CullFunctor _functor;
|
||||||
RenderArgs* _args;
|
RenderArgs* _args;
|
||||||
RenderDetails::Item& _renderDetails;
|
RenderDetails::Item& _renderDetails;
|
||||||
|
ViewFrustumPointer _antiFrustum;
|
||||||
glm::vec3 _eyePos;
|
glm::vec3 _eyePos;
|
||||||
float _squareTanAlpha;
|
float _squareTanAlpha;
|
||||||
|
|
||||||
Test(CullFunctor& functor, RenderArgs* pargs, RenderDetails::Item& renderDetails) :
|
Test(CullFunctor& functor, RenderArgs* pargs, RenderDetails::Item& renderDetails, ViewFrustumPointer antiFrustum = nullptr) :
|
||||||
_functor(functor),
|
_functor(functor),
|
||||||
_args(pargs),
|
_args(pargs),
|
||||||
_renderDetails(renderDetails) {
|
_renderDetails(renderDetails),
|
||||||
|
_antiFrustum(antiFrustum) {
|
||||||
// FIXME: Keep this code here even though we don't use it yet
|
// FIXME: Keep this code here even though we don't use it yet
|
||||||
/*_eyePos = _args->getViewFrustum().getPosition();
|
/*_eyePos = _args->getViewFrustum().getPosition();
|
||||||
float a = glm::degrees(Octree::getPerspectiveAccuracyAngle(_args->_sizeScale, _args->_boundaryLevelAdjust));
|
float a = glm::degrees(Octree::getPerspectiveAccuracyAngle(_args->_sizeScale, _args->_boundaryLevelAdjust));
|
||||||
|
@ -49,6 +51,15 @@ struct Test {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool antiFrustumTest(const AABox& bound) {
|
||||||
|
assert(_antiFrustum);
|
||||||
|
if (_antiFrustum->boxInsideFrustum(bound)) {
|
||||||
|
_renderDetails._outOfView++;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool solidAngleTest(const AABox& bound) {
|
bool solidAngleTest(const AABox& bound) {
|
||||||
// FIXME: Keep this code here even though we don't use it yet
|
// FIXME: Keep this code here even though we don't use it yet
|
||||||
//auto eyeToPoint = bound.calcCenter() - _eyePos;
|
//auto eyeToPoint = bound.calcCenter() - _eyePos;
|
||||||
|
@ -331,6 +342,7 @@ void CullShapeBounds::run(const RenderContextPointer& renderContext, const Input
|
||||||
|
|
||||||
const auto& inShapes = inputs.get0();
|
const auto& inShapes = inputs.get0();
|
||||||
const auto& filter = inputs.get1();
|
const auto& filter = inputs.get1();
|
||||||
|
const auto& antiFrustum = inputs.get2();
|
||||||
auto& outShapes = outputs.edit0();
|
auto& outShapes = outputs.edit0();
|
||||||
auto& outBounds = outputs.edit1();
|
auto& outBounds = outputs.edit1();
|
||||||
|
|
||||||
|
@ -339,7 +351,7 @@ void CullShapeBounds::run(const RenderContextPointer& renderContext, const Input
|
||||||
|
|
||||||
if (!filter.selectsNothing()) {
|
if (!filter.selectsNothing()) {
|
||||||
auto& details = args->_details.edit(_detailType);
|
auto& details = args->_details.edit(_detailType);
|
||||||
Test test(_cullFunctor, args, details);
|
Test test(_cullFunctor, args, details, antiFrustum);
|
||||||
|
|
||||||
for (auto& inItems : inShapes) {
|
for (auto& inItems : inShapes) {
|
||||||
auto key = inItems.first;
|
auto key = inItems.first;
|
||||||
|
@ -351,13 +363,21 @@ void CullShapeBounds::run(const RenderContextPointer& renderContext, const Input
|
||||||
|
|
||||||
details._considered += (int)inItems.second.size();
|
details._considered += (int)inItems.second.size();
|
||||||
|
|
||||||
for (auto& item : inItems.second) {
|
if (antiFrustum == nullptr) {
|
||||||
if (test.frustumTest(item.bound) && test.solidAngleTest(item.bound)) {
|
for (auto& item : inItems.second) {
|
||||||
outItems->second.emplace_back(item);
|
if (test.solidAngleTest(item.bound) && test.frustumTest(item.bound)) {
|
||||||
outBounds += item.bound;
|
outItems->second.emplace_back(item);
|
||||||
|
outBounds += item.bound;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (auto& item : inItems.second) {
|
||||||
|
if (test.solidAngleTest(item.bound) && test.frustumTest(item.bound) && test.antiFrustumTest(item.bound)) {
|
||||||
|
outItems->second.emplace_back(item);
|
||||||
|
outBounds += item.bound;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
details._rendered += (int)outItems->second.size();
|
details._rendered += (int)outItems->second.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,7 @@ namespace render {
|
||||||
|
|
||||||
class CullShapeBounds {
|
class CullShapeBounds {
|
||||||
public:
|
public:
|
||||||
using Inputs = render::VaryingSet2<ShapeBounds, ItemFilter>;
|
using Inputs = render::VaryingSet3<ShapeBounds, ItemFilter, ViewFrustumPointer>;
|
||||||
using Outputs = render::VaryingSet2<ShapeBounds, AABox>;
|
using Outputs = render::VaryingSet2<ShapeBounds, AABox>;
|
||||||
using JobModel = Job::ModelIO<CullShapeBounds, Inputs, Outputs>;
|
using JobModel = Job::ModelIO<CullShapeBounds, Inputs, Outputs>;
|
||||||
|
|
||||||
|
|
|
@ -280,6 +280,18 @@ bool ViewFrustum::boxIntersectsFrustum(const AABox& box) const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ViewFrustum::boxInsideFrustum(const AABox& box) const {
|
||||||
|
// only check against frustum
|
||||||
|
for (int i = 0; i < NUM_FRUSTUM_PLANES; i++) {
|
||||||
|
const glm::vec3& normal = _planes[i].getNormal();
|
||||||
|
// check distance to nearest box point
|
||||||
|
if (_planes[i].distance(box.getNearestVertex(normal)) < 0.0f) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ViewFrustum::sphereIntersectsKeyhole(const glm::vec3& center, float radius) const {
|
bool ViewFrustum::sphereIntersectsKeyhole(const glm::vec3& center, float radius) const {
|
||||||
// check positive touch against central sphere
|
// check positive touch against central sphere
|
||||||
if (glm::length(center - _position) <= (radius + _centerSphereRadius)) {
|
if (glm::length(center - _position) <= (radius + _centerSphereRadius)) {
|
||||||
|
|
|
@ -104,6 +104,7 @@ public:
|
||||||
bool sphereIntersectsFrustum(const glm::vec3& center, float radius) const;
|
bool sphereIntersectsFrustum(const glm::vec3& center, float radius) const;
|
||||||
bool cubeIntersectsFrustum(const AACube& box) const;
|
bool cubeIntersectsFrustum(const AACube& box) const;
|
||||||
bool boxIntersectsFrustum(const AABox& box) const;
|
bool boxIntersectsFrustum(const AABox& box) const;
|
||||||
|
bool boxInsideFrustum(const AABox& box) const;
|
||||||
|
|
||||||
bool sphereIntersectsKeyhole(const glm::vec3& center, float radius) const;
|
bool sphereIntersectsKeyhole(const glm::vec3& center, float radius) const;
|
||||||
bool cubeIntersectsKeyhole(const AACube& cube) const;
|
bool cubeIntersectsKeyhole(const AACube& cube) const;
|
||||||
|
|
Loading…
Reference in a new issue