From 8b1535ca06fef9aeb69719e8308bf97a28261052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Mon, 26 May 2025 07:54:29 +0200 Subject: [PATCH] added capsule reflection blockers --- WickedEngine/shaders/ShaderInterop_Renderer.h | 2 +- WickedEngine/shaders/globals.hlsli | 13 +++--- WickedEngine/shaders/lightCullingCS.hlsl | 2 - WickedEngine/shaders/shadingHF.hlsli | 22 ++++++--- WickedEngine/wiRenderer.cpp | 46 +++++++------------ WickedEngine/wiVersion.cpp | 2 +- 6 files changed, 41 insertions(+), 46 deletions(-) diff --git a/WickedEngine/shaders/ShaderInterop_Renderer.h b/WickedEngine/shaders/ShaderInterop_Renderer.h index 18137c417..0a22450fe 100644 --- a/WickedEngine/shaders/ShaderInterop_Renderer.h +++ b/WickedEngine/shaders/ShaderInterop_Renderer.h @@ -1047,7 +1047,7 @@ struct alignas(16) ShaderFrustumCorners #endif // __cplusplus }; -static const float CAPSULE_SHADOW_AFFECTION_RANGE = 2; // how far away the capsule shadow can reach outside of their own radius +static const float CAPSULE_SHADOW_AFFECTION_RANGE = 4; // how far away the capsule shadow can reach outside of their own radius static const float CAPSULE_SHADOW_BOLDEN = 1.1f; // multiplier for capsule shadow capsule radiuses globally static const uint SHADER_ENTITY_COUNT = 256; diff --git a/WickedEngine/shaders/globals.hlsli b/WickedEngine/shaders/globals.hlsli index 98caa6c70..b133b78d5 100644 --- a/WickedEngine/shaders/globals.hlsli +++ b/WickedEngine/shaders/globals.hlsli @@ -750,6 +750,7 @@ struct PrimitiveID #define HEMISPHERE_SAMPLING_PDF rcp(2 * PI) #define sqr(a) ((a)*(a)) +#define pow3(a) ((a)*(a)*(a)) #define pow4(a) ((a)*(a)*(a)*(a)) #define pow5(a) ((a)*(a)*(a)*(a)*(a)) #define pow8(a) ((a)*(a)*(a)*(a)*(a)*(a)*(a)*(a)) @@ -881,31 +882,31 @@ inline uint4 align(uint4 value, uint4 alignment) inline float2 uv_to_clipspace(in float2 uv) { - float2 clipspace = uv * 2 - 1; + float2 clipspace = mad(uv, 2, -1); clipspace.y *= -1; return clipspace; } inline half2 uv_to_clipspace(in half2 uv) { - half2 clipspace = uv * 2 - 1; + half2 clipspace = mad(uv, 2, -1); clipspace.y *= -1; return clipspace; } inline float2 clipspace_to_uv(in float2 clipspace) { - return clipspace * float2(0.5, -0.5) + 0.5; + return mad(clipspace, float2(0.5, -0.5), 0.5); } inline float3 clipspace_to_uv(in float3 clipspace) { - return clipspace * float3(0.5, -0.5, 1) + float3(0.5, 0.5, 0); + return mad(clipspace, float3(0.5, -0.5, 1), float3(0.5, 0.5, 0)); } inline half2 clipspace_to_uv(in half2 clipspace) { - return clipspace * half2(0.5, -0.5) + 0.5; + return mad(clipspace, half2(0.5, -0.5), 0.5); } inline half3 clipspace_to_uv(in half3 clipspace) { - return clipspace * half3(0.5, -0.5, 1) + half3(0.5, 0.5, 0); + return mad(clipspace, half3(0.5, -0.5, 1), half3(0.5, 0.5, 0)); } inline half3 GetSunColor() { return unpack_half3(GetWeather().sun_color); } // sun color with intensity applied diff --git a/WickedEngine/shaders/lightCullingCS.hlsl b/WickedEngine/shaders/lightCullingCS.hlsl index e6c0b5716..a54d40685 100644 --- a/WickedEngine/shaders/lightCullingCS.hlsl +++ b/WickedEngine/shaders/lightCullingCS.hlsl @@ -2,8 +2,6 @@ #include "cullingShaderHF.hlsli" #include "lightingHF.hlsli" -#define entityCount (GetFrame().entity_culling_count) - RWStructuredBuffer entityTiles : register(u0); // Group shared variables. diff --git a/WickedEngine/shaders/shadingHF.hlsli b/WickedEngine/shaders/shadingHF.hlsli index 320d21a3b..a93ca6f41 100644 --- a/WickedEngine/shaders/shadingHF.hlsli +++ b/WickedEngine/shaders/shadingHF.hlsli @@ -557,16 +557,18 @@ inline void TiledLighting(inout Surface surface, inout Lighting lighting, uint f } } - // Capsule shadows: + // Capsule shadows and capsule reflection blockers: [branch] if ((GetFrame().options & OPTION_BIT_CAPSULE_SHADOW_ENABLED) && !surface.IsCapsuleShadowDisabled() && !forces().empty()) // capsule shadows are contained in forces array for now... { - half4 cone = half4(surface.dominant_lightdir, GetCapsuleShadowAngle()); + half4 occlusion_cone = half4(surface.dominant_lightdir, GetCapsuleShadowAngle()); + half4 reflection_cone = half4(surface.R, max(0.001, sqr(surface.roughness) * 0.5)); half capsuleshadow = 1; + half capsulereflection = 1; // Loop through light buckets in the tile: ShaderEntityIterator iterator = forces(); - for (uint bucket = iterator.first_bucket(); (bucket <= iterator.last_bucket()) && (capsuleshadow > 0); ++bucket) + for (uint bucket = iterator.first_bucket(); (bucket <= iterator.last_bucket()) && (capsuleshadow > 0 || capsulereflection > 0); ++bucket) { uint bucket_bits = load_entitytile(flatTileIndex + bucket); bucket_bits = iterator.mask_entity(bucket, bucket_bits); @@ -577,7 +579,7 @@ inline void TiledLighting(inout Surface surface, inout Lighting lighting, uint f #endif // ENTITY_TILE_UNIFORM [loop] - while ((bucket_bits != 0) && (capsuleshadow > 0)) + while ((bucket_bits != 0) && (capsuleshadow > 0 || capsulereflection > 0)) { // Retrieve global entity index from local bucket, then remove bit from local bucket: const uint bucket_bit_index = firstbitlow(bucket_bits); @@ -591,21 +593,27 @@ inline void TiledLighting(inout Surface surface, inout Lighting lighting, uint f float3 A = entity.position; float3 B = entity.GetColliderTip(); half radius = entity.GetRange() * CAPSULE_SHADOW_BOLDEN; - half occ = directionalOcclusionCapsule(surface.P, A, B, radius, cone); + half occ = directionalOcclusionCapsule(surface.P, A, B, radius, occlusion_cone); + half ref = directionalOcclusionCapsule(surface.P, A, B, radius, reflection_cone); // attenuation based on capsule-sphere: float3 center = lerp(A, B, 0.5); half range = distance(center, A) + radius + CAPSULE_SHADOW_AFFECTION_RANGE; half range2 = range * range; - half dist2 = distance_squared(surface.P, center); - occ = 1 - saturate((1 - occ) * saturate(attenuation_pointlight(dist2, range, range2))); + occ = 1 - saturate((1 - occ) * saturate(attenuation_pointlight(distance_squared(surface.P, center), range, range2))); + ref = 1 - saturate((1 - ref) * saturate(attenuation_pointlight(distance_squared(closest_point_on_line(surface.P, surface.P + surface.R, center), center), range, range2))); capsuleshadow *= occ; + capsulereflection *= ref; } } capsuleshadow = lerp(capsuleshadow, 1, GetCapsuleShadowFade()); capsuleshadow = saturate(capsuleshadow); surface.occlusion *= capsuleshadow; + + capsulereflection = pow4(capsulereflection); + lighting.direct.specular *= capsulereflection; + lighting.indirect.specular *= capsulereflection; } } diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index b47041074..e236da0cd 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -9922,42 +9922,30 @@ void ComputeTiledLightCulling( BindCommonResources(cmd); - // Perform the culling + device->EventBegin("Entity Culling", cmd); + + if (GetDebugLightCulling() && debugUAV.IsValid()) { - device->EventBegin("Entity Culling", cmd); - - if (GetDebugLightCulling() && debugUAV.IsValid()) - { - device->BindComputeShader(&shaders[GetAdvancedLightCulling() ? CSTYPE_LIGHTCULLING_ADVANCED_DEBUG : CSTYPE_LIGHTCULLING_DEBUG], cmd); - device->BindUAV(&debugUAV, 3, cmd); - } - else - { - device->BindComputeShader(&shaders[GetAdvancedLightCulling() ? CSTYPE_LIGHTCULLING_ADVANCED : CSTYPE_LIGHTCULLING], cmd); - } - - const GPUResource* uavs[] = { - &res.entityTiles, - }; - device->BindUAVs(uavs, 0, arraysize(uavs), cmd); - - device->Dispatch(res.tileCount.x, res.tileCount.y, 1, cmd); - - { - GPUBarrier barriers[] = { - GPUBarrier::Buffer(&res.entityTiles, ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE), - }; - device->Barrier(barriers, arraysize(barriers), cmd); - } - - device->EventEnd(cmd); + device->BindComputeShader(&shaders[GetAdvancedLightCulling() ? CSTYPE_LIGHTCULLING_ADVANCED_DEBUG : CSTYPE_LIGHTCULLING_DEBUG], cmd); + device->BindUAV(&debugUAV, 3, cmd); } + else + { + device->BindComputeShader(&shaders[GetAdvancedLightCulling() ? CSTYPE_LIGHTCULLING_ADVANCED : CSTYPE_LIGHTCULLING], cmd); + } + + device->BindUAV(&res.entityTiles, 0, cmd); + + device->Dispatch(res.tileCount.x, res.tileCount.y, 1, cmd); + + device->Barrier(GPUBarrier::Buffer(&res.entityTiles, ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE), cmd); + + device->EventEnd(cmd); // Unbind from UAV slots: GPUResource empty; const GPUResource* uavs[] = { &empty, - &empty }; device->BindUAVs(uavs, 0, arraysize(uavs), cmd); diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 02890282d..2bc476bf0 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 776; + const int revision = 777; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);