Starting to add cascading shadow maps

This commit is contained in:
2025-07-14 21:10:07 +02:00
parent cc22f10565
commit 9bd1ca1b09
18 changed files with 282 additions and 172 deletions
+21 -3
View File
@@ -3,6 +3,18 @@ import LightEnv;
import MaterialParameter;
import MATERIAL_FILE_NAME;
const static uint64_t NUM_CASCADES = 4;
/*struct ShadowMappingData
{
Texture2DArray shadowMaps[NUM_CASCADES];
ConstantBuffer<float4x4> lightSpaceMatrices[NUM_CASCADES];
ConstantBuffer<float[NUM_CASCADES]> cascadeSplits;
};
ParameterBlock<ShadowMappingData> pShadowMapping;
*/
struct LightCullingData
{
RWStructuredBuffer<uint> lightIndexList;
@@ -30,7 +42,13 @@ float4 fragmentMain(in FragmentParameter params) : SV_Target
float3 result = float3(0, 0, 0);
for(int i = 0; i < pLightEnv.numDirectionalLights; ++i)
{
float4 lightSpacePos = mul(biasMat, mul(pLightEnv.directionalLights[i].lightSpaceMatrix, float4(params.position_WS, 1)));
/*uint cascadeIndex = 0;
for (uint c = 0; c < NUM_CASCADES - 1; ++c) {
if (params.position_VS.z < pShadowMapping.cascadeSplits[c]) {
cascadeIndex = c + 1;
}
}
float4 lightSpacePos = mul(biasMat, mul(pShadowMapping.lightSpaceMatrices[i], float4(params.position_WS, 1)));
float4 shadowCoord = lightSpacePos / lightSpacePos.w;
int2 texDim;
pLightEnv.shadowMap.GetDimensions(texDim.x, texDim.y);
@@ -55,9 +73,9 @@ float4 fragmentMain(in FragmentParameter params) : SV_Target
shadowFactor += shadow;
count++;
}
}
}*/
result += (shadowFactor / count) * pLightEnv.directionalLights[i].illuminate(lightingParams, brdf);
result += /*(shadowFactor / count) **/ pLightEnv.directionalLights[i].illuminate(lightingParams, brdf);
}
for (uint i = 0; i < pLightEnv.numPointLights; ++i)
{
-2
View File
@@ -10,7 +10,6 @@ struct DirectionalLight : ILightEnv
{
float4 color;
float4 direction;
float4x4 lightSpaceMatrix;
float3 illuminate<B:IBRDF>(LightingParameter params, B brdf)
{
@@ -369,4 +368,3 @@ struct CookTorrance : IBRDF
}
[mutating] void setNormal(float3 n) { normal = n; }
};
+8 -4
View File
@@ -63,7 +63,8 @@ struct FragmentParameter
float3 normal_WS : NORMALWS;
float3 tangent_WS : TANGENTWS;
float3 biTangent_WS : BITANGENTWS;
float3 position_WS : POSITIONWS;
float3 position_WS : POSITIONWS;
float3 position_VS : POSITIONVS;
float3 vertexColor : COLOR;
float4 texCoords0 : TEXCOORDS0;
float4 texCoords1 : TEXCOORDS1;
@@ -109,7 +110,8 @@ struct FragmentParameter
result.normal_WS = f0.normal_WS * barycentricCoords.x + f1.normal_WS * barycentricCoords.y + f2.normal_WS * barycentricCoords.z;
result.tangent_WS = f0.tangent_WS * barycentricCoords.x + f1.tangent_WS * barycentricCoords.y + f2.tangent_WS * barycentricCoords.z;
result.biTangent_WS = f0.biTangent_WS * barycentricCoords.x + f1.biTangent_WS * barycentricCoords.y + f2.biTangent_WS * barycentricCoords.z;
result.position_WS = f0.position_WS * barycentricCoords.x + f1.position_WS * barycentricCoords.y + f2.position_WS * barycentricCoords.z;
result.position_WS = f0.position_WS * barycentricCoords.x + f1.position_WS * barycentricCoords.y + f2.position_WS * barycentricCoords.z;
result.position_VS = f0.position_VS * barycentricCoords.x + f1.position_VS * barycentricCoords.y + f2.position_VS * barycentricCoords.z;
result.vertexColor = f0.vertexColor * barycentricCoords.x + f1.vertexColor * barycentricCoords.y + f2.vertexColor * barycentricCoords.z;
result.texCoords0 = f0.texCoords0 * barycentricCoords.x + f1.texCoords0 * barycentricCoords.y + f2.texCoords0 * barycentricCoords.z;
result.texCoords1 = f0.texCoords1 * barycentricCoords.x + f1.texCoords1 * barycentricCoords.y + f2.texCoords1 * barycentricCoords.z;
@@ -135,7 +137,8 @@ struct VertexAttributes
FragmentParameter getParameter(float4x4 transformMatrix, float4x4 inverseTransformMatrix)
{
float4 modelPos = float4(position_MS, 1);
float4 worldPos = mul(transformMatrix, modelPos);
float4 worldPos = mul(transformMatrix, modelPos);
float4 viewPos = mul(pViewParams.viewMatrix, worldPos);
float4 clipPos = mul(pViewParams.viewProjectionMatrix, worldPos);
FragmentParameter result;
result.position_CS = clipPos;
@@ -145,7 +148,8 @@ struct VertexAttributes
result.biTangent_WS = mul(transformMatrix, float4(biTangent_MS, 0)).xyz;
result.normal_WS = mul(transformMatrix, float4(normal_MS, 0)).xyz;
result.vertexColor = vertexColor;
result.position_WS = worldPos.xyz;
result.position_WS = worldPos.xyz;
result.position_VS = viewPos.xyz;
result.texCoords0 = float4(texCoords[0], texCoords[1]);
result.texCoords1 = float4(texCoords[2], texCoords[3]);
result.texCoords2 = float4(texCoords[4], texCoords[5]);
+4 -1
View File
@@ -535,8 +535,11 @@ template <typename T, size_t N> struct StaticArray {
}
}
}
constexpr StaticArray(const StaticArray& other) = default;
constexpr StaticArray(StaticArray&& other) = default;
constexpr ~StaticArray() {}
constexpr StaticArray& operator=(const StaticArray& other) = default;
constexpr StaticArray& operator=(StaticArray&& other) = default;
constexpr size_type size() const { return N; }
constexpr pointer data() { return _data; }
constexpr const_pointer data() const { return _data; }
+2 -1
View File
@@ -84,7 +84,8 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics)
BasePass::~BasePass() {}
void BasePass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {
viewParamsSet = createViewParamsSet(cam, transform);
updateViewParameters(cam, transform);
viewParamsSet = createViewParamsSet();
cameraPos = transform.getPosition();
cameraForward = transform.getForward();
@@ -42,7 +42,8 @@ CachedDepthPass::CachedDepthPass(Gfx::PGraphics graphics, PScene scene) : Render
CachedDepthPass::~CachedDepthPass() {}
void CachedDepthPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {
viewParamsSet = createViewParamsSet(cam, transform);
updateViewParameters(cam, transform);
viewParamsSet = createViewParamsSet();
}
void CachedDepthPass::render() {
@@ -66,7 +66,8 @@ DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : Rend
DepthCullingPass::~DepthCullingPass() {}
void DepthCullingPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {
viewParamsSet = createViewParamsSet(cam, transform);
updateViewParameters(cam, transform);
viewParamsSet = createViewParamsSet();
}
void DepthCullingPass::render() {
@@ -1,6 +1,7 @@
#include "LightCullingPass.h"
#include "Actor/CameraActor.h"
#include "Component/Camera.h"
#include "Component/Transform.h"
#include "Graphics/Command.h"
#include "Graphics/Graphics.h"
#include "Graphics/Pipeline.h"
@@ -15,7 +16,8 @@ LightCullingPass::LightCullingPass(Gfx::PGraphics graphics, PScene scene) : Rend
LightCullingPass::~LightCullingPass() {}
void LightCullingPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {
viewParamsSet = createViewParamsSet(cam, transform);
updateViewParameters(cam, transform);
viewParamsSet = createViewParamsSet();
oLightIndexCounter->pipelineBarrier(Gfx::SE_ACCESS_MEMORY_WRITE_BIT | Gfx::SE_ACCESS_MEMORY_READ_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_MEMORY_WRITE_BIT,
@@ -232,7 +234,8 @@ void LightCullingPass::setupFrustums() {
numThreads = glm::ceil(glm::vec4(viewportWidth / (float)BLOCK_SIZE, viewportHeight / (float)BLOCK_SIZE, 1, 0));
numThreadGroups = glm::ceil(glm::vec4(numThreads.x / (float)BLOCK_SIZE, numThreads.y / (float)BLOCK_SIZE, 1, 0));
viewParamsSet = createViewParamsSet(Component::Camera(), Component::Transform());
updateViewParameters(Component::Camera(), Component::Transform());
viewParamsSet = createViewParamsSet();
dispatchParamsLayout = graphics->createDescriptorLayout("pDispatchParams");
dispatchParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
@@ -65,8 +65,8 @@ RayTracingPass::RayTracingPass(Gfx::PGraphics graphics, PScene scene) : RenderPa
static uint32 pass = 0;
static Component::Transform lastCam;
void RayTracingPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {
viewParamsSet = createViewParamsSet(cam, transform);
if (lastCam.getPosition() != transform.getPosition() || lastCam.getForward() != transform.getForward()) {
updateViewParameters(cam, transform);
viewParamsSet = createViewParamsSet(); if (lastCam.getPosition() != transform.getPosition() || lastCam.getForward() != transform.getForward()) {
lastCam = transform;
pass = 0;
}
+20 -18
View File
@@ -27,8 +27,7 @@ void RenderPass::setResources(PRenderGraphResources _resources) { resources = _r
void RenderPass::setViewport(Gfx::PViewport _viewport) { viewport = _viewport; }
Gfx::PDescriptorSet RenderPass::createViewParamsSet(const Component::Camera& cam, const Component::Transform& transform)
{
void RenderPass::updateViewParameters(const Component::Camera& cam, const Component::Transform& transform) {
auto screenDim = Vector2(static_cast<float>(viewport->getWidth()), static_cast<float>(viewport->getHeight()));
Vector eyePos = transform.getPosition();
Vector lookAt = eyePos + transform.getForward();
@@ -48,24 +47,27 @@ Gfx::PDescriptorSet RenderPass::createViewParamsSet(const Component::Camera& cam
.frameIndex = Gfx::getCurrentFrameIndex(),
.time = static_cast<float>(Gfx::getCurrentFrameTime()),
};
}
Gfx::PDescriptorSet RenderPass::createViewParamsSet()
{
// screen space
StaticArray<Vector4, 4> corners = {
Vector4(0, 0, -1, 1),
Vector4(screenDim.x, 0, -1, 1),
Vector4(screenDim.y, 0, -1, 1),
Vector4(screenDim.x, screenDim.y, -1, 1),
};
for (uint32 i = 0; i < corners.size(); ++i) {
Vector2 texCoord = Vector2(corners[i].x, corners[i].y) / screenDim;
Vector4 clip = Vector4(Vector2(texCoord.x, 1 - texCoord.y) * 2.0f - 1.0f, corners[i].z, corners[i].w);
Vector4 world = viewParams.inverseViewProjectionMatrix * clip;
corners[i] = world / world.w;
}
//StaticArray<Vector4, 4> corners = {
// Vector4(0, 0, -1, 1),
// Vector4(screenDim.x, 0, -1, 1),
// Vector4(screenDim.y, 0, -1, 1),
// Vector4(screenDim.x, screenDim.y, -1, 1),
//};
//
//for (uint32 i = 0; i < corners.size(); ++i) {
// Vector2 texCoord = Vector2(corners[i].x, corners[i].y) / screenDim;
//
// Vector4 clip = Vector4(Vector2(texCoord.x, 1 - texCoord.y) * 2.0f - 1.0f, corners[i].z, corners[i].w);
//
// Vector4 world = viewParams.inverseViewProjectionMatrix * clip;
//
// corners[i] = world / world.w;
//}
// extract_planes_from_view_projection_matrix(viewParams.viewProjectionMatrix, viewParams.viewFrustum);
+2 -1
View File
@@ -27,7 +27,8 @@ class RenderPass {
void setViewport(Gfx::PViewport _viewport);
protected:
Gfx::PDescriptorSet createViewParamsSet(const Component::Camera& cam, const Component::Transform& transform);
void updateViewParameters(const Component::Camera& cam, const Component::Transform& transform);
Gfx::PDescriptorSet createViewParamsSet();
struct Plane {
Vector n;
float d;
+196 -104
View File
@@ -1,6 +1,10 @@
#include "ShadowPass.h"
#include "Graphics/Enums.h"
#include "Graphics/Graphics.h"
#include "Graphics/Initializer.h"
#include "Graphics/Shader.h"
#include <glm/ext/matrix_transform.hpp>
#include <glm/matrix.hpp>
using namespace Seele;
@@ -39,126 +43,214 @@ ShadowPass::ShadowPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graph
ShadowPass::~ShadowPass() {}
void ShadowPass::beginFrame(const Component::Camera&, const Component::Transform&) {}
void ShadowPass::beginFrame(const Component::Camera& camera, const Component::Transform& transform) {
uint32 cascadeDim = SHADOW_MAP_SIZE;
float cascadeSplits[NUM_CASCADES];
float nearClip = camera.nearPlane;
float farClip = camera.farPlane;
float clipRange = farClip - nearClip;
float minZ = nearClip;
float maxZ = nearClip + clipRange;
float range = maxZ - minZ;
float ratio = maxZ / minZ;
constexpr float cascadeSplitLambda = 0.95f;
for (uint32 i = 0; i < NUM_CASCADES; ++i) {
cascades[i].shadowMaps = graphics->createTexture2D(TextureCreateInfo{
.format = Gfx::SE_FORMAT_D32_SFLOAT,
.width = cascadeDim,
.height = cascadeDim,
.elements = (uint32)scene->getLightEnvironment()->getNumDirectionalLights(),
.usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_SAMPLED_BIT,
.name = "ShadowMapCascade",
});
cascades[i].views.clear();
for (uint32 j = 0; j < cascades[i].shadowMaps->getNumLayers(); ++j) {
cascades[i].views.add(cascades[i].shadowMaps->createTextureView(0, 1, j, 1));
}
cascadeDim /= 2;
float p = (i + 1) / static_cast<float>(NUM_CASCADES);
float log = minZ * std::pow(ratio, p);
float uniform = minZ + range * p;
float d = cascadeSplitLambda * (log - uniform) + uniform;
cascadeSplits[i] = (d - nearClip) / clipRange;
}
// call this to update view params member, ignore descriptor set
updateViewParameters(camera, transform);
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 = viewParams.inverseViewProjectionMatrix * Vector4(c, 1);
c = invCorner / invCorner.w;
}
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];
Array<Vector> cascadeCorners(8);
for (uint32 j = 0; j < 4; j++) {
Vector dist = frustumCorners[j + 4] - frustumCorners[j];
cascadeCorners[j + 4] = frustumCorners[j] + (dist * splitDist);
cascadeCorners[j] = frustumCorners[j] + (dist * lastSplitDist);
}
Vector frustumCenter = Vector(0);
for (uint32 j = 0; j < 8; j++) {
frustumCenter += cascadeCorners[j];
}
frustumCenter /= 8.0f;
float radius = 0.0f;
for (uint j = 0; j < 8; j++) {
float distance = glm::length(cascadeCorners[j] - frustumCenter);
radius = glm::max(radius, distance);
}
radius = std::ceil(radius * 16.0f) / 16.0f;
Vector maxExtents = Vector(radius);
Vector minExtents = -maxExtents;
Vector lightDir = glm::normalize(scene->getLightEnvironment()->getDirectionalLight(s).direction);
Matrix4 viewMatrix = glm::lookAt(frustumCenter - lightDir * -minExtents.z, frustumCenter, Vector(0, 1, 0));
Matrix4 projectionMatrix =
glm::ortho(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.screenDimensions = Vector2(maxExtents.x - minExtents.x, maxExtents.y - minExtents.y);
viewParams.invScreenDimensions = 1.0f / viewParams.screenDimensions;
cascades[i].viewParams.add(createViewParamsSet());
}
}
}
void ShadowPass::render() {
graphics->beginDebugRegion("ShadowPass");
Gfx::ShaderPermutation permutation = graphics->getShaderCompiler()->getTemplate("ShadowPass");
permutation.setDepthCulling(true);
permutation.setPositionOnly(true);
const auto& shadowMaps = scene->getLightEnvironment()->getShadowMaps();
for (uint32 shadowIndex = 0; shadowIndex < scene->getLightEnvironment()->getNumDirectionalLights(); ++shadowIndex) {
Array<Gfx::ORenderCommand> commands;
renderPass = graphics->createRenderPass(
Gfx::RenderTargetLayout{
.depthAttachment = Gfx::RenderTargetAttachment(shadowMaps[shadowIndex]->getDefaultView(), Gfx::SE_IMAGE_LAYOUT_UNDEFINED,
Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE),
for (uint32 c = 0; c < NUM_CASCADES; ++c) {
graphics->beginDebugRegion("Cascade");
for (uint32 shadowIndex = 0; shadowIndex < cascades[c].shadowMaps->getNumLayers(); ++shadowIndex) {
Array<Gfx::ORenderCommand> commands;
renderPass = graphics->createRenderPass(
Gfx::RenderTargetLayout{
.depthAttachment = Gfx::RenderTargetAttachment(
cascades[c].views[shadowIndex], Gfx::SE_IMAGE_LAYOUT_UNDEFINED,
Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE),
},
{
Gfx::SubPassDependency{
.srcSubpass = ~0U,
.dstSubpass = 0,
.srcStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
},
Gfx::SubPassDependency{
.srcSubpass = 0,
.dstSubpass = ~0U,
.srcStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
{
Gfx::SubPassDependency{
.srcSubpass = ~0U,
.dstSubpass = 0,
.srcStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
},
Gfx::SubPassDependency{
.srcSubpass = 0,
.dstSubpass = ~0U,
.srcStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
},
},
},
{
.size = {shadowMaps[shadowIndex]->getWidth(), shadowMaps[shadowIndex]->getHeight()},
.offset = {0, 0},
},
"Shadow");
Component::Camera lightCamera = Component::Camera{
.nearPlane = -100.f,
.farPlane = 100.0f,
};
Gfx::PDescriptorSet viewParamsSet = createViewParamsSet(lightCamera, scene->getLightEnvironment()->getDirectionalTransform(shadowIndex));
graphics->beginRenderPass(renderPass);
for (VertexData* vertexData : VertexData::getList()) {
permutation.setVertexData(vertexData->getTypeName());
Gfx::PermutationId id(permutation);
{
.size = {cascades[c].shadowMaps->getWidth(), cascades[c].shadowMaps->getHeight()},
.offset = {0, 0},
},
"Shadow");
graphics->beginRenderPass(renderPass);
for (VertexData* vertexData : VertexData::getList()) {
permutation.setVertexData(vertexData->getTypeName());
Gfx::PermutationId id(permutation);
Gfx::ORenderCommand command = graphics->createRenderCommand("ShadowRender");
command->setViewport(shadowViewport);
Gfx::ORenderCommand command = graphics->createRenderCommand("ShadowRender");
command->setViewport(shadowViewport);
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
constexpr float depthBiasConstant = -1.25f;
constexpr float depthBiasSlope = -1.75f;
if (graphics->supportMeshShading()) {
Gfx::MeshPipelineCreateInfo pipelineInfo = {
.taskShader = collection->taskShader,
.meshShader = collection->meshShader,
.fragmentShader = collection->fragmentShader,
.renderPass = renderPass,
.pipelineLayout = collection->pipelineLayout,
.rasterizationState =
{
.cullMode = Gfx::SE_CULL_MODE_FRONT_BIT,
.depthBiasEnable = true,
.depthBiasConstantFactor = depthBiasConstant,
.depthBiasSlopeFactor = depthBiasSlope,
},
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
constexpr float depthBiasConstant = -1.25f;
constexpr float depthBiasSlope = -1.75f;
if (graphics->supportMeshShading()) {
Gfx::MeshPipelineCreateInfo pipelineInfo = {
.taskShader = collection->taskShader,
.meshShader = collection->meshShader,
.fragmentShader = collection->fragmentShader,
.renderPass = renderPass,
.pipelineLayout = collection->pipelineLayout,
.rasterizationState =
{
.cullMode = Gfx::SE_CULL_MODE_FRONT_BIT,
.depthBiasEnable = true,
.depthBiasConstantFactor = depthBiasConstant,
.depthBiasSlopeFactor = depthBiasSlope,
},
};
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline);
} else {
Gfx::LegacyPipelineCreateInfo pipelineInfo = {
.vertexShader = collection->vertexShader,
.fragmentShader = collection->fragmentShader,
.renderPass = renderPass,
.pipelineLayout = collection->pipelineLayout,
.rasterizationState =
{
.cullMode = Gfx::SE_CULL_MODE_FRONT_BIT,
.depthBiasEnable = true,
.depthBiasConstantFactor = depthBiasConstant,
.depthBiasSlopeFactor = depthBiasSlope,
},
};
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline);
}
command->bindDescriptor({cascades[c].viewParams[shadowIndex], vertexData->getVertexDataSet(), vertexData->getInstanceDataSet()});
VertexData::DrawCallOffsets offsets = {
.instanceOffset = 0,
};
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline);
} else {
Gfx::LegacyPipelineCreateInfo pipelineInfo = {
.vertexShader = collection->vertexShader,
.fragmentShader = collection->fragmentShader,
.renderPass = renderPass,
.pipelineLayout = collection->pipelineLayout,
.rasterizationState =
{
.cullMode = Gfx::SE_CULL_MODE_FRONT_BIT,
.depthBiasEnable = true,
.depthBiasConstantFactor = depthBiasConstant,
.depthBiasSlopeFactor = depthBiasSlope,
},
};
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline);
}
command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet()});
VertexData::DrawCallOffsets offsets = {
.instanceOffset = 0,
};
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0,
sizeof(VertexData::DrawCallOffsets), &offsets);
if (graphics->supportMeshShading()) {
command->drawMesh((uint32)vertexData->getNumInstances(), 1, 1);
} else {
const auto& materials = vertexData->getMaterialData();
for (const auto& materialData : materials) {
// material not used for any active meshes, skip
if (materialData.instances.size() == 0)
continue;
for (const auto& drawCall : materialData.instances) {
command->bindIndexBuffer(vertexData->getIndexBuffer());
uint32 inst = drawCall.offsets.instanceOffset;
for (const auto& meshData : drawCall.instanceMeshData) {
// all meshlets of a mesh share the same indices offset
command->drawIndexed(meshData.indicesRange.size, 1, meshData.indicesRange.offset,
vertexData->getIndicesOffset(meshData.meshletRange.offset), inst++);
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0,
sizeof(VertexData::DrawCallOffsets), &offsets);
if (graphics->supportMeshShading()) {
command->drawMesh((uint32)vertexData->getNumInstances(), 1, 1);
} else {
const auto& materials = vertexData->getMaterialData();
for (const auto& materialData : materials) {
// material not used for any active meshes, skip
if (materialData.instances.size() == 0)
continue;
for (const auto& drawCall : materialData.instances) {
command->bindIndexBuffer(vertexData->getIndexBuffer());
uint32 inst = drawCall.offsets.instanceOffset;
for (const auto& meshData : drawCall.instanceMeshData) {
// all meshlets of a mesh share the same indices offset
command->drawIndexed(meshData.indicesRange.size, 1, meshData.indicesRange.offset,
vertexData->getIndicesOffset(meshData.meshletRange.offset), inst++);
}
}
}
}
commands.add(std::move(command));
}
commands.add(std::move(command));
graphics->executeCommands(std::move(commands));
graphics->endRenderPass();
graphics->waitDeviceIdle();
}
graphics->executeCommands(std::move(commands));
graphics->endRenderPass();
graphics->waitDeviceIdle();
graphics->endDebugRegion();
}
graphics->endDebugRegion();
}
@@ -168,7 +260,7 @@ void ShadowPass::endFrame() {}
void ShadowPass::publishOutputs() {
shadowViewport = graphics->createViewport(nullptr, ViewportCreateInfo{.dimensions =
{
.size = {8192, 8192},
.size = {SHADOW_MAP_SIZE, SHADOW_MAP_SIZE},
.offset = {0, 0},
},
.fieldOfView = 0,
@@ -1,7 +1,12 @@
#pragma once
#include "Graphics/Buffer.h"
#include "Graphics/Descriptor.h"
#include "RenderPass.h"
namespace Seele {
static constexpr uint64 SHADOW_MAP_SIZE = 8192;
class ShadowPass : public RenderPass {
public:
ShadowPass(Gfx::PGraphics graphics, PScene scene);
@@ -15,6 +20,13 @@ class ShadowPass : public RenderPass {
virtual void createRenderPass() override;
private:
AABB cameraFrustumBox;
static constexpr uint64 NUM_CASCADES = 4;
struct Cascade {
Gfx::OTexture2D shadowMaps;
Array<Gfx::OTextureView> views;
Array<Gfx::PDescriptorSet> viewParams;
};
StaticArray<Cascade, NUM_CASCADES> cascades;
Gfx::OPipelineLayout shadowLayout;
Gfx::PShaderBuffer cullingBuffer;
Gfx::OViewport shadowViewport;
@@ -124,7 +124,8 @@ ToneMappingPass::ToneMappingPass(Gfx::PGraphics graphics) : RenderPass(graphics)
ToneMappingPass::~ToneMappingPass() {}
void ToneMappingPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {
viewParamsSet = createViewParamsSet(cam, transform);
updateViewParameters(cam, transform);
viewParamsSet = createViewParamsSet();
}
void ToneMappingPass::render() {
+2 -1
View File
@@ -54,7 +54,8 @@ UIPass::UIPass(Gfx::PGraphics graphics, UI::PSystem system) : RenderPass(graphic
UIPass::~UIPass() {}
void UIPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {
viewParamsSet = createViewParamsSet(cam, transform);
updateViewParameters(cam, transform);
viewParamsSet = createViewParamsSet();
glyphs.clear();
usedTextures.clear();
elements.clear();
@@ -8,7 +8,8 @@ VisibilityPass::VisibilityPass(Gfx::PGraphics graphics) : RenderPass(graphics) {
VisibilityPass::~VisibilityPass() {}
void VisibilityPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {
viewParamsSet = createViewParamsSet(cam, transform);
updateViewParameters(cam, transform);
viewParamsSet = createViewParamsSet();
cullingBuffer->rotateBuffer(VertexData::getMeshletCount() * sizeof(VertexData::MeshletCullingInfo), true);
}
-25
View File
@@ -82,34 +82,11 @@ void LightEnvironment::reset() {
}
void LightEnvironment::addDirectionalLight(const Component::DirectionalLight& dirLight, const Component::Transform& transform) {
Vector eyePos = transform.getPosition();
Vector lookAt = eyePos + transform.getForward();
Matrix4 cameraMatrix = glm::lookAt(eyePos, lookAt, Vector(0, 1, 0));
Matrix4 correctionMatrix = Matrix4(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1 / 2.f, 0, 0, 0, 1 / 2.f, 1);
dirs.add(ShaderDirectionalLight{
.color = Vector4(dirLight.color, dirLight.intensity),
.direction = Vector4(transform.getForward(), 0),
.lightSpaceMatrix = correctionMatrix * glm::ortho(-100.0f, 100.0f, -100.0f, 100.0f, 100.0f, -100.0f) * cameraMatrix,
});
directionalTransforms.add(transform);
if (shadowMaps.size() < dirs.size()) {
shadowMaps.add(graphics->createTexture2D(TextureCreateInfo{
.format = Gfx::SE_FORMAT_D32_SFLOAT,
.width = 8192,
.height = 8192,
.elements = (uint32)dirs.size(),
.usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_SAMPLED_BIT,
.name = "ShadowMap",
}));
shadowMaps.back()->changeLayout(Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, Gfx::SE_ACCESS_NONE, Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
shadowSamplers.add(graphics->createSampler(SamplerCreateInfo{
.addressModeU = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
.addressModeV = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
.addressModeW = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
.name = "ShadowSampler",
}));
}
}
void LightEnvironment::addPointLight(const Component::PointLight& pointLight, const Component::Transform& transform) {
@@ -136,8 +113,6 @@ void LightEnvironment::commit() {
uint32 numDirectionalLights = (uint32)dirs.size();
set->updateConstants("numDirectionalLights", 0, &numDirectionalLights);
set->updateBuffer("directionalLights", 0, directionalLights);
set->updateTexture("shadowMap", 0, shadowMaps[0]->getDefaultView());
set->updateSampler("shadowSampler", 0, Gfx::PSampler(shadowSamplers[0]));
set->updateConstants("numPointLights", 0, &numPointLights);
set->updateBuffer("pointLights", 0, pointLights);
set->updateTexture("irradianceMap", 0, environment->getIrradianceMap()->getDefaultView());
-4
View File
@@ -4,7 +4,6 @@
#include "Component/Transform.h"
#include "Graphics/Buffer.h"
#include "Graphics/Descriptor.h"
#include "Graphics/Texture.h"
namespace Seele {
DECLARE_REF(EnvironmentMapAsset)
@@ -13,7 +12,6 @@ class LightEnvironment {
struct ShaderDirectionalLight {
Vector4 color;
Vector4 direction;
Matrix4 lightSpaceMatrix;
};
struct ShaderPointLight {
Vector4 position_WS;
@@ -31,12 +29,10 @@ class LightEnvironment {
Gfx::PDescriptorSet getDescriptorSet();
PEnvironmentMapAsset getEnvironmentMap() { return environment; }
uint64 getNumDirectionalLights() const { return dirs.size(); }
const Array<Gfx::OTexture2D>& getShadowMaps() const { return shadowMaps; }
private:
Gfx::PGraphics graphics;
Gfx::OShaderBuffer directionalLights;
Array<Gfx::OTexture2D> shadowMaps;
Array<Gfx::OSampler> shadowSamplers;
Gfx::OShaderBuffer pointLights;
Array<ShaderDirectionalLight> dirs;