diff --git a/TombEngine/Game/collision/floordata.cpp b/TombEngine/Game/collision/floordata.cpp index b1ffdac52..99e0200cf 100644 --- a/TombEngine/Game/collision/floordata.cpp +++ b/TombEngine/Game/collision/floordata.cpp @@ -546,7 +546,7 @@ namespace TEN::Collision::Floordata // For bridges with zero thickness (which is incorrect setup, but still possible), break out of // infinite loop caused by infinite traversal over the same height value. int nextPos = sector->GetBridgeSurfaceHeight(pos, !isBottom); - if (nextPos = pos.y) + if (nextPos == pos.y) nextPos += (isBottom ? 1 : -1); // Set vertical position to lowest bridge ceiling height or highest bridge floor height. diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 1b3d12275..c1f02c035 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -209,6 +209,12 @@ namespace TEN::Renderer for (int k = 0; k < obj.ObjectMeshes.size(); k++) { + if (item->MeshIds.size() <= k) + { + TENLog("Mesh structure was not properly initialized for object " + GetObjectName((GAME_OBJECT_ID)item->ObjectID)); + break; + } + auto* mesh = GetMesh(item->MeshIds[k]); for (auto& bucket : mesh->Buckets) diff --git a/TombEngine/Shaders/Shadows.hlsli b/TombEngine/Shaders/Shadows.hlsli index c71c2f32e..c0c4e4f63 100644 --- a/TombEngine/Shaders/Shadows.hlsli +++ b/TombEngine/Shaders/Shadows.hlsli @@ -2,8 +2,9 @@ #include "./Math.hlsli" #include "./ShaderLight.hlsli" -#define SHADOW_INTENSITY (0.55f) -#define INV_SHADOW_INTENSITY (1.0f - SHADOW_INTENSITY) +#define SHADOW_INTENSITY (0.5f) +#define SHADOW_BLUR_MIN (2.0f) +#define SHADOW_BLUR_MAX (8.0f) struct Sphere { @@ -102,6 +103,11 @@ float3 DoShadow(float3 worldPos, float3 normal, float3 lighting, float bias) float ndot = dot(normal, dir); float facingFactor = saturate((ndot - bias) / (1.0f - bias + EPSILON)); + // Calculate distance-based blur factor with non-linear progression + float distanceToLight = length(Light.Position - worldPos); + float blurFactor = pow(saturate(distanceToLight / Light.Out), 2.0f); + float kernelSize = lerp(SHADOW_BLUR_MIN, SHADOW_BLUR_MAX, blurFactor); + [unroll] for (int i = 0; i < 6; i++) { @@ -119,18 +125,19 @@ float3 DoShadow(float3 worldPos, float3 normal, float3 lighting, float bias) lightClipSpace.y = lightClipSpace.y / -2 + 0.5; float sum = 0; - float x, y; + float samples = 0; - // Perform PCF filtering on a 4 x 4 texel neighborhood. - for (y = -1.5; y <= 1.5; y += 1.0) + // Perform basic PCF filtering with distance-based kernel size + for (float y = -kernelSize; y <= kernelSize; y += 1.0) { - for (x = -1.5; x <= 1.5; x += 1.0) + for (float x = -kernelSize; x <= kernelSize; x += 1.0) { sum += ShadowMap.SampleCmpLevelZero(ShadowMapSampler, float3(lightClipSpace.xy + TexOffset(x, y), i), lightClipSpace.z); + samples += 1.0; } } - shadowFactor = lerp(shadowFactor, sum / 16.0, facingFactor * insideLightBounds); + shadowFactor = lerp(shadowFactor, sum / samples, facingFactor * insideLightBounds); } } @@ -138,11 +145,11 @@ float3 DoShadow(float3 worldPos, float3 normal, float3 lighting, float bias) float isSpot = step(0.5f, Light.Type == LT_SPOT); // 1.0 if LT_SPOT, 0.0 otherwise float isOther = 1.0 - (isPoint + isSpot); // 1.0 if neither LT_POINT nor LT_SPOT - float pointFactor = 1.0f - Luma(DoPointLight(worldPos, normal, Light)); - float spotFactor = 1.0f - Luma(DoSpotLight(worldPos, normal, Light)); + float pointFactor = Luma(DoPointLight(worldPos, normal, Light)); + float spotFactor = Luma(DoSpotLight(worldPos, normal, Light)); - float3 pointShadow = lighting * saturate((shadowFactor + SHADOW_INTENSITY) + (pow(pointFactor, 4) * INV_SHADOW_INTENSITY)); - float3 spotShadow = lighting * saturate((shadowFactor + SHADOW_INTENSITY) + (pow(spotFactor, 4) * INV_SHADOW_INTENSITY)); + float3 pointShadow = lighting * (1.0f - (1.0f - shadowFactor) * SHADOW_INTENSITY * pointFactor); + float3 spotShadow = lighting * (1.0f - (1.0f - shadowFactor) * SHADOW_INTENSITY * spotFactor ); return pointShadow * isPoint + spotShadow * isSpot + lighting * isOther; } \ No newline at end of file