Fixed shadow pass and physics system a little bit
This commit is contained in:
@@ -72,9 +72,14 @@ void ShadowPass::beginFrame(const Component::Camera& camera, const Component::Tr
|
|||||||
updateViewParameters(camera, transform);
|
updateViewParameters(camera, transform);
|
||||||
Matrix4 invCam = viewParams.inverseViewProjectionMatrix;
|
Matrix4 invCam = viewParams.inverseViewProjectionMatrix;
|
||||||
float lastSplitDist = 0.0;
|
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) {
|
for (uint32 i = 0; i < NUM_CASCADES; ++i) {
|
||||||
float splitDist = cascadeSplits[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<Vector> frustumCorners = {
|
Array<Vector> 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, 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),
|
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++) {
|
for (uint32 j = 0; j < 4; j++) {
|
||||||
Vector dist = frustumCorners[j + 4] - frustumCorners[j];
|
Vector dist = frustumCorners[j + 4] - frustumCorners[j];
|
||||||
frustumCorners[j + 4] = frustumCorners[j] + (dist * splitDist);
|
frustumCorners[j + 4] = frustumCorners[j] + (dist * overlapFar);
|
||||||
frustumCorners[j] = frustumCorners[j] + (dist * lastSplitDist);
|
frustumCorners[j] = frustumCorners[j] + (dist * overlapNear);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector frustumCenter = Vector(0);
|
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) {
|
for (uint32 s = 0; s < scene->getLightEnvironment()->getNumDirectionalLights(); ++s) {
|
||||||
Vector lightDir = glm::normalize(scene->getLightEnvironment()->getDirectionalLight(s).direction);
|
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 viewMatrix = glm::lookAt(cameraPos, frustumCenter, Vector(0, 1, 0));
|
||||||
Matrix4 projectionMatrix =
|
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;
|
Matrix4 viewProjectionMatrix = projectionMatrix * viewMatrix;
|
||||||
viewParams = {
|
viewParams = {
|
||||||
.viewMatrix = viewMatrix,
|
.viewMatrix = viewMatrix,
|
||||||
@@ -193,7 +198,7 @@ void ShadowPass::render() {
|
|||||||
.pipelineLayout = collection->pipelineLayout,
|
.pipelineLayout = collection->pipelineLayout,
|
||||||
.rasterizationState =
|
.rasterizationState =
|
||||||
{
|
{
|
||||||
.cullMode = Gfx::SE_CULL_MODE_NONE,
|
.cullMode = Gfx::SE_CULL_MODE_FRONT_BIT,
|
||||||
.depthBiasEnable = true,
|
.depthBiasEnable = true,
|
||||||
.depthBiasConstantFactor = depthBiasConstant,
|
.depthBiasConstantFactor = depthBiasConstant,
|
||||||
.depthBiasSlopeFactor = depthBiasSlope,
|
.depthBiasSlopeFactor = depthBiasSlope,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#include "PhysicsSystem.h"
|
#include "PhysicsSystem.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <random>
|
|
||||||
|
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
@@ -466,27 +465,44 @@ void PhysicsSystem::computeBVector(const Array<Contact>& contacts, Array<float>&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsSystem::solveQP(const Array<Array<float>>& CI, const Array<float>& ci0, Array<float>& sol) const {
|
void PhysicsSystem::solveQP(const Array<Array<float>>& A, const Array<float>& b, Array<float>& f) const {
|
||||||
static std::mt19937_64 generator;
|
// Solves the LCP: find f >= 0 such that Af + b >= 0 and f^T(Af + b) = 0
|
||||||
static std::uniform_real_distribution<float> dist(0.01f, 0.1f);
|
// using Projected Gauss-Seidel (PGS) iteration
|
||||||
sol.resize(CI.size());
|
const size_t n = A.size();
|
||||||
bool solved = false;
|
f.resize(n);
|
||||||
while (!solved) {
|
|
||||||
for (size_t i = 0; i < sol.size(); ++i) {
|
for (size_t i = 0; i < n; ++i) {
|
||||||
sol[i] = dist(generator);
|
f[i] = 0.0f;
|
||||||
}
|
}
|
||||||
solved = true;
|
|
||||||
for (size_t i = 0; i < sol.size(); ++i) {
|
constexpr size_t maxIterations = 200;
|
||||||
float res = 0;
|
constexpr float tolerance = 1e-6f;
|
||||||
for (size_t j = 0; j < sol.size(); ++j) {
|
|
||||||
res += CI[i][j] * sol[j] + ci0[i];
|
for (size_t iter = 0; iter < maxIterations; ++iter) {
|
||||||
}
|
float maxDelta = 0.0f;
|
||||||
if (res < 0) {
|
|
||||||
solved = false;
|
for (size_t i = 0; i < n; ++i) {
|
||||||
std::cout << "failed to solve QP" << std::endl;
|
float sigma = b[i];
|
||||||
continue;
|
for (size_t j = 0; j < n; ++j) {
|
||||||
|
if (j != i) {
|
||||||
|
sigma += A[i][j] * f[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user