Pre bindless
This commit is contained in:
@@ -10,11 +10,26 @@ struct DirectionalLight : ILightEnv
|
||||
{
|
||||
float4 color;
|
||||
float4 direction;
|
||||
float4x4 lightSpaceMatrix;
|
||||
Texture2D shadowMap;
|
||||
SamplerState shadowSampler;
|
||||
|
||||
float3 illuminate<B:IBRDF>(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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -5,7 +5,23 @@ using namespace Seele;
|
||||
DirectionalLightActor::DirectionalLightActor(PScene scene) : Actor(scene) { attachComponent<Component::DirectionalLight>(); }
|
||||
|
||||
DirectionalLightActor::DirectionalLightActor(PScene scene, Vector color, float intensity, Vector direction) : Actor(scene) {
|
||||
attachComponent<Component::DirectionalLight>(Vector4(color, intensity), Vector4(glm::normalize(direction), 0));
|
||||
attachComponent<Component::DirectionalLight>(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<float>(), 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<Component::Transform>(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<Component::DirectionalLight>();
|
||||
}
|
||||
}
|
||||
Component::Transform& DirectionalLightActor::getTransformComponent() { return accessComponent<Component::Transform>(); }
|
||||
|
||||
const Component::Transform& DirectionalLightActor::getTransformComponent() const { return accessComponent<Component::Transform>(); }
|
||||
@@ -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:
|
||||
};
|
||||
|
||||
@@ -5,11 +5,16 @@ using namespace Seele;
|
||||
PointLightActor::PointLightActor(PScene scene) : Actor(scene) { attachComponent<Component::PointLight>(); }
|
||||
|
||||
PointLightActor::PointLightActor(PScene scene, Vector position, float intensity, Vector color, float attenuation) : Actor(scene) {
|
||||
attachComponent<Component::PointLight>(Vector4(position, intensity), Vector4(color, attenuation));
|
||||
attachComponent<Component::PointLight>(color, intensity, attenuation);
|
||||
attachComponent<Component::Transform>(Math::Transform(position));
|
||||
}
|
||||
|
||||
PointLightActor::~PointLightActor() {}
|
||||
|
||||
Component::PointLight& PointLightActor::getPointLightComponent() { return accessComponent<Component::PointLight>(); }
|
||||
|
||||
const Component::PointLight& PointLightActor::getPointLightComponent() const { return accessComponent<Component::PointLight>(); }
|
||||
const Component::PointLight& PointLightActor::getPointLightComponent() const { return accessComponent<Component::PointLight>(); }
|
||||
|
||||
Component::Transform& PointLightActor::getTransformComponent() { return accessComponent<Component::Transform>(); }
|
||||
|
||||
const Component::Transform& PointLightActor::getTransformComponent() const { return accessComponent<Component::Transform>(); }
|
||||
@@ -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:
|
||||
};
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
namespace Seele {
|
||||
namespace Component {
|
||||
struct DirectionalLight {
|
||||
Vector4 colorIntensity;
|
||||
Vector4 direction;
|
||||
Vector color;
|
||||
float intensity;
|
||||
};
|
||||
} // namespace Component
|
||||
} // namespace Seele
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<float>(), 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 =
|
||||
{
|
||||
|
||||
@@ -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<float>(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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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<Gfx::OTexture2D>& getShadowMaps() const { return shadowMapArray; }
|
||||
const Array<Gfx::OTexture2D>& getShadowMaps() const { return shadowMaps; }
|
||||
|
||||
private:
|
||||
Gfx::OShaderBuffer directionalLights;
|
||||
Array<Gfx::OTexture2D> shadowMapArray;
|
||||
Array<Gfx::OTexture2D> shadowMaps;
|
||||
Array<Gfx::OSampler> shadowSamplers;
|
||||
Gfx::OShaderBuffer pointLights;
|
||||
Array<Component::DirectionalLight> dirs;
|
||||
Array<Component::PointLight> points;
|
||||
Array<ShaderDirectionalLight> dirs;
|
||||
Array<Component::Transform> directionalTransforms;
|
||||
Array<ShaderPointLight> points;
|
||||
PEnvironmentMapAsset environment;
|
||||
Gfx::OSampler environmentSampler;
|
||||
Gfx::ODescriptorLayout layout;
|
||||
|
||||
@@ -9,6 +9,10 @@ LightGather::~LightGather() {}
|
||||
|
||||
void LightGather::update() {
|
||||
lightEnv->reset();
|
||||
scene->view<Component::PointLight>([this](Component::PointLight& pointLight) { lightEnv->addPointLight(pointLight); });
|
||||
scene->view<Component::DirectionalLight>([this](Component::DirectionalLight& dirLight) { lightEnv->addDirectionalLight(dirLight); });
|
||||
scene->view<Component::PointLight, Component::Transform>(
|
||||
[this](Component::PointLight& pointLight, Component::Transform& transform) { lightEnv->addPointLight(pointLight, transform); });
|
||||
scene->view<Component::DirectionalLight, Component::Transform>(
|
||||
[this](Component::DirectionalLight& dirLight, Component::Transform& transform) {
|
||||
lightEnv->addDirectionalLight(dirLight, transform);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user