Reverse depth is now working in the shadow pass
This commit is contained in:
@@ -50,10 +50,10 @@ void ShadowPass::beginFrame(const Component::Camera& camera, const Component::Tr
|
||||
|
||||
float nearClip = camera.nearPlane;
|
||||
float farClip = camera.farPlane;
|
||||
float clipRange = farClip - nearClip;
|
||||
float clipRange = nearClip - farClip;
|
||||
|
||||
float minZ = nearClip;
|
||||
float maxZ = nearClip + clipRange;
|
||||
float minZ = farClip;
|
||||
float maxZ = nearClip;
|
||||
|
||||
float range = maxZ - minZ;
|
||||
float ratio = maxZ / minZ;
|
||||
@@ -63,72 +63,74 @@ void ShadowPass::beginFrame(const Component::Camera& camera, const Component::Tr
|
||||
float log = minZ * std::pow(ratio, p);
|
||||
float uniform = minZ + range * p;
|
||||
float d = cascadeSplitLambda * (log - uniform) + uniform;
|
||||
cascadeSplits[i] = (d - nearClip) / clipRange;
|
||||
splitDepths[i] = (camera.nearPlane + cascadeSplits[i] * clipRange) * -1.0f;
|
||||
cascadeSplits[i] = (d - farClip) / clipRange;
|
||||
splitDepths[i] = farClip + cascadeSplits[i] * clipRange;
|
||||
cascades[i].viewParams.clear();
|
||||
}
|
||||
cascadeSplitsBuffer->updateContents(0, sizeof(float) * NUM_CASCADES, splitDepths);
|
||||
|
||||
// call this to update view params member, ignore descriptor set
|
||||
updateViewParameters(camera, transform);
|
||||
Matrix4 invCam = viewParams.inverseViewProjectionMatrix;
|
||||
for (uint32 s = 0; s < scene->getLightEnvironment()->getNumDirectionalLights(); ++s) {
|
||||
float lastSplitDist = 0.0;
|
||||
for (uint32 i = 0; i < NUM_CASCADES; ++i) {
|
||||
float splitDist = cascadeSplits[i];
|
||||
float lastSplitDist = 0.0;
|
||||
for (uint32 i = 0; i < NUM_CASCADES; ++i) {
|
||||
float splitDist = cascadeSplits[i];
|
||||
|
||||
Array<Vector> frustumCorners = {
|
||||
Vector(-1.0f, 1.0f, 1.0f), Vector(1.0f, 1.0f, 1.0f), Vector(1.0f, -1.0f, 1.0f), Vector(-1.0f, -1.0f, 1.0f),
|
||||
Vector(-1.0f, 1.0f, 0.0f), Vector(1.0f, 1.0f, 0.0f), Vector(1.0f, -1.0f, 0.0f), Vector(-1.0f, -1.0f, 0.0f),
|
||||
};
|
||||
Array<Vector> frustumCorners = {
|
||||
Vector(-1.0f, 1.0f, 0.0f), Vector(1.0f, 1.0f, 0.0f), Vector(1.0f, -1.0f, 0.0f), Vector(-1.0f, -1.0f, 0.0f),
|
||||
Vector(-1.0f, 1.0f, 1.0f), Vector(1.0f, 1.0f, 1.0f), Vector(1.0f, -1.0f, 1.0f), Vector(-1.0f, -1.0f, 1.0f),
|
||||
};
|
||||
|
||||
for (auto& c : frustumCorners) {
|
||||
Vector4 invCorner = invCam * Vector4(c, 1);
|
||||
c = invCorner / invCorner.w;
|
||||
}
|
||||
for (uint32 j = 0; j < 4; j++) {
|
||||
Vector dist = frustumCorners[j + 4] - frustumCorners[j];
|
||||
frustumCorners[j + 4] = frustumCorners[j] + (dist * splitDist);
|
||||
frustumCorners[j] = frustumCorners[j] + (dist * lastSplitDist);
|
||||
}
|
||||
for (auto& c : frustumCorners) {
|
||||
Vector4 invCorner = invCam * Vector4(c, 1);
|
||||
c = invCorner / invCorner.w;
|
||||
}
|
||||
for (uint32 j = 0; j < 4; j++) {
|
||||
Vector dist = frustumCorners[j + 4] - frustumCorners[j];
|
||||
frustumCorners[j + 4] = frustumCorners[j] + (dist * splitDist);
|
||||
frustumCorners[j] = frustumCorners[j] + (dist * lastSplitDist);
|
||||
}
|
||||
|
||||
Vector frustumCenter = Vector(0);
|
||||
for (uint32 j = 0; j < 8; j++) {
|
||||
frustumCenter += frustumCorners[j];
|
||||
}
|
||||
frustumCenter /= 8.0f;
|
||||
Vector frustumCenter = Vector(0);
|
||||
for (uint32 j = 0; j < 8; j++) {
|
||||
frustumCenter += frustumCorners[j];
|
||||
}
|
||||
frustumCenter /= 8.0f;
|
||||
|
||||
float radius = 0.0f;
|
||||
for (uint j = 0; j < 8; j++) {
|
||||
float distance = glm::length(frustumCorners[j] - frustumCenter);
|
||||
radius = glm::max(radius, distance);
|
||||
}
|
||||
radius = std::ceil(radius * 16.0f) / 16.0f;
|
||||
float radius = 0.0f;
|
||||
for (uint j = 0; j < 8; j++) {
|
||||
float distance = glm::length(frustumCorners[j] - frustumCenter);
|
||||
radius = glm::max(radius, distance);
|
||||
}
|
||||
radius = std::ceil(radius * 16.0f) / 16.0f;
|
||||
|
||||
Vector maxExtents = Vector(radius);
|
||||
Vector minExtents = -maxExtents;
|
||||
Vector maxExtents = Vector(radius);
|
||||
Vector minExtents = -maxExtents;
|
||||
|
||||
for (uint32 s = 0; s < scene->getLightEnvironment()->getNumDirectionalLights(); ++s) {
|
||||
Vector lightDir = glm::normalize(scene->getLightEnvironment()->getDirectionalLight(s).direction);
|
||||
Vector cameraPos = frustumCenter - lightDir * -minExtents.z;
|
||||
Matrix4 viewMatrix = glm::lookAt(cameraPos, frustumCenter, Vector(0, 1, 0));
|
||||
Matrix4 projectionMatrix =
|
||||
orthographicProjection(minExtents.x, maxExtents.x, minExtents.y, maxExtents.y, 0.0f, maxExtents.z - minExtents.z);
|
||||
Matrix4 viewProjectionMatrix = projectionMatrix * viewMatrix;
|
||||
viewParams.viewMatrix = viewMatrix;
|
||||
viewParams.inverseViewMatrix = glm::inverse(viewMatrix);
|
||||
viewParams.projectionMatrix = projectionMatrix;
|
||||
viewParams.inverseProjection = glm::inverse(projectionMatrix);
|
||||
viewParams.viewProjectionMatrix = viewProjectionMatrix;
|
||||
viewParams.inverseViewProjectionMatrix = glm::inverse(viewProjectionMatrix);
|
||||
viewParams.cameraPosition_WS = Vector4(cameraPos, 1);
|
||||
viewParams.cameraForward_WS = Vector4(frustumCenter - cameraPos, 0);
|
||||
viewParams.screenDimensions = Vector2(maxExtents.x - minExtents.x, maxExtents.y - minExtents.y);
|
||||
viewParams.invScreenDimensions = 1.0f / viewParams.screenDimensions;
|
||||
viewParams = {
|
||||
.viewMatrix = viewMatrix,
|
||||
.inverseViewMatrix = glm::inverse(viewMatrix),
|
||||
.projectionMatrix = projectionMatrix,
|
||||
.inverseProjection = glm::inverse(projectionMatrix),
|
||||
.viewProjectionMatrix = viewProjectionMatrix,
|
||||
.inverseViewProjectionMatrix = glm::inverse(viewProjectionMatrix),
|
||||
.cameraPosition_WS = Vector4(cameraPos, 1),
|
||||
.cameraForward_WS = Vector4(frustumCenter - cameraPos, 0),
|
||||
.screenDimensions = Vector2(maxExtents.x - minExtents.x, maxExtents.y - minExtents.y),
|
||||
.invScreenDimensions = 1.0f / Vector2(maxExtents.x - minExtents.x, maxExtents.y - minExtents.y),
|
||||
.frameIndex = Gfx::getCurrentFrameIndex(),
|
||||
.time = (float)Gfx::getCurrentFrameTime(),
|
||||
};
|
||||
cascades[i].viewParams.add(createViewParamsSet());
|
||||
cascades[i].lightSpaceBuffer->updateContents(0, sizeof(Matrix4), &viewProjectionMatrix);
|
||||
|
||||
lastSplitDist = cascadeSplits[i];
|
||||
}
|
||||
lastSplitDist = cascadeSplits[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +179,7 @@ void ShadowPass::render() {
|
||||
Gfx::PermutationId id(permutation);
|
||||
|
||||
Gfx::ORenderCommand command = graphics->createRenderCommand("ShadowRender");
|
||||
command->setViewport(shadowViewport);
|
||||
command->setViewport(cascades[c].shadowViewport);
|
||||
|
||||
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
|
||||
constexpr float depthBiasConstant = -1.25f;
|
||||
@@ -262,19 +264,9 @@ void ShadowPass::publishOutputs() {
|
||||
.data = nullptr,
|
||||
},
|
||||
.name = "CascadeSplits"});
|
||||
shadowViewport = graphics->createViewport(nullptr, ViewportCreateInfo{.dimensions =
|
||||
{
|
||||
.size = {SHADOW_MAP_SIZE, SHADOW_MAP_SIZE},
|
||||
.offset = {0, 0},
|
||||
},
|
||||
.fieldOfView = 0,
|
||||
.left = -100,
|
||||
.right = 100,
|
||||
.top = 100,
|
||||
.bottom = -100});
|
||||
uint32 cascadeDim = SHADOW_MAP_SIZE;
|
||||
for (uint32 s = 0; s < NUM_CASCADES; ++s) {
|
||||
cascades[s].shadowMaps = graphics->createTexture2DArray(TextureCreateInfo{
|
||||
for (uint32 c = 0; c < NUM_CASCADES; ++c) {
|
||||
cascades[c].shadowMaps = graphics->createTexture2DArray(TextureCreateInfo{
|
||||
.format = Gfx::SE_FORMAT_D32_SFLOAT,
|
||||
.width = cascadeDim,
|
||||
.height = cascadeDim,
|
||||
@@ -282,19 +274,26 @@ void ShadowPass::publishOutputs() {
|
||||
.usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_SAMPLED_BIT,
|
||||
.name = "ShadowMapCascade",
|
||||
});
|
||||
cascades[s].lightSpaceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{.sourceData =
|
||||
cascades[c].lightSpaceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{.sourceData =
|
||||
{
|
||||
.size = sizeof(Matrix4),
|
||||
.data = nullptr,
|
||||
},
|
||||
.name = "LightSpaceBuffer"});
|
||||
cascades[s].views.clear();
|
||||
for (uint32 j = 0; j < cascades[s].shadowMaps->getNumLayers(); ++j) {
|
||||
cascades[s].views.add(cascades[s].shadowMaps->createTextureView(0, 1, j, 1));
|
||||
cascades[c].views.clear();
|
||||
for (uint32 j = 0; j < cascades[c].shadowMaps->getNumLayers(); ++j) {
|
||||
cascades[c].views.add(cascades[c].shadowMaps->createTextureView(0, 1, j, 1));
|
||||
}
|
||||
cascades[c].shadowViewport = graphics->createViewport(nullptr, ViewportCreateInfo{
|
||||
.dimensions =
|
||||
{
|
||||
.size = {cascadeDim, cascadeDim},
|
||||
.offset = {0, 0},
|
||||
},
|
||||
});
|
||||
cascadeDim /= 2;
|
||||
resources->registerTextureOutput(fmt::format("SHADOWMAP_TEXTURE{0}", s), Gfx::PTexture2DArray(cascades[s].shadowMaps));
|
||||
resources->registerBufferOutput(fmt::format("SHADOWMAP_LIGHTSPACE{0}", s), cascades[s].lightSpaceBuffer);
|
||||
resources->registerTextureOutput(fmt::format("SHADOWMAP_TEXTURE{0}", c), Gfx::PTexture2DArray(cascades[c].shadowMaps));
|
||||
resources->registerBufferOutput(fmt::format("SHADOWMAP_LIGHTSPACE{0}", c), cascades[c].lightSpaceBuffer);
|
||||
}
|
||||
cascadeSplitsBuffer = graphics->createUniformBuffer(UniformBufferCreateInfo{.sourceData =
|
||||
{
|
||||
@@ -303,7 +302,7 @@ void ShadowPass::publishOutputs() {
|
||||
},
|
||||
.name = "CASCADE_SPLITS"});
|
||||
resources->registerUniformOutput("SHADOWMAP_CASCADESPLITS", cascadeSplitsBuffer);
|
||||
viewport = shadowViewport;
|
||||
viewport = cascades[0].shadowViewport;
|
||||
}
|
||||
|
||||
void ShadowPass::createRenderPass() { cullingBuffer = resources->requestBuffer("CULLINGBUFFER"); }
|
||||
|
||||
Reference in New Issue
Block a user