Added Cascade subclass in LightStage Shadow

This commit is contained in:
Olivier Prat 2017-11-10 14:55:49 +01:00
parent 7fd03bed7e
commit e0b36b800f
6 changed files with 64 additions and 37 deletions

View file

@ -438,7 +438,7 @@ void DebugDeferredBuffer::run(const RenderContextPointer& renderContext, const I
auto lightAndShadow = lightStage->getCurrentKeyLightAndShadow();
const auto& globalShadow = lightAndShadow.second;
if (globalShadow) {
batch.setResourceTexture(Shadow, globalShadow->map);
batch.setResourceTexture(Shadow, globalShadow->getCascade(0).map);
}
if (linearDepthTarget) {

View file

@ -503,7 +503,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
// Bind the shadow buffer
if (globalShadow) {
batch.setResourceTexture(SHADOW_MAP_UNIT, globalShadow->map);
batch.setResourceTexture(SHADOW_MAP_UNIT, globalShadow->getCascade(0).map);
}
auto& program = deferredLightingEffect->_directionalSkyboxLight;

View file

@ -28,20 +28,34 @@ LightStage::Shadow::Schema::Schema() {
defaultTransform.bias = 0.005f;
std::fill(cascades, cascades + SHADOW_CASCADE_MAX_COUNT, defaultTransform);
invMapSize = 1.0f / MAP_SIZE;
cascadeCount = 1;
}
LightStage::Shadow::Shadow(model::LightPointer light) : _light{ light}, _frustum{ std::make_shared<ViewFrustum>() } {
LightStage::Shadow::Cascade::Cascade() : _frustum{ std::make_shared<ViewFrustum>() } {
framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(MAP_SIZE));
map = framebuffer->getDepthStencilBuffer();
Schema schema;
_schemaBuffer = std::make_shared<gpu::Buffer>(sizeof(Schema), (const gpu::Byte*) &schema);
}
void LightStage::Shadow::setKeylightFrustum(const ViewFrustum& viewFrustum,
const glm::mat4& LightStage::Shadow::Cascade::getView() const {
return _frustum->getView();
}
const glm::mat4& LightStage::Shadow::Cascade::getProjection() const {
return _frustum->getProjection();
}
LightStage::Shadow::Shadow(model::LightPointer light, unsigned int cascadeCount) : _light{ light } {
Schema schema;
_schemaBuffer = std::make_shared<gpu::Buffer>(sizeof(Schema), (const gpu::Byte*) &schema);
_cascades.resize(cascadeCount);
}
void LightStage::Shadow::setKeylightFrustum(unsigned int cascadeIndex, const ViewFrustum& viewFrustum,
float viewMinShadowDistance, float viewMaxShadowDistance,
float nearDepth, float farDepth) {
assert(viewMinShadowDistance < viewMaxShadowDistance);
assert(nearDepth < farDepth);
assert(cascadeIndex < _cascades.size());
// Orient the keylight frustum
const auto& direction = glm::normalize(_light->getDirection());
@ -55,12 +69,15 @@ void LightStage::Shadow::setKeylightFrustum(const ViewFrustum& viewFrustum,
auto up = glm::normalize(glm::cross(side, direction));
orientation = glm::quat_cast(glm::mat3(side, up, -direction));
}
_frustum->setOrientation(orientation);
auto& cascade = _cascades[cascadeIndex];
cascade._frustum->setOrientation(orientation);
// Position the keylight frustum
_frustum->setPosition(viewFrustum.getPosition() - (nearDepth + farDepth)*direction);
cascade._frustum->setPosition(viewFrustum.getPosition() - (nearDepth + farDepth)*direction);
const Transform view{ _frustum->getView()};
const Transform view{ cascade._frustum->getView()};
const Transform viewInverse{ view.getInverseMatrix() };
auto nearCorners = viewFrustum.getCorners(viewMinShadowDistance);
@ -92,30 +109,24 @@ void LightStage::Shadow::setKeylightFrustum(const ViewFrustum& viewFrustum,
auto near = glm::max(max.z, -nearDepth);
auto far = -min.z;
glm::mat4 ortho = glm::ortho<float>(min.x, max.x, min.y, max.y, near, far);
_frustum->setProjection(ortho);
cascade._frustum->setProjection(ortho);
// Calculate the frustum's internal state
_frustum->calculate();
cascade._frustum->calculate();
// Update the buffer
_schemaBuffer.edit<Schema>().cascades[0].reprojection = _biasMatrix * ortho * viewInverse.getMatrix();
_schemaBuffer.edit<Schema>().cascades[cascadeIndex].reprojection = _biasMatrix * ortho * viewInverse.getMatrix();
}
void LightStage::Shadow::setFrustum(const ViewFrustum& shadowFrustum) {
void LightStage::Shadow::setFrustum(unsigned int cascadeIndex, const ViewFrustum& shadowFrustum) {
assert(cascadeIndex < _cascades.size());
const Transform view{ shadowFrustum.getView() };
const Transform viewInverse{ view.getInverseMatrix() };
auto& cascade = _cascades[cascadeIndex];
*_frustum = shadowFrustum;
*cascade._frustum = shadowFrustum;
// Update the buffer
_schemaBuffer.edit<Schema>().cascades[0].reprojection = _biasMatrix * shadowFrustum.getProjection() * viewInverse.getMatrix();
}
const glm::mat4& LightStage::Shadow::getView() const {
return _frustum->getView();
}
const glm::mat4& LightStage::Shadow::getProjection() const {
return _frustum->getProjection();
_schemaBuffer.edit<Schema>().cascades[cascadeIndex].reprojection = _biasMatrix * shadowFrustum.getProjection() * viewInverse.getMatrix();
}
LightStage::Index LightStage::findLight(const LightPointer& light) const {

View file

@ -46,27 +46,43 @@ public:
using UniformBufferView = gpu::BufferView;
static const int MAP_SIZE = 1024;
Shadow(model::LightPointer light);
class Cascade {
friend Shadow;
public:
void setKeylightFrustum(const ViewFrustum& viewFrustum, float viewMinShadowDistance, float viewMaxShadowDistance, float nearDepth = 1.0f, float farDepth = 1000.0f);
Cascade();
void setFrustum(const ViewFrustum& shadowFrustum);
const std::shared_ptr<ViewFrustum> getFrustum() const { return _frustum; }
gpu::FramebufferPointer framebuffer;
gpu::TexturePointer map;
const glm::mat4& getView() const;
const glm::mat4& getProjection() const;
const std::shared_ptr<ViewFrustum>& getFrustum() const { return _frustum; }
const glm::mat4& getView() const;
const glm::mat4& getProjection() const;
private:
std::shared_ptr<ViewFrustum> _frustum;
};
Shadow(model::LightPointer light, unsigned int cascadeCount = 1);
void setKeylightFrustum(unsigned int cascadeIndex, const ViewFrustum& viewFrustum, float viewMinShadowDistance, float viewMaxShadowDistance, float nearDepth = 1.0f, float farDepth = 1000.0f);
void setFrustum(unsigned int cascadeIndex, const ViewFrustum& shadowFrustum);
const UniformBufferView& getBuffer() const { return _schemaBuffer; }
gpu::FramebufferPointer framebuffer;
gpu::TexturePointer map;
unsigned int getCascadeCount() const { return (unsigned int)_cascades.size(); }
const Cascade& getCascade(unsigned int index) const { return _cascades[index]; }
protected:
using Cascades = std::vector<Cascade>;
static const glm::mat4 _biasMatrix;
model::LightPointer _light;
std::shared_ptr<ViewFrustum> _frustum;
Cascades _cascades;
#include "Shadows_shared.slh"

View file

@ -545,7 +545,7 @@ void DrawFrustums::run(const render::RenderContextPointer& renderContext) {
const auto globalShadow = lightStage->getCurrentKeyShadow();
if (globalShadow) {
updateFrustum(*globalShadow->getFrustum(), _shadowFrustumMeshVertices);
updateFrustum(*globalShadow->getCascade(0).getFrustum(), _shadowFrustumMeshVertices);
}
}

View file

@ -139,7 +139,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, con
auto shadow = lightStage->getCurrentKeyShadow();
if (!shadow) return;
const auto& fbo = shadow->framebuffer;
const auto& fbo = shadow->getCascade(0).framebuffer;
RenderArgs* args = renderContext->args;
ShapeKey::Builder defaultKeyBuilder;
@ -149,7 +149,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, con
// the minimal Z range.
adjustNearFar(inShapeBounds, adjustedShadowFrustum);
// Reapply the frustum as it has been adjusted
shadow->setFrustum(adjustedShadowFrustum);
shadow->setFrustum(0, adjustedShadowFrustum);
args->popViewFrustum();
args->pushViewFrustum(adjustedShadowFrustum);
@ -252,10 +252,10 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, O
auto nearClip = args->getViewFrustum().getNearClip();
float nearDepth = -args->_boomOffset.z;
const float SHADOW_MAX_DISTANCE = 20.0f;
globalShadow->setKeylightFrustum(args->getViewFrustum(), nearDepth, nearClip + SHADOW_MAX_DISTANCE, SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR);
globalShadow->setKeylightFrustum(0, args->getViewFrustum(), nearDepth, nearClip + SHADOW_MAX_DISTANCE, SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR);
// Set the keylight render args
args->pushViewFrustum(*(globalShadow->getFrustum()));
args->pushViewFrustum(*(globalShadow->getCascade(0).getFrustum()));
args->_renderMode = RenderArgs::SHADOW_RENDER_MODE;
}
}