From ed666351912a727ccb646c3b0b239d277c33a232 Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Wed, 7 May 2025 16:08:12 +0200 Subject: [PATCH] Pre bindless --- res/shaders/lib/LightEnv.slang | 17 ++++++- src/Engine/Actor/DirectionalLightActor.cpp | 23 +++++++++- src/Engine/Actor/DirectionalLightActor.h | 2 + src/Engine/Actor/PointLightActor.cpp | 9 +++- src/Engine/Actor/PointLightActor.h | 2 + src/Engine/Component/DirectionalLight.h | 4 +- src/Engine/Component/PointLight.h | 6 +-- src/Engine/Graphics/RenderPass/ShadowPass.cpp | 30 +++---------- src/Engine/Graphics/Window.cpp | 4 +- src/Engine/Math/Transform.cpp | 1 + src/Engine/Math/Transform.h | 1 + src/Engine/Scene/LightEnvironment.cpp | 44 +++++++++++++------ src/Engine/Scene/LightEnvironment.h | 27 +++++++++--- src/Engine/System/LightGather.cpp | 8 +++- 14 files changed, 120 insertions(+), 58 deletions(-) diff --git a/res/shaders/lib/LightEnv.slang b/res/shaders/lib/LightEnv.slang index 7d80d23..86b3874 100644 --- a/res/shaders/lib/LightEnv.slang +++ b/res/shaders/lib/LightEnv.slang @@ -10,11 +10,26 @@ struct DirectionalLight : ILightEnv { float4 color; float4 direction; + float4x4 lightSpaceMatrix; + Texture2D shadowMap; + SamplerState shadowSampler; float3 illuminate(LightingParameter params, B brdf) { float3 dir_WS = -normalize(direction.xyz); - return brdf.evaluate(params.viewDir_WS, dir_WS, color.xyz * color.w); + float3 color = brdf.evaluate(params.viewDir_WS, dir_WS, color.xyz * color.w); + + float4 lightSpacePos = mul(lightSpaceMatrix, float4(params.position_WS, 1)); + float3 projCoords = lightSpacePos.xyz / lightSpacePos.w; + projCoords = projCoords * 0.5 + 0.5; + float closestDepth = shadowMap.Sample(shadowSampler, projCoords.xy).r; + float currentDepth = projCoords.z; + float bias = max(0.05 * (1.0 - dot(brdf.getNormal(), direction.xyz)), 0.005); + float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0; + if (projCoords.z > 1.0) + shadow = 0; + + return shadow * color; } }; diff --git a/src/Engine/Actor/DirectionalLightActor.cpp b/src/Engine/Actor/DirectionalLightActor.cpp index ff7c02b..e5fa4b0 100644 --- a/src/Engine/Actor/DirectionalLightActor.cpp +++ b/src/Engine/Actor/DirectionalLightActor.cpp @@ -5,7 +5,23 @@ using namespace Seele; DirectionalLightActor::DirectionalLightActor(PScene scene) : Actor(scene) { attachComponent(); } DirectionalLightActor::DirectionalLightActor(PScene scene, Vector color, float intensity, Vector direction) : Actor(scene) { - attachComponent(Vector4(color, intensity), Vector4(glm::normalize(direction), 0)); + attachComponent(Vector4(color, intensity)); + Vector lightDirection = Vector(direction); + float dot = glm::dot(lightDirection, Math::Transform::FORWARD); + Quaternion rotation = Quaternion(1, 0, 0, 0); + // Handle the edge cases first + if (glm::epsilonEqual(dot, 1.0f, 0.00001f)) { + // Vectors are the same, no rotation + } else if (glm::epsilonEqual(dot, -1.0f, 0.00001f)) { + // Vectors are opposite need 180-degree rotation around any perpendicular axis + rotation = glm::angleAxis(glm::pi(), Vector(0, 1, 0)); + } else { + // Normal case + Vector axis = glm::normalize(glm::cross(lightDirection, Math::Transform::FORWARD)); + float angle = std::acos(dot); // angle between vectors + rotation = glm::angleAxis(angle, axis); + } + attachComponent(Math::Transform(Vector(0, 0, 0), rotation)); } DirectionalLightActor::~DirectionalLightActor() {} @@ -16,4 +32,7 @@ Component::DirectionalLight& DirectionalLightActor::getDirectionalLightComponent const Component::DirectionalLight& DirectionalLightActor::getDirectionalLightComponent() const { return accessComponent(); -} \ No newline at end of file +} +Component::Transform& DirectionalLightActor::getTransformComponent() { return accessComponent(); } + +const Component::Transform& DirectionalLightActor::getTransformComponent() const { return accessComponent(); } \ No newline at end of file diff --git a/src/Engine/Actor/DirectionalLightActor.h b/src/Engine/Actor/DirectionalLightActor.h index c3b52dc..fe48709 100644 --- a/src/Engine/Actor/DirectionalLightActor.h +++ b/src/Engine/Actor/DirectionalLightActor.h @@ -10,6 +10,8 @@ class DirectionalLightActor : public Actor { virtual ~DirectionalLightActor(); Component::DirectionalLight& getDirectionalLightComponent(); const Component::DirectionalLight& getDirectionalLightComponent() const; + Component::Transform& getTransformComponent(); + const Component::Transform& getTransformComponent() const; private: }; diff --git a/src/Engine/Actor/PointLightActor.cpp b/src/Engine/Actor/PointLightActor.cpp index f286bf7..3ef1d9c 100644 --- a/src/Engine/Actor/PointLightActor.cpp +++ b/src/Engine/Actor/PointLightActor.cpp @@ -5,11 +5,16 @@ using namespace Seele; PointLightActor::PointLightActor(PScene scene) : Actor(scene) { attachComponent(); } PointLightActor::PointLightActor(PScene scene, Vector position, float intensity, Vector color, float attenuation) : Actor(scene) { - attachComponent(Vector4(position, intensity), Vector4(color, attenuation)); + attachComponent(color, intensity, attenuation); + attachComponent(Math::Transform(position)); } PointLightActor::~PointLightActor() {} Component::PointLight& PointLightActor::getPointLightComponent() { return accessComponent(); } -const Component::PointLight& PointLightActor::getPointLightComponent() const { return accessComponent(); } \ No newline at end of file +const Component::PointLight& PointLightActor::getPointLightComponent() const { return accessComponent(); } + +Component::Transform& PointLightActor::getTransformComponent() { return accessComponent(); } + +const Component::Transform& PointLightActor::getTransformComponent() const { return accessComponent(); } \ No newline at end of file diff --git a/src/Engine/Actor/PointLightActor.h b/src/Engine/Actor/PointLightActor.h index c1b756b..8b76058 100644 --- a/src/Engine/Actor/PointLightActor.h +++ b/src/Engine/Actor/PointLightActor.h @@ -10,6 +10,8 @@ class PointLightActor : public Actor { virtual ~PointLightActor(); Component::PointLight& getPointLightComponent(); const Component::PointLight& getPointLightComponent() const; + Component::Transform& getTransformComponent(); + const Component::Transform& getTransformComponent() const; private: }; diff --git a/src/Engine/Component/DirectionalLight.h b/src/Engine/Component/DirectionalLight.h index a934a87..ce00223 100644 --- a/src/Engine/Component/DirectionalLight.h +++ b/src/Engine/Component/DirectionalLight.h @@ -3,8 +3,8 @@ namespace Seele { namespace Component { struct DirectionalLight { - Vector4 colorIntensity; - Vector4 direction; + Vector color; + float intensity; }; } // namespace Component } // namespace Seele diff --git a/src/Engine/Component/PointLight.h b/src/Engine/Component/PointLight.h index 4862a98..a431a57 100644 --- a/src/Engine/Component/PointLight.h +++ b/src/Engine/Component/PointLight.h @@ -4,9 +4,9 @@ namespace Seele { namespace Component { struct PointLight { - // give the lights a radius so that they are not actual points - Vector4 positionWS; - Vector4 colorRange; + Vector color; + float intensity; + float attenuation; }; } // namespace Component } // namespace Seele diff --git a/src/Engine/Graphics/RenderPass/ShadowPass.cpp b/src/Engine/Graphics/RenderPass/ShadowPass.cpp index 2faa13d..1974e3b 100644 --- a/src/Engine/Graphics/RenderPass/ShadowPass.cpp +++ b/src/Engine/Graphics/RenderPass/ShadowPass.cpp @@ -39,7 +39,7 @@ ShadowPass::ShadowPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graph ShadowPass::~ShadowPass() {} -void ShadowPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {} +void ShadowPass::beginFrame(const Component::Camera&, const Component::Transform&) {} void ShadowPass::render() { graphics->beginDebugRegion("ShadowPass"); @@ -81,31 +81,13 @@ void ShadowPass::render() { "Shadow"); graphics->beginRenderPass(renderPass); auto light = scene->getLightEnvironment()->getDirectionalLight(shadowIndex); - Vector lightDirection = Vector(light.direction); - Vector lightPosition = -light.direction * 100.0f; - float dot = glm::dot(lightDirection, Math::Transform::FORWARD); - Quaternion rotation = Quaternion(1, 0, 0, 0); - // Handle the edge cases first - if (glm::epsilonEqual(dot, 1.0f, 0.00001f)) { - // Vectors are the same, no rotation - } else if (glm::epsilonEqual(dot, -1.0f, 0.00001f)) { - // Vectors are opposite need 180-degree rotation around any perpendicular axis - rotation = glm::angleAxis(glm::pi(), Vector(0, 1, 0)); - } else { - // Normal case - Vector axis = glm::normalize(glm::cross(lightDirection, Math::Transform::FORWARD)); - float angle = std::acos(dot); // angle between vectors - rotation = glm::angleAxis(angle, axis); - } - Component::Transform lightTransform = Component::Transform{ - .transform = Math::Transform(lightPosition, rotation), - }; + Component::Camera lightCamera = Component::Camera{ - .nearPlane = -1000.f, + .nearPlane = 0.f, .farPlane = 1000.0f, }; - Gfx::PDescriptorSet viewParamsSet = createViewParamsSet(lightCamera, lightTransform); + Gfx::PDescriptorSet viewParamsSet = createViewParamsSet(lightCamera, scene->getLightEnvironment()->getDirectionalTransform(shadowIndex)); for (VertexData* vertexData : VertexData::getList()) { permutation.setVertexData(vertexData->getTypeName()); Gfx::PermutationId id(permutation); @@ -123,7 +105,7 @@ void ShadowPass::render() { .pipelineLayout = collection->pipelineLayout, .rasterizationState = { - .cullMode = Gfx::SE_CULL_MODE_NONE, + .cullMode = Gfx::SE_CULL_MODE_FRONT_BIT, }, .colorBlend = { @@ -140,7 +122,7 @@ void ShadowPass::render() { .pipelineLayout = collection->pipelineLayout, .rasterizationState = { - .cullMode = Gfx::SE_CULL_MODE_NONE, + .cullMode = Gfx::SE_CULL_MODE_FRONT_BIT, }, .colorBlend = { diff --git a/src/Engine/Graphics/Window.cpp b/src/Engine/Graphics/Window.cpp index 43c81bb..4d77643 100644 --- a/src/Engine/Graphics/Window.cpp +++ b/src/Engine/Graphics/Window.cpp @@ -21,11 +21,11 @@ Viewport::Viewport(PWindow owner, const ViewportCreateInfo& viewportInfo) Viewport::~Viewport() {} Matrix4 Viewport::getProjectionMatrix(float nearPlane, float farPlane) const { + Matrix4 correctionMatrix = Matrix4(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1 / 2.f, 0, 0, 0, 1 / 2.f, 1); if (fieldOfView > 0.0f) { Matrix4 projectionMatrix = glm::perspective(fieldOfView, sizeX / static_cast(sizeY), nearPlane, farPlane); - Matrix4 correctionMatrix = Matrix4(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1 / 2.f, 0, 0, 0, 1 / 2.f, 1); return correctionMatrix * projectionMatrix; } else { - return glm::ortho(orthoLeft, orthoRight, orthoTop, orthoBottom, nearPlane, farPlane); + return correctionMatrix * glm::ortho(orthoLeft, orthoRight, orthoTop, orthoBottom, farPlane, nearPlane); } } \ No newline at end of file diff --git a/src/Engine/Math/Transform.cpp b/src/Engine/Math/Transform.cpp index 89dead3..a886e15 100644 --- a/src/Engine/Math/Transform.cpp +++ b/src/Engine/Math/Transform.cpp @@ -24,6 +24,7 @@ Transform::Transform(Vector position, Quaternion rotation, Vector scale) : position(Vector4(position, 0)), rotation(rotation), scale(Vector4(scale, 0)) {} Transform::Transform(Quaternion rotation, Vector scale) : position(Vector4(0, 0, 0, 0)), rotation(rotation), scale(Vector4(scale, 0)) {} Transform::~Transform() {} + Matrix4 Transform::toMatrix() const { // TODO: actual calculations, SIMD Matrix4 result = Matrix4(1); diff --git a/src/Engine/Math/Transform.h b/src/Engine/Math/Transform.h index 10dc73d..bf5b1c5 100644 --- a/src/Engine/Math/Transform.h +++ b/src/Engine/Math/Transform.h @@ -16,6 +16,7 @@ class Transform { Transform(Quaternion rotation, Vector scale); ~Transform(); Matrix4 toMatrix() const; + void fromMatrix(Matrix4 mat); Vector transformPosition(const Vector& v) const; Vector getPosition() const; diff --git a/src/Engine/Scene/LightEnvironment.cpp b/src/Engine/Scene/LightEnvironment.cpp index c6adf95..95cfadb 100644 --- a/src/Engine/Scene/LightEnvironment.cpp +++ b/src/Engine/Scene/LightEnvironment.cpp @@ -55,12 +55,41 @@ void LightEnvironment::reset() { layout->reset(); set = layout->allocateDescriptorSet(); dirs.clear(); + directionalTransforms.clear(); points.clear(); } -void LightEnvironment::addDirectionalLight(Component::DirectionalLight dirLight) { dirs.add(dirLight); } +void LightEnvironment::addDirectionalLight(const Component::DirectionalLight& dirLight, const Component::Transform& transform) { + dirs.add(ShaderDirectionalLight{ + .color = Vector4(dirLight.color, dirLight.intensity), + .direction = Vector4(transform.getForward(), 0), + .lightSpaceMatrix = transform.toMatrix(), + }); + directionalTransforms.add(transform); + if (shadowMaps.size() < dirs.size()) { + shadowMaps.add(graphics->createTexture2D(TextureCreateInfo{ + .format = Gfx::SE_FORMAT_D32_SFLOAT, + .width = 2048, + .height = 2048, + .elements = (uint32)dirs.size(), + .usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_SAMPLED_BIT, + .name = "ShadowMap", + })); + shadowSamplers.add(graphics->createSampler(SamplerCreateInfo{ + .addressModeU = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, + .addressModeV = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, + .addressModeW = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, + .name = "ShadowSampler", + })); + } +} -void LightEnvironment::addPointLight(Component::PointLight pointLight) { points.add(pointLight); } +void LightEnvironment::addPointLight(const Component::PointLight& pointLight, const Component::Transform& transform) { + points.add(ShaderPointLight{ + .position_WS = Vector4(transform.getPosition(), pointLight.intensity), + .colorRange = Vector4(pointLight.color, pointLight.attenuation), + }); +} void LightEnvironment::commit() { directionalLights->rotateBuffer(sizeof(Component::DirectionalLight) * dirs.size()); @@ -84,17 +113,6 @@ void LightEnvironment::commit() { set->updateTexture("irradianceMap", 0, environment->getIrradianceMap()); set->updateSampler("irradianceSampler", 0, environmentSampler); set->writeChanges(); - - while (shadowMapArray.size() < dirs.size()) { - shadowMapArray.add(graphics->createTexture2D(TextureCreateInfo{ - .format = Gfx::SE_FORMAT_D32_SFLOAT, - .width = 2048, - .height = 2048, - .elements = (uint32)dirs.size(), - .usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_SAMPLED_BIT, - .name = "ShadowMap", - })); - } } const Gfx::PDescriptorLayout LightEnvironment::getDescriptorLayout() const { return layout; } diff --git a/src/Engine/Scene/LightEnvironment.h b/src/Engine/Scene/LightEnvironment.h index 0a57121..f1d45d1 100644 --- a/src/Engine/Scene/LightEnvironment.h +++ b/src/Engine/Scene/LightEnvironment.h @@ -1,6 +1,7 @@ #pragma once #include "Component/DirectionalLight.h" #include "Component/PointLight.h" +#include "Component/Transform.h" #include "Graphics/Buffer.h" #include "Graphics/Descriptor.h" @@ -8,25 +9,37 @@ namespace Seele { DECLARE_REF(EnvironmentMapAsset) class LightEnvironment { public: + struct ShaderDirectionalLight { + Vector4 color; + Vector4 direction; + Matrix4 lightSpaceMatrix; + }; + struct ShaderPointLight { + Vector4 position_WS; + Vector4 colorRange; + }; LightEnvironment(Gfx::PGraphics graphics); ~LightEnvironment(); void reset(); - void addDirectionalLight(Component::DirectionalLight dirLight); - void addPointLight(Component::PointLight pointLight); + void addDirectionalLight(const Component::DirectionalLight& dirLight, const Component::Transform& transform); + void addPointLight(const Component::PointLight& pointLight, const Component::Transform& transform); void commit(); const Gfx::PDescriptorLayout getDescriptorLayout() const; - const Component::DirectionalLight& getDirectionalLight(uint32 lightIndex) const { return dirs[lightIndex]; } + const ShaderDirectionalLight& getDirectionalLight(uint32 lightIndex) const { return dirs[lightIndex]; } + const Component::Transform& getDirectionalTransform(uint32 lightIndex) const { return directionalTransforms[lightIndex]; } Gfx::PDescriptorSet getDescriptorSet(); PEnvironmentMapAsset getEnvironmentMap() { return environment; } uint64 getNumDirectionalLights() const { return dirs.size(); } - const Array& getShadowMaps() const { return shadowMapArray; } + const Array& getShadowMaps() const { return shadowMaps; } private: Gfx::OShaderBuffer directionalLights; - Array shadowMapArray; + Array shadowMaps; + Array shadowSamplers; Gfx::OShaderBuffer pointLights; - Array dirs; - Array points; + Array dirs; + Array directionalTransforms; + Array points; PEnvironmentMapAsset environment; Gfx::OSampler environmentSampler; Gfx::ODescriptorLayout layout; diff --git a/src/Engine/System/LightGather.cpp b/src/Engine/System/LightGather.cpp index c6fe2ed..5d3326b 100644 --- a/src/Engine/System/LightGather.cpp +++ b/src/Engine/System/LightGather.cpp @@ -9,6 +9,10 @@ LightGather::~LightGather() {} void LightGather::update() { lightEnv->reset(); - scene->view([this](Component::PointLight& pointLight) { lightEnv->addPointLight(pointLight); }); - scene->view([this](Component::DirectionalLight& dirLight) { lightEnv->addDirectionalLight(dirLight); }); + scene->view( + [this](Component::PointLight& pointLight, Component::Transform& transform) { lightEnv->addPointLight(pointLight, transform); }); + scene->view( + [this](Component::DirectionalLight& dirLight, Component::Transform& transform) { + lightEnv->addDirectionalLight(dirLight, transform); + }); }