Simplify descriptor setup

Refs #1157
This commit is contained in:
Sascha Willems 2024-10-06 15:17:11 +02:00
parent 6b91f3c493
commit a2d5a1fd44
18 changed files with 41 additions and 68 deletions

View file

@ -62,7 +62,6 @@ public:
struct UBOFS { struct UBOFS {
float cascadeSplits[4]; float cascadeSplits[4];
glm::mat4 cascadeViewProjMat[4];
glm::mat4 inverseViewMat; glm::mat4 inverseViewMat;
glm::vec3 lightDir; glm::vec3 lightDir;
float _pad; float _pad;
@ -76,9 +75,7 @@ public:
VkPipeline sceneShadowPCF; VkPipeline sceneShadowPCF;
} pipelines; } pipelines;
struct DescriptorSetLayouts { VkDescriptorSetLayout descriptorSetLayout;
VkDescriptorSetLayout base;
} descriptorSetLayouts;
VkDescriptorSet descriptorSet; VkDescriptorSet descriptorSet;
// For simplicity all pipelines use the same push constant block layout // For simplicity all pipelines use the same push constant block layout
@ -92,12 +89,6 @@ public:
VkRenderPass renderPass; VkRenderPass renderPass;
VkPipelineLayout pipelineLayout; VkPipelineLayout pipelineLayout;
VkPipeline pipeline; VkPipeline pipeline;
vks::Buffer uniformBuffer;
struct UniformBlock {
std::array<glm::mat4, SHADOW_MAP_CASCADE_COUNT> cascadeViewProjMat;
} ubo;
} depthPass; } depthPass;
// Layered depth image containing the shadow cascade depths // Layered depth image containing the shadow cascade depths
@ -117,18 +108,17 @@ public:
// Contains all resources required for a single shadow map cascade // Contains all resources required for a single shadow map cascade
struct Cascade { struct Cascade {
VkFramebuffer frameBuffer; VkFramebuffer frameBuffer;
VkDescriptorSet descriptorSet;
VkImageView view; VkImageView view;
float splitDepth; float splitDepth;
glm::mat4 viewProjMatrix; glm::mat4 viewProjMatrix;
void destroy(VkDevice device) { void destroy(VkDevice device) {
vkDestroyImageView(device, view, nullptr); vkDestroyImageView(device, view, nullptr);
vkDestroyFramebuffer(device, frameBuffer, nullptr); vkDestroyFramebuffer(device, frameBuffer, nullptr);
} }
}; };
std::array<Cascade, SHADOW_MAP_CASCADE_COUNT> cascades; std::array<Cascade, SHADOW_MAP_CASCADE_COUNT> cascades;
// Per-cascade matrices will be passed to the shaders as a linear array
vks::Buffer cascadeViewProjMatricesBuffer;
VulkanExample() : VulkanExampleBase() VulkanExample() : VulkanExampleBase()
{ {
@ -159,9 +149,9 @@ public:
vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
vkDestroyPipelineLayout(device, depthPass.pipelineLayout, nullptr); vkDestroyPipelineLayout(device, depthPass.pipelineLayout, nullptr);
vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.base, nullptr); vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
depthPass.uniformBuffer.destroy(); cascadeViewProjMatricesBuffer.destroy();
uniformBuffers.VS.destroy(); uniformBuffers.VS.destroy();
uniformBuffers.FS.destroy(); uniformBuffers.FS.destroy();
} }
@ -174,10 +164,10 @@ public:
} }
/* /*
Render the example scene with given command buffer, pipeline layout and descriptor set Render the example scene to acommand buffer using the supplied pipeline layout and for the selected shadow cascade index
Used by the scene rendering and depth pass generation command buffer Used by the scene rendering and depth pass generation command buffer
*/ */
void renderScene(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VkDescriptorSet descriptorSet, uint32_t cascadeIndex = 0) { void renderScene(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, uint32_t cascadeIndex = 0) {
// We use push constants for passing shadow cascade info to the shaders // We use push constants for passing shadow cascade info to the shaders
PushConstBlock pushConstBlock = { glm::vec4(0.0f), cascadeIndex }; PushConstBlock pushConstBlock = { glm::vec4(0.0f), cascadeIndex };
@ -197,10 +187,10 @@ public:
glm::vec3(-1.25f, -0.25f, -1.25f), glm::vec3(-1.25f, -0.25f, -1.25f),
}; };
for (auto position : positions) { for (auto& position : positions) {
pushConstBlock.position = glm::vec4(position, 0.0f); pushConstBlock.position = glm::vec4(position, 0.0f);
vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(PushConstBlock), &pushConstBlock); vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(PushConstBlock), &pushConstBlock);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); // This will also bind the texture images to set 1
models.tree.draw(commandBuffer, vkglTF::RenderFlags::BindImages, pipelineLayout); models.tree.draw(commandBuffer, vkglTF::RenderFlags::BindImages, pipelineLayout);
} }
} }
@ -377,12 +367,11 @@ public:
vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor);
// One pass per cascade // One pass per cascade
// The layer that this pass renders to is defined by the cascade's image view (selected via the cascade's descriptor set)
for (uint32_t j = 0; j < SHADOW_MAP_CASCADE_COUNT; j++) { for (uint32_t j = 0; j < SHADOW_MAP_CASCADE_COUNT; j++) {
renderPassBeginInfo.framebuffer = cascades[j].frameBuffer; renderPassBeginInfo.framebuffer = cascades[j].frameBuffer;
vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, depthPass.pipeline); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, depthPass.pipeline);
renderScene(drawCmdBuffers[i], depthPass.pipelineLayout, cascades[j].descriptorSet, j); renderScene(drawCmdBuffers[i], depthPass.pipelineLayout, j);
vkCmdEndRenderPass(drawCmdBuffers[i]); vkCmdEndRenderPass(drawCmdBuffers[i]);
} }
} }
@ -430,7 +419,7 @@ public:
// Render shadowed scene // Render shadowed scene
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, (filterPCF) ? pipelines.sceneShadowPCF : pipelines.sceneShadow); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, (filterPCF) ? pipelines.sceneShadowPCF : pipelines.sceneShadow);
renderScene(drawCmdBuffers[i], pipelineLayout, descriptorSet); renderScene(drawCmdBuffers[i], pipelineLayout);
drawUI(drawCmdBuffers[i]); drawUI(drawCmdBuffers[i]);
@ -470,44 +459,31 @@ public:
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0),
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1), vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1),
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 2), vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 2),
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 3),
}; };
VkDescriptorSetLayoutCreateInfo descriptorLayout = VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings);
vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout));
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayouts.base));
/* /*
Descriptor sets Descriptor sets
*/ */
std::vector<VkWriteDescriptorSet> writeDescriptorSets;
VkDescriptorImageInfo depthMapDescriptor = VkDescriptorImageInfo depthMapDescriptor =
vks::initializers::descriptorImageInfo(depth.sampler, depth.view, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL); vks::initializers::descriptorImageInfo(depth.sampler, depth.view, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL);
VkDescriptorSetAllocateInfo allocInfo = VkDescriptorSetAllocateInfo allocInfo =
vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.base, 1); vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1);
// Scene rendering / debug display // Scene rendering / debug display
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet));
writeDescriptorSets = { const std::vector<VkWriteDescriptorSet> writeDescriptorSets = {
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.VS.descriptor), vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.VS.descriptor),
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &depthMapDescriptor), vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &depthMapDescriptor),
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &uniformBuffers.FS.descriptor), vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &uniformBuffers.FS.descriptor),
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3, &cascadeViewProjMatricesBuffer.descriptor),
}; };
vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL);
// Per-cascade descriptor sets
// Each descriptor set represents a single layer of the array texture
for (uint32_t i = 0; i < SHADOW_MAP_CASCADE_COUNT; i++) {
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &cascades[i].descriptorSet));
VkDescriptorImageInfo cascadeImageInfo = vks::initializers::descriptorImageInfo(depth.sampler, depth.view, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL);
writeDescriptorSets = {
vks::initializers::writeDescriptorSet(cascades[i].descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &depthPass.uniformBuffer.descriptor),
vks::initializers::writeDescriptorSet(cascades[i].descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &cascadeImageInfo)
};
vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL);
}
/* /*
Pipeline layouts Pipeline layouts
*/ */
@ -515,7 +491,7 @@ public:
// Shared pipeline layout (scene and depth map debug display) // Shared pipeline layout (scene and depth map debug display)
{ {
VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(PushConstBlock), 0); VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(PushConstBlock), 0);
std::array<VkDescriptorSetLayout, 2> setLayouts = { descriptorSetLayouts.base, vkglTF::descriptorSetLayoutImage }; std::array<VkDescriptorSetLayout, 2> setLayouts = { descriptorSetLayout, vkglTF::descriptorSetLayoutImage };
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast<uint32_t>(setLayouts.size())); VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast<uint32_t>(setLayouts.size()));
pipelineLayoutCreateInfo.pushConstantRangeCount = 1; pipelineLayoutCreateInfo.pushConstantRangeCount = 1;
pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange;
@ -525,7 +501,7 @@ public:
// Depth pass pipeline layout // Depth pass pipeline layout
{ {
VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(PushConstBlock), 0); VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(PushConstBlock), 0);
std::array<VkDescriptorSetLayout, 2> setLayouts = { descriptorSetLayouts.base, vkglTF::descriptorSetLayoutImage }; std::array<VkDescriptorSetLayout, 2> setLayouts = { descriptorSetLayout, vkglTF::descriptorSetLayoutImage };
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast<uint32_t>(setLayouts.size())); VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast<uint32_t>(setLayouts.size()));
pipelineLayoutCreateInfo.pushConstantRangeCount = 1; pipelineLayoutCreateInfo.pushConstantRangeCount = 1;
pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange;
@ -599,12 +575,12 @@ public:
void prepareUniformBuffers() void prepareUniformBuffers()
{ {
// Shadow map generation buffer blocks // Cascade matrices
VK_CHECK_RESULT(vulkanDevice->createBuffer( VK_CHECK_RESULT(vulkanDevice->createBuffer(
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
&depthPass.uniformBuffer, &cascadeViewProjMatricesBuffer,
sizeof(depthPass.ubo))); sizeof(glm::mat4) * SHADOW_MAP_CASCADE_COUNT));
// Scene uniform buffer blocks // Scene uniform buffer blocks
VK_CHECK_RESULT(vulkanDevice->createBuffer( VK_CHECK_RESULT(vulkanDevice->createBuffer(
@ -619,7 +595,7 @@ public:
sizeof(uboFS))); sizeof(uboFS)));
// Map persistent // Map persistent
VK_CHECK_RESULT(depthPass.uniformBuffer.map()); VK_CHECK_RESULT(cascadeViewProjMatricesBuffer.map());
VK_CHECK_RESULT(uniformBuffers.VS.map()); VK_CHECK_RESULT(uniformBuffers.VS.map());
VK_CHECK_RESULT(uniformBuffers.FS.map()); VK_CHECK_RESULT(uniformBuffers.FS.map());
@ -725,10 +701,11 @@ public:
/* /*
Depth rendering Depth rendering
*/ */
std::vector<glm::mat4> cascadeViewProjMatrices(SHADOW_MAP_CASCADE_COUNT);
for (uint32_t i = 0; i < SHADOW_MAP_CASCADE_COUNT; i++) { for (uint32_t i = 0; i < SHADOW_MAP_CASCADE_COUNT; i++) {
depthPass.ubo.cascadeViewProjMat[i] = cascades[i].viewProjMatrix; cascadeViewProjMatrices[i] = cascades[i].viewProjMatrix;
} }
memcpy(depthPass.uniformBuffer.mapped, &depthPass.ubo, sizeof(depthPass.ubo)); memcpy(cascadeViewProjMatricesBuffer.mapped, cascadeViewProjMatrices.data(), sizeof(glm::mat4) * SHADOW_MAP_CASCADE_COUNT);
/* /*
Scene rendering Scene rendering
@ -736,14 +713,10 @@ public:
uboVS.projection = camera.matrices.perspective; uboVS.projection = camera.matrices.perspective;
uboVS.view = camera.matrices.view; uboVS.view = camera.matrices.view;
uboVS.model = glm::mat4(1.0f); uboVS.model = glm::mat4(1.0f);
uboVS.lightDir = normalize(-lightPos); uboVS.lightDir = normalize(-lightPos);
memcpy(uniformBuffers.VS.mapped, &uboVS, sizeof(uboVS)); memcpy(uniformBuffers.VS.mapped, &uboVS, sizeof(uboVS));
for (uint32_t i = 0; i < SHADOW_MAP_CASCADE_COUNT; i++) { for (uint32_t i = 0; i < SHADOW_MAP_CASCADE_COUNT; i++) {
uboFS.cascadeSplits[i] = cascades[i].splitDepth; uboFS.cascadeSplits[i] = cascades[i].splitDepth;
uboFS.cascadeViewProjMat[i] = cascades[i].viewProjMatrix;
} }
uboFS.inverseViewMat = glm::inverse(camera.matrices.view); uboFS.inverseViewMat = glm::inverse(camera.matrices.view);
uboFS.lightDir = normalize(-lightPos); uboFS.lightDir = normalize(-lightPos);

View file

@ -11,16 +11,12 @@ layout(push_constant) uniform PushConsts {
uint cascadeIndex; uint cascadeIndex;
} pushConsts; } pushConsts;
layout (binding = 0) uniform UBO { layout (set = 0, binding = 3) uniform UBO {
mat4[SHADOW_MAP_CASCADE_COUNT] cascadeViewProjMat; mat4[SHADOW_MAP_CASCADE_COUNT] cascadeViewProjMat;
} ubo; } ubo;
layout (location = 0) out vec2 outUV; layout (location = 0) out vec2 outUV;
out gl_PerVertex {
vec4 gl_Position;
};
void main() void main()
{ {
outUV = inUV; outUV = inUV;

View file

@ -19,13 +19,16 @@ layout (location = 0) out vec4 outFragColor;
layout (set = 0, binding = 2) uniform UBO { layout (set = 0, binding = 2) uniform UBO {
vec4 cascadeSplits; vec4 cascadeSplits;
mat4 cascadeViewProjMat[SHADOW_MAP_CASCADE_COUNT];
mat4 inverseViewMat; mat4 inverseViewMat;
vec3 lightDir; vec3 lightDir;
float _pad; float _pad;
int colorCascades; int colorCascades;
} ubo; } ubo;
layout (set = 0, binding = 3) uniform CVPM {
mat4 matrices[SHADOW_MAP_CASCADE_COUNT];
} cascadeViewProjMatrices;
const mat4 biasMat = mat4( const mat4 biasMat = mat4(
0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0,
@ -84,7 +87,7 @@ void main()
} }
// Depth compare for shadowing // Depth compare for shadowing
vec4 shadowCoord = (biasMat * ubo.cascadeViewProjMat[cascadeIndex]) * vec4(inPos, 1.0); vec4 shadowCoord = (biasMat * cascadeViewProjMatrices.matrices[cascadeIndex]) * vec4(inPos, 1.0);
float shadow = 0; float shadow = 0;
if (enablePCF == 1) { if (enablePCF == 1) {

View file

@ -22,10 +22,6 @@ layout(push_constant) uniform PushConsts {
uint cascadeIndex; uint cascadeIndex;
} pushConsts; } pushConsts;
out gl_PerVertex {
vec4 gl_Position;
};
void main() void main()
{ {
outColor = inColor; outColor = inColor;

View file

@ -1,4 +1,5 @@
// Copyright 2020 Google LLC // Copyright 2020 Google LLC
// Copyright 2024 Sascha Willems
struct VSInput struct VSInput
{ {
@ -17,8 +18,7 @@ struct PushConsts {
struct UBO { struct UBO {
float4x4 cascadeViewProjMat[SHADOW_MAP_CASCADE_COUNT]; float4x4 cascadeViewProjMat[SHADOW_MAP_CASCADE_COUNT];
}; };
cbuffer ubo : register(b3) { UBO ubo; }
cbuffer ubo : register(b0) { UBO ubo; }
struct VSOutput struct VSOutput
{ {

View file

@ -1,4 +1,5 @@
// Copyright 2020 Google LLC // Copyright 2020 Google LLC
// Copyright 2024 Sascha Willems
#define SHADOW_MAP_CASCADE_COUNT 4 #define SHADOW_MAP_CASCADE_COUNT 4
@ -22,7 +23,6 @@ struct VSOutput
struct UBO { struct UBO {
float4 cascadeSplits; float4 cascadeSplits;
float4x4 cascadeViewProjMat[SHADOW_MAP_CASCADE_COUNT];
float4x4 inverseViewMat; float4x4 inverseViewMat;
float3 lightDir; float3 lightDir;
float _pad; float _pad;
@ -30,6 +30,11 @@ struct UBO {
}; };
cbuffer ubo : register(b2) { UBO ubo; }; cbuffer ubo : register(b2) { UBO ubo; };
struct CVPM {
float4x4 matrices[SHADOW_MAP_CASCADE_COUNT];
};
cbuffer cascadeViewProjMatrices : register(b3) { CVPM cascadeViewProjMatrices; }
static const float4x4 biasMat = float4x4( static const float4x4 biasMat = float4x4(
0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.5,
0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5,
@ -90,7 +95,7 @@ float4 main(VSOutput input) : SV_TARGET
} }
// Depth compare for shadowing // Depth compare for shadowing
float4 shadowCoord = mul(biasMat, mul(ubo.cascadeViewProjMat[cascadeIndex], float4(input.Pos, 1.0))); float4 shadowCoord = mul(biasMat, mul(cascadeViewProjMatrices.matrices[cascadeIndex], float4(input.Pos, 1.0)));
float shadow = 0; float shadow = 0;
if (enablePCF == 1) { if (enablePCF == 1) {