Merge branch 'CSM-new'

CSM-dev is clipmap shadow map and it works
This commit is contained in:
2025-10-23 00:35:44 +09:00
11 changed files with 128 additions and 163 deletions

View File

@@ -10,10 +10,18 @@ inline constexpr bool kUseValidationLayers = true;
// Shadow mapping configuration
inline constexpr int kShadowCascadeCount = 4;
// Maximum shadow distance for CSM in view-space units
inline constexpr float kShadowCSMFar = 50.0f;
inline constexpr float kShadowCSMFar = 400.0f;
// Shadow map resolution used for stabilization (texel snapping). Must match actual image size.
inline constexpr float kShadowMapResolution = 4096.0f;
inline constexpr float kShadowMapResolution = 2048.0f;
// Extra XY expansion for cascade footprint (safety against FOV/aspect changes)
inline constexpr float kShadowCascadeRadiusScale = 1.15f;
inline constexpr float kShadowCascadeRadiusScale = 2.5f;
// Additive XY margin in world units (light-space) beyond scaled radius
inline constexpr float kShadowCascadeRadiusMargin = 10.0f;
inline constexpr float kShadowCascadeRadiusMargin = 40.0f;
// Clipmap shadow configuration (used when cascades operate in clipmap mode)
// Base coverage radius of level 0 around the camera (world units). Each level doubles the radius.
inline constexpr float kShadowClipBaseRadius = 20.0f;
// Pullback distance of the light eye from the clipmap center along the light direction (world units)
inline constexpr float kShadowClipLightPullback = 160.0f;
// Additional Z padding for the orthographic frustum along light direction
inline constexpr float kShadowClipZPadding = 80.0f;

View File

@@ -18,6 +18,8 @@
#include "render/vk_pipelines.h"
#include <iostream>
#include <glm/gtx/transform.hpp>
#include "config.h"
#include "render/primitives.h"
#include "vk_mem_alloc.h"
@@ -126,7 +128,7 @@ void VulkanEngine::init()
auto imguiPass = std::make_unique<ImGuiPass>();
_renderPassManager->setImGuiPass(std::move(imguiPass));
const std::string structurePath = _assetManager->modelPath("seoul_high.glb");
const std::string structurePath = _assetManager->modelPath("police_office.glb");
const auto structureFile = _assetManager->loadGLTF(structurePath);
assert(structureFile.has_value());
@@ -317,6 +319,7 @@ void VulkanEngine::draw()
RGImageHandle hGBufferAlbedo = _renderGraph->import_gbuffer_albedo();
RGImageHandle hSwapchain = _renderGraph->import_swapchain_image(swapchainImageIndex);
// Create a transient shadow depth target (fixed resolution for now)
// Create transient depth targets for cascaded shadow maps
const VkExtent2D shadowExtent{2048, 2048};
std::array<RGImageHandle, kShadowCascadeCount> hShadowCascades{};

View File

@@ -35,11 +35,9 @@ void SamplerManager::init(DeviceManager *deviceManager)
sh.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
sh.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
sh.compareEnable = VK_FALSE; // manual PCF
// Depth shadow maps are single-level; keep base LOD only and avoid mip filtering.
sh.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
sh.maxLod = 0.0f;
sh.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
vkCreateSampler(_deviceManager->device(), &sh, nullptr, &_shadowLinearClamp);
}
void SamplerManager::cleanup()
@@ -56,6 +54,7 @@ void SamplerManager::cleanup()
vkDestroySampler(_deviceManager->device(), _defaultSamplerLinear, nullptr);
_defaultSamplerLinear = VK_NULL_HANDLE;
}
if (_shadowLinearClamp)
{
vkDestroySampler(_deviceManager->device(), _shadowLinearClamp, nullptr);

View File

@@ -15,6 +15,7 @@ public:
VkSampler defaultNearest() const { return _defaultSamplerNearest; }
VkSampler shadowLinearClamp() const { return _shadowLinearClamp; }
private:
DeviceManager *_deviceManager = nullptr;
VkSampler _defaultSamplerLinear = VK_NULL_HANDLE;