From 61dcb0430ab595b12287d22f20f7caffa9af153b Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Wed, 25 Feb 2026 07:13:54 +0100 Subject: [PATCH] Fixed shadow pass and physics system a little bit --- src/Engine/Graphics/RenderPass/ShadowPass.cpp | 15 +++-- src/Engine/Physics/PhysicsSystem.cpp | 56 ++++++++++++------- 2 files changed, 46 insertions(+), 25 deletions(-) diff --git a/src/Engine/Graphics/RenderPass/ShadowPass.cpp b/src/Engine/Graphics/RenderPass/ShadowPass.cpp index b7c3430..d819bdf 100644 --- a/src/Engine/Graphics/RenderPass/ShadowPass.cpp +++ b/src/Engine/Graphics/RenderPass/ShadowPass.cpp @@ -72,9 +72,14 @@ void ShadowPass::beginFrame(const Component::Camera& camera, const Component::Tr updateViewParameters(camera, transform); Matrix4 invCam = viewParams.inverseViewProjectionMatrix; float lastSplitDist = 0.0; + constexpr float cascadeOverlap = 0.1f; // overlap factor to prevent gaps at cascade boundaries for (uint32 i = 0; i < NUM_CASCADES; ++i) { float splitDist = cascadeSplits[i]; + // Extend each cascade's frustum slice slightly into adjacent cascades + float overlapNear = (i > 0) ? lastSplitDist - cascadeOverlap * (lastSplitDist - (i > 1 ? cascadeSplits[i - 2] : 0.0f)) : 0.0f; + float overlapFar = (i < NUM_CASCADES - 1) ? splitDist + cascadeOverlap * (cascadeSplits[i + 1] - splitDist) : splitDist; + Array frustumCorners = { Vector(-1.0f, 1.0f, 0.0f), Vector(1.0f, 1.0f, 0.0f), Vector(1.0f, -1.0f, 0.0f), Vector(-1.0f, -1.0f, 0.0f), Vector(-1.0f, 1.0f, 1.0f), Vector(1.0f, 1.0f, 1.0f), Vector(1.0f, -1.0f, 1.0f), Vector(-1.0f, -1.0f, 1.0f), @@ -86,8 +91,8 @@ void ShadowPass::beginFrame(const Component::Camera& camera, const Component::Tr } for (uint32 j = 0; j < 4; j++) { Vector dist = frustumCorners[j + 4] - frustumCorners[j]; - frustumCorners[j + 4] = frustumCorners[j] + (dist * splitDist); - frustumCorners[j] = frustumCorners[j] + (dist * lastSplitDist); + frustumCorners[j + 4] = frustumCorners[j] + (dist * overlapFar); + frustumCorners[j] = frustumCorners[j] + (dist * overlapNear); } Vector frustumCenter = Vector(0); @@ -108,10 +113,10 @@ void ShadowPass::beginFrame(const Component::Camera& camera, const Component::Tr for (uint32 s = 0; s < scene->getLightEnvironment()->getNumDirectionalLights(); ++s) { Vector lightDir = glm::normalize(scene->getLightEnvironment()->getDirectionalLight(s).direction); - Vector cameraPos = frustumCenter - lightDir * -minExtents.z; + Vector cameraPos = frustumCenter - lightDir * (100.0f * -minExtents.z); Matrix4 viewMatrix = glm::lookAt(cameraPos, frustumCenter, Vector(0, 1, 0)); Matrix4 projectionMatrix = - orthographicProjection(minExtents.x, maxExtents.x, minExtents.y, maxExtents.y, 0.0f, maxExtents.z - minExtents.z); + orthographicProjection(minExtents.x, maxExtents.x, minExtents.y, maxExtents.y, 0.0f, maxExtents.z - (100.0f * minExtents.z)); Matrix4 viewProjectionMatrix = projectionMatrix * viewMatrix; viewParams = { .viewMatrix = viewMatrix, @@ -193,7 +198,7 @@ void ShadowPass::render() { .pipelineLayout = collection->pipelineLayout, .rasterizationState = { - .cullMode = Gfx::SE_CULL_MODE_NONE, + .cullMode = Gfx::SE_CULL_MODE_FRONT_BIT, .depthBiasEnable = true, .depthBiasConstantFactor = depthBiasConstant, .depthBiasSlopeFactor = depthBiasSlope, diff --git a/src/Engine/Physics/PhysicsSystem.cpp b/src/Engine/Physics/PhysicsSystem.cpp index 137fbdf..0bef6f7 100644 --- a/src/Engine/Physics/PhysicsSystem.cpp +++ b/src/Engine/Physics/PhysicsSystem.cpp @@ -1,6 +1,5 @@ #include "PhysicsSystem.h" #include -#include using namespace Seele; @@ -466,27 +465,44 @@ void PhysicsSystem::computeBVector(const Array& contacts, Array& } } -void PhysicsSystem::solveQP(const Array>& CI, const Array& ci0, Array& sol) const { - static std::mt19937_64 generator; - static std::uniform_real_distribution dist(0.01f, 0.1f); - sol.resize(CI.size()); - bool solved = false; - while (!solved) { - for (size_t i = 0; i < sol.size(); ++i) { - sol[i] = dist(generator); - } - solved = true; - for (size_t i = 0; i < sol.size(); ++i) { - float res = 0; - for (size_t j = 0; j < sol.size(); ++j) { - res += CI[i][j] * sol[j] + ci0[i]; +void PhysicsSystem::solveQP(const Array>& A, const Array& b, Array& f) const { + // Solves the LCP: find f >= 0 such that Af + b >= 0 and f^T(Af + b) = 0 + // using Projected Gauss-Seidel (PGS) iteration + const size_t n = A.size(); + f.resize(n); + + for (size_t i = 0; i < n; ++i) { + f[i] = 0.0f; + } + + constexpr size_t maxIterations = 200; + constexpr float tolerance = 1e-6f; + + for (size_t iter = 0; iter < maxIterations; ++iter) { + float maxDelta = 0.0f; + + for (size_t i = 0; i < n; ++i) { + float sigma = b[i]; + for (size_t j = 0; j < n; ++j) { + if (j != i) { + sigma += A[i][j] * f[j]; + } } - if (res < 0) { - solved = false; - std::cout << "failed to solve QP" << std::endl; - continue; + + float diagonal = A[i][i]; + float newF; + if (std::abs(diagonal) > 1e-10f) { + newF = std::max(0.0f, -sigma / diagonal); + } else { + newF = 0.0f; } + + maxDelta = std::max(maxDelta, std::abs(newF - f[i])); + f[i] = newF; + } + + if (maxDelta < tolerance) { + return; } - return; } }