overte-HifiExperiments/libraries/render-utils/src/RenderShadowTask.h
2019-01-08 11:47:28 -08:00

171 lines
5.9 KiB
C++

//
// RenderShadowTask.h
// render-utils/src/
//
// Created by Zach Pomerantz on 1/7/2016.
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_RenderShadowTask_h
#define hifi_RenderShadowTask_h
#include <gpu/Framebuffer.h>
#include <gpu/Pipeline.h>
#include <render/CullTask.h>
#include "Shadows_shared.slh"
#include "LightingModel.h"
#include "LightStage.h"
class ViewFrustum;
class RenderShadowMap {
public:
using Inputs = render::VaryingSet3<render::ShapeBounds, AABox, LightStage::ShadowFramePointer>;
using JobModel = render::Job::ModelI<RenderShadowMap, Inputs>;
RenderShadowMap(render::ShapePlumberPointer shapePlumber, unsigned int cascadeIndex) : _shapePlumber{ shapePlumber }, _cascadeIndex{ cascadeIndex } {}
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs);
protected:
render::ShapePlumberPointer _shapePlumber;
unsigned int _cascadeIndex;
};
//class RenderShadowTaskConfig : public render::Task::Config::Persistent {
class RenderShadowTaskConfig : public render::Task::Config {
Q_OBJECT
public:
// RenderShadowTaskConfig() : render::Task::Config::Persistent(QStringList() << "Render" << "Engine" << "Shadows", true) {}
RenderShadowTaskConfig() {}
signals:
void dirty();
};
class RenderShadowTask {
public:
// There is one AABox per shadow cascade
using Input = render::VaryingSet2<LightStage::FramePointer, LightingModelPointer>;
using Output = render::VaryingSet2<render::VaryingArray<AABox, SHADOW_CASCADE_MAX_COUNT>, LightStage::ShadowFramePointer>;
using Config = RenderShadowTaskConfig;
using JobModel = render::Task::ModelIO<RenderShadowTask, Input, Output, Config>;
RenderShadowTask() {}
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cameraCullFunctor, uint8_t tagBits = 0x00, uint8_t tagMask = 0x00);
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 {
Q_OBJECT
Q_PROPERTY(float constantBias0 MEMBER constantBias0 NOTIFY dirty)
Q_PROPERTY(float constantBias1 MEMBER constantBias1 NOTIFY dirty)
Q_PROPERTY(float constantBias2 MEMBER constantBias2 NOTIFY dirty)
Q_PROPERTY(float constantBias3 MEMBER constantBias3 NOTIFY dirty)
Q_PROPERTY(float slopeBias0 MEMBER slopeBias0 NOTIFY dirty)
Q_PROPERTY(float slopeBias1 MEMBER slopeBias1 NOTIFY dirty)
Q_PROPERTY(float slopeBias2 MEMBER slopeBias2 NOTIFY dirty)
Q_PROPERTY(float slopeBias3 MEMBER slopeBias3 NOTIFY dirty)
public:
float constantBias0{ 0.15f };
float constantBias1{ 0.15f };
float constantBias2{ 0.175f };
float constantBias3{ 0.2f };
float slopeBias0{ 0.6f };
float slopeBias1{ 0.6f };
float slopeBias2{ 0.7f };
float slopeBias3{ 0.82f };
signals:
void dirty();
};
class RenderShadowSetup {
public:
using Input = RenderShadowTask::Input;
using Output = render::VaryingSet5<RenderArgs::RenderMode, glm::ivec2, ViewFrustumPointer, LightStage::ShadowFramePointer, graphics::LightPointer>;
using Config = RenderShadowSetupConfig;
using JobModel = render::Job::ModelIO<RenderShadowSetup, Input, Output, Config>;
RenderShadowSetup();
void configure(const Config& configuration);
void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output);
private:
ViewFrustumPointer _cameraFrustum;
ViewFrustumPointer _coarseShadowFrustum;
struct {
float _constant;
float _slope;
} _bias[SHADOW_CASCADE_MAX_COUNT];
LightStage::ShadowFrame::Object _globalShadowObject;
LightStage::ShadowFramePointer _shadowFrameCache;
void setConstantBias(int cascadeIndex, float value);
void setSlopeBias(int cascadeIndex, float value);
};
class RenderShadowCascadeSetup {
public:
using Inputs = LightStage::ShadowFramePointer;
using Outputs = render::VaryingSet3<render::ItemFilter, ViewFrustumPointer, RenderShadowTask::CullFunctor>;
using JobModel = render::Job::ModelIO<RenderShadowCascadeSetup, Inputs, Outputs>;
RenderShadowCascadeSetup(unsigned int cascadeIndex, uint8_t tagBits = 0x00, uint8_t tagMask = 0x00) :
_cascadeIndex(cascadeIndex), _tagBits(tagBits), _tagMask(tagMask) {}
void run(const render::RenderContextPointer& renderContext, const Inputs& input, Outputs& output);
private:
unsigned int _cascadeIndex;
uint8_t _tagBits { 0x00 };
uint8_t _tagMask { 0x00 };
};
class RenderShadowCascadeTeardown {
public:
using Input = render::ItemFilter;
using JobModel = render::Job::ModelI<RenderShadowCascadeTeardown, Input>;
void run(const render::RenderContextPointer& renderContext, const Input& input);
};
class RenderShadowTeardown {
public:
using Input = RenderShadowSetup::Output;
using JobModel = render::Job::ModelI<RenderShadowTeardown, Input>;
void run(const render::RenderContextPointer& renderContext, const Input& input);
};
class CullShadowBounds {
public:
using Inputs = render::VaryingSet5<render::ShapeBounds, render::ItemFilter, ViewFrustumPointer, graphics::LightPointer, RenderShadowTask::CullFunctor>;
using Outputs = render::VaryingSet2<render::ShapeBounds, AABox>;
using JobModel = render::Job::ModelIO<CullShadowBounds, Inputs, Outputs>;
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs);
};
#endif // hifi_RenderShadowTask_h