EDIT: shadow on/off

This commit is contained in:
2025-12-08 17:38:13 +09:00
parent 33fc35ab6c
commit f62ce93695
9 changed files with 56 additions and 17 deletions

View File

@@ -189,6 +189,12 @@ float sampleCascadeShadow(uint ci, vec3 worldPos, vec3 N, vec3 L)
float calcShadowVisibility(vec3 worldPos, vec3 N, vec3 L) float calcShadowVisibility(vec3 worldPos, vec3 N, vec3 L)
{ {
// Early out when shadows are globally disabled.
if (sceneData.rtParams.y <= 0.0)
{
return 1.0;
}
vec3 wp = worldPos + N * SHADOW_NORMAL_OFFSET * (0.5 + 0.5 * (1.0 - max(dot(N, L), 0.0))); vec3 wp = worldPos + N * SHADOW_NORMAL_OFFSET * (0.5 + 0.5 * (1.0 - max(dot(N, L), 0.0)));
// RT-only mode: cast a ray and skip clipmap sampling entirely // RT-only mode: cast a ray and skip clipmap sampling entirely
@@ -301,7 +307,7 @@ void main(){
// Optional RT shadow for the first few point lights (hybrid mode) // Optional RT shadow for the first few point lights (hybrid mode)
#ifdef GL_EXT_ray_query #ifdef GL_EXT_ray_query
if (sceneData.rtOptions.x == 1u && i < 4u) if (sceneData.rtOptions.x == 1u && sceneData.rtParams.y > 0.0 && i < 4u)
{ {
vec3 toL = sceneData.punctualLights[i].position_radius.xyz - pos; vec3 toL = sceneData.punctualLights[i].position_radius.xyz - pos;
float maxT = length(toL); float maxT = length(toL);

View File

@@ -181,6 +181,12 @@ float sampleCascadeShadow(uint ci, vec3 worldPos, vec3 N, vec3 L)
float calcShadowVisibility(vec3 worldPos, vec3 N, vec3 L) float calcShadowVisibility(vec3 worldPos, vec3 N, vec3 L)
{ {
// Early out when shadows are globally disabled.
if (sceneData.rtParams.y <= 0.0)
{
return 1.0;
}
vec3 wp = worldPos + N * SHADOW_NORMAL_OFFSET * (0.5 + 0.5 * (1.0 - max(dot(N, L), 0.0))); vec3 wp = worldPos + N * SHADOW_NORMAL_OFFSET * (0.5 + 0.5 * (1.0 - max(dot(N, L), 0.0)));
CascadeMix cm = computeCascadeMix(wp); CascadeMix cm = computeCascadeMix(wp);

View File

@@ -23,11 +23,12 @@ layout(set = 0, binding = 0) uniform SceneData{
mat4 lightViewProjCascades[4]; mat4 lightViewProjCascades[4];
// View-space split distances for selecting cascades (x,y,z,w) // View-space split distances for selecting cascades (x,y,z,w)
vec4 cascadeSplitsView; vec4 cascadeSplitsView;
// Ray-query settings (packed) // Ray-query & reflection settings (packed)
// rtOptions.x = enabled (1/0) // rtOptions.x = RT shadows enabled (1/0)
// rtOptions.y = cascade bitmask (bit i => cascade i assisted) // rtOptions.y = cascade bitmask (bit i => cascade i assisted)
uvec4 rtOptions; uvec4 rtOptions;
// rtParams.x = N·L threshold; others reserved // rtParams.x = N·L threshold for hybrid shadows
// rtParams.y = shadows enabled flag (1.0 = on, 0.0 = off)
vec4 rtParams; vec4 rtParams;
GPUPunctualLight punctualLights[MAX_PUNCTUAL_LIGHTS]; GPUPunctualLight punctualLights[MAX_PUNCTUAL_LIGHTS];

View File

@@ -37,6 +37,8 @@ struct ShadowSettings
{ {
// 0 = Clipmap only, 1 = Clipmap + RT assist, 2 = RT only // 0 = Clipmap only, 1 = Clipmap + RT assist, 2 = RT only
uint32_t mode = 2; uint32_t mode = 2;
// Global enable/disable for all shadowing (raster + RT).
bool enabled = true;
bool hybridRayQueryEnabled = false; // derived convenience: (mode != 0) bool hybridRayQueryEnabled = false; // derived convenience: (mode != 0)
uint32_t hybridRayCascadesMask = 0b1110; // bit i => cascade i uses ray query assist (default: 1..3) uint32_t hybridRayCascadesMask = 0b1110; // bit i => cascade i uses ray query assist (default: 1..3)
float hybridRayNoLThreshold = 0.25f; // trigger when N·L below this (mode==1) float hybridRayNoLThreshold = 0.25f; // trigger when N·L below this (mode==1)

View File

@@ -771,9 +771,12 @@ void VulkanEngine::draw()
// Build or update TLAS for current frame now that the previous frame is idle. // Build or update TLAS for current frame now that the previous frame is idle.
// TLAS is used for hybrid/full RT shadows and RT-assisted SSR reflections. // TLAS is used for hybrid/full RT shadows and RT-assisted SSR reflections.
// For reflections, only build TLAS when RT is actually enabled (reflectionMode != 0). // For reflections, only build TLAS when RT is actually enabled (reflectionMode != 0).
if (_rayManager && // For shadows, only build TLAS when shadows are enabled and an RT shadow mode is selected.
(_context->shadowSettings.mode != 0u || const bool rtShadowsActive =
(_context->enableSSR && _context->reflectionMode != 0u))) _context->shadowSettings.enabled && (_context->shadowSettings.mode != 0u);
const bool rtReflectionsActive =
_context->enableSSR && (_context->reflectionMode != 0u);
if (_rayManager && (rtShadowsActive || rtReflectionsActive))
{ {
_rayManager->buildTLASFromDrawContext(_context->getMainDrawContext(), get_current_frame()._deletionQueue); _rayManager->buildTLASFromDrawContext(_context->getMainDrawContext(), get_current_frame()._deletionQueue);
} }
@@ -817,7 +820,7 @@ void VulkanEngine::draw()
// For debug overlays (IBL volumes), re-use HDR draw image as a color target. // For debug overlays (IBL volumes), re-use HDR draw image as a color target.
RGImageHandle hDebugColor = hDraw; RGImageHandle hDebugColor = hDraw;
// Create transient depth targets for cascaded shadow maps (even if RT-only, to keep descriptors stable) // Create transient depth targets for cascaded shadow maps (even if RT-only / disabled, to keep descriptors stable)
const VkExtent2D shadowExtent{2048, 2048}; const VkExtent2D shadowExtent{2048, 2048};
std::array<RGImageHandle, kShadowCascadeCount> hShadowCascades{}; std::array<RGImageHandle, kShadowCascadeCount> hShadowCascades{};
for (int i = 0; i < kShadowCascadeCount; ++i) for (int i = 0; i < kShadowCascadeCount; ++i)
@@ -846,7 +849,7 @@ void VulkanEngine::draw()
{ {
background->register_graph(_renderGraph.get(), hDraw, hDepth); background->register_graph(_renderGraph.get(), hDraw, hDepth);
} }
if (_context->shadowSettings.mode != 2u) if (_context->shadowSettings.enabled && _context->shadowSettings.mode != 2u)
{ {
if (auto *shadow = _renderPassManager->getPass<ShadowPass>()) if (auto *shadow = _renderPassManager->getPass<ShadowPass>())
{ {

View File

@@ -515,6 +515,12 @@ namespace
ImGui::Separator(); ImGui::Separator();
auto &ss = eng->_context->shadowSettings; auto &ss = eng->_context->shadowSettings;
// Global on/off toggle for all shadowing.
ImGui::Checkbox("Enable Shadows", &ss.enabled);
ImGui::Separator();
ImGui::BeginDisabled(!ss.enabled);
int mode = static_cast<int>(ss.mode); int mode = static_cast<int>(ss.mode);
ImGui::TextUnformatted("Shadow Mode"); ImGui::TextUnformatted("Shadow Mode");
ImGui::RadioButton("Clipmap only", &mode, 0); ImGui::RadioButton("Clipmap only", &mode, 0);
@@ -524,7 +530,7 @@ namespace
ImGui::RadioButton("RT only", &mode, 2); ImGui::RadioButton("RT only", &mode, 2);
if (!(rq && as) && mode != 0) mode = 0; // guard for unsupported HW if (!(rq && as) && mode != 0) mode = 0; // guard for unsupported HW
ss.mode = static_cast<uint32_t>(mode); ss.mode = static_cast<uint32_t>(mode);
ss.hybridRayQueryEnabled = (ss.mode != 0); ss.hybridRayQueryEnabled = ss.enabled && (ss.mode != 0);
ImGui::BeginDisabled(ss.mode != 1u); ImGui::BeginDisabled(ss.mode != 1u);
ImGui::TextUnformatted("Cascades using ray assist:"); ImGui::TextUnformatted("Cascades using ray assist:");
@@ -541,6 +547,7 @@ namespace
} }
ImGui::SliderFloat("N·L threshold", &ss.hybridRayNoLThreshold, 0.0f, 1.0f, "%.2f"); ImGui::SliderFloat("N·L threshold", &ss.hybridRayNoLThreshold, 0.0f, 1.0f, "%.2f");
ImGui::EndDisabled(); ImGui::EndDisabled();
ImGui::EndDisabled();
ImGui::Separator(); ImGui::Separator();
ImGui::TextWrapped( ImGui::TextWrapped(

View File

@@ -119,9 +119,15 @@ struct GPUSceneData {
glm::mat4 lightViewProjCascades[4]; glm::mat4 lightViewProjCascades[4];
glm::vec4 cascadeSplitsView; glm::vec4 cascadeSplitsView;
// Hybrid ray-query options (match shaders/input_structures.glsl) // Hybrid ray-query / reflection options (match shaders/input_structures.glsl)
glm::uvec4 rtOptions; // x: enabled (1/0), y: cascade mask, z,w: reserved // rtOptions.x = RT shadows enabled (1/0)
glm::vec4 rtParams; // x: N·L threshold, yzw: reserved // rtOptions.y = cascade bitmask (bit i => cascade i assisted)
// rtOptions.z = shadow mode (0 = clipmap, 1 = hybrid, 2 = RT only)
// rtOptions.w = reflection mode (SSR/RT)
glm::uvec4 rtOptions;
// rtParams.x = N·L threshold for hybrid shadows
// rtParams.y = shadows enabled flag (1.0 = on, 0.0 = off)
glm::vec4 rtParams;
GPUPunctualLight punctualLights[kMaxPunctualLights]; GPUPunctualLight punctualLights[kMaxPunctualLights];
glm::uvec4 lightCounts; glm::uvec4 lightCounts;

View File

@@ -192,7 +192,12 @@ void LightingPass::draw_lighting(VkCommandBuffer cmd,
const bool haveRTFeatures = ctxLocal->getDevice()->supportsAccelerationStructure(); const bool haveRTFeatures = ctxLocal->getDevice()->supportsAccelerationStructure();
const VkAccelerationStructureKHR tlas = (ctxLocal->ray ? ctxLocal->ray->tlas() : VK_NULL_HANDLE); const VkAccelerationStructureKHR tlas = (ctxLocal->ray ? ctxLocal->ray->tlas() : VK_NULL_HANDLE);
const VkDeviceAddress tlasAddr = (ctxLocal->ray ? ctxLocal->ray->tlasAddress() : 0); const VkDeviceAddress tlasAddr = (ctxLocal->ray ? ctxLocal->ray->tlasAddress() : 0);
const bool useRT = haveRTFeatures && (ctxLocal->shadowSettings.mode != 0u) && (tlas != VK_NULL_HANDLE) && (tlasAddr != 0); const bool useRT =
haveRTFeatures &&
ctxLocal->shadowSettings.enabled &&
(ctxLocal->shadowSettings.mode != 0u) &&
(tlas != VK_NULL_HANDLE) &&
(tlasAddr != 0);
const char* pipeName = useRT ? "deferred_lighting.rt" : "deferred_lighting.nort"; const char* pipeName = useRT ? "deferred_lighting.rt" : "deferred_lighting.nort";
if (!pipelineManager->getGraphics(pipeName, _pipeline, _pipelineLayout)) if (!pipelineManager->getGraphics(pipeName, _pipeline, _pipelineLayout))

View File

@@ -346,12 +346,15 @@ void SceneManager::update_scene()
if (_context) if (_context)
{ {
const auto &ss = _context->shadowSettings; const auto &ss = _context->shadowSettings;
const uint32_t rtEnabled = (ss.mode != 0) ? 1u : 0u; // RT shadows are considered active only when shadows are enabled and
// a hybrid/RT shadow mode is selected (mode != 0).
const uint32_t rtEnabled = (ss.enabled && ss.mode != 0u) ? 1u : 0u;
const uint32_t reflMode = _context->reflectionMode; const uint32_t reflMode = _context->reflectionMode;
// rtOptions.x = RT shadows enabled, y = cascade mask, z = shadow mode, w = reflection mode (SSR/RT) // rtOptions.x = RT shadows enabled, y = cascade mask, z = shadow mode, w = reflection mode (SSR/RT)
sceneData.rtOptions = glm::uvec4(rtEnabled, ss.hybridRayCascadesMask, ss.mode, reflMode); sceneData.rtOptions = glm::uvec4(rtEnabled, ss.hybridRayCascadesMask, ss.mode, reflMode);
// rtParams.x = N·L threshold for hybrid shadows; remaining components reserved // rtParams.x = N·L threshold for hybrid shadows
sceneData.rtParams = glm::vec4(ss.hybridRayNoLThreshold, 0.0f, 0.0f, 0.0f); // rtParams.y = shadows enabled flag (1.0 = on, 0.0 = off)
sceneData.rtParams = glm::vec4(ss.hybridRayNoLThreshold, ss.enabled ? 1.0f : 0.0f, 0.0f, 0.0f);
} }
// Fill punctual lights into GPUSceneData // Fill punctual lights into GPUSceneData