55namespace reactor
66{
77
8+ struct SceneUBO
9+ {
10+ glm::mat4 view;
11+ glm::mat4 projection;
12+ };
13+
814ShadowMapping::ShadowMapping (VulkanRenderer& renderer, uint32_t resolution)
915 : m_renderer(renderer), m_resolution(resolution), m_shadowMapView(VK_NULL_HANDLE),
1016 m_shadowMapSampler (VK_NULL_HANDLE)
@@ -76,7 +82,11 @@ void ShadowMapping::createResources()
7682 m_mvpBuffer.reserve (frameCount);
7783 for (size_t i = 0 ; i < frameCount; ++i)
7884 {
79- m_mvpBuffer.push_back (std::make_unique<Buffer>(m_renderer.allocator (), sizeof (glm::mat4), vk::BufferUsageFlagBits::eUniformBuffer, VMA_MEMORY_USAGE_AUTO, " MVP Buffer" ));
85+ m_mvpBuffer.push_back (std::make_unique<Buffer>(m_renderer.allocator (),
86+ sizeof (SceneUBO),
87+ vk::BufferUsageFlagBits::eUniformBuffer,
88+ VMA_MEMORY_USAGE_CPU_TO_GPU,
89+ " MVP Buffer" ));
8090 }
8191}
8292
@@ -99,8 +109,10 @@ void ShadowMapping::createPipeline()
99109 // No fragment shader, we only want depth output
100110 .setVertexInputFromVertex ()
101111 .setDepthAttachment (vk::Format::eD32Sfloat, true ) // depth test and write enabled
112+ .enableDepthBias ()
102113 .setDescriptorSetLayouts (setLayouts)
103- .setMultisample (4 )
114+ .setMultisample (1 )
115+ .setCullMode (vk::CullModeFlagBits::eFront)
104116 .setFrontFace (vk::FrontFace::eClockwise) // Match main geometry pipeline
105117 .addPushContantRange (vk::ShaderStageFlagBits::eVertex, 0 , sizeof (glm::mat4));
106118
@@ -115,7 +127,7 @@ void ShadowMapping::createDescriptors()
115127
116128 // Descriptor set bindings: UBO for light's MVP
117129 std::vector<vk::DescriptorSetLayoutBinding> bindings = {
118- { 0 , vk::DescriptorType::eUniformBuffer, 1 , vk::ShaderStageFlagBits::eVertex }
130+ {0 , vk::DescriptorType::eUniformBuffer, 1 , vk::ShaderStageFlagBits::eVertex}
119131 // Add more if you want—for example for a sampler or shadow map
120132 };
121133
@@ -128,7 +140,7 @@ void ShadowMapping::createDescriptors()
128140 vk::DescriptorBufferInfo uboInfo{};
129141 uboInfo.buffer = m_mvpBuffer[i]->getHandle ();
130142 uboInfo.offset = 0 ;
131- uboInfo.range = sizeof (glm::mat4 );
143+ uboInfo.range = sizeof (SceneUBO );
132144
133145 vk::WriteDescriptorSet writes{};
134146 writes.dstSet = m_descriptors->get (i);
@@ -140,7 +152,76 @@ void ShadowMapping::createDescriptors()
140152
141153 m_descriptors->updateSet ({writes});
142154 }
155+ }
156+
157+ void ShadowMapping::recordShadowPass (vk::CommandBuffer cmd,
158+ size_t frameIndex,
159+ const std::function<void (vk::CommandBuffer)>& drawCallback)
160+ {
161+ vk::ClearValue clearDepth;
162+ clearDepth.depthStencil = vk::ClearDepthStencilValue{1 .0f , 0 };
163+
164+ vk::RenderingAttachmentInfo depthAttachment{};
165+ depthAttachment.imageView = m_shadowMapView;
166+ depthAttachment.imageLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
167+ depthAttachment.loadOp = vk::AttachmentLoadOp::eClear;
168+ depthAttachment.storeOp = vk::AttachmentStoreOp::eStore;
169+ depthAttachment.clearValue = clearDepth;
170+
171+ vk::RenderingInfo renderingInfo{};
172+ renderingInfo.renderArea = vk::Rect2D ({0 , 0 }, {m_resolution, m_resolution});
173+ renderingInfo.layerCount = 1 ;
174+ renderingInfo.pDepthAttachment = &depthAttachment;
175+
176+ cmd.setDepthBias (depthBiasConstant, 0 .0f , depthBiasSlope);
177+
178+ cmd.beginRendering (&renderingInfo);
179+
180+ // set viewport/scissor
181+ vk::Viewport viewport = {0 .0f , 0 .0f , (float )m_resolution, (float )m_resolution, 0 .0f , 1 .0f };
182+ vk::Rect2D scissor = {vk::Offset2D{0 , 0 }, vk::Extent2D{m_resolution, m_resolution}};
183+ cmd.setViewport (0 , viewport);
184+ cmd.setScissor (0 , scissor);
185+
186+ cmd.bindPipeline (vk::PipelineBindPoint::eGraphics, m_depthPassPipeline->get ());
187+
188+ auto descriptor = m_descriptors->get (frameIndex);
189+
190+ // bind descriptor set (with light MVP)
191+ cmd.bindDescriptorSets (
192+ vk::PipelineBindPoint::eGraphics, m_depthPassPipeline->getLayout (), 0 , 1 , &descriptor, 0 , nullptr );
143193
194+ // draw the shadow casters
195+ drawCallback (cmd);
196+
197+ cmd.endRendering ();
198+ }
199+
200+ vk::ImageView ShadowMapping::shadowMapView () const
201+ {
202+ return m_shadowMapView;
203+ }
204+
205+ vk::Sampler ShadowMapping::shadowMapSampler () const
206+ {
207+ return m_shadowMapSampler;
208+ }
209+
210+ vk::DescriptorSet ShadowMapping::shadowMapDescriptorSet (size_t frameIndex) const
211+ {
212+ return m_descriptors->get (frameIndex);
213+ }
214+
215+ void ShadowMapping::setLightMatrix (const glm::mat4& lightSpaceMatrix, size_t frameIndex)
216+ {
217+ SceneUBO ubo;
218+ ubo.view = glm::mat4 (1 .0f );
219+ ubo.projection = lightSpaceMatrix;
220+
221+ // map buffer, copy matrix
222+ void * data = m_mvpBuffer[frameIndex]->map ();
223+ memcpy (data, &ubo, sizeof (SceneUBO));
224+ m_mvpBuffer[frameIndex]->unmap ();
144225}
145226
146227} // namespace reactor
0 commit comments