project-aster/samples/03_model_render/light_manager.h

115 lines
3.3 KiB
C++

// =============================================
// Aster: light_manager.h
// Copyright (c) 2020-2025 Anish Bhobe
// =============================================
#pragma once
#include "aster/aster.h"
// TODO: Separate files so you only import handles.
#include "aster/core/buffer.h"
#include "aster/systems/resource.h"
#include <EASTL/vector.h>
namespace systems
{
class ResourceManager;
class CommitManager;
} // namespace systems
struct DirectionalLight
{
vec3 m_Direction;
u32 m_UnusedPadding0_;
u32 m_Color_; // LSB is used for flags. (R G B Flags)
f32 m_Intensity;
};
struct PointLight
{
vec3 m_Position;
f32 m_Range;
u32 m_Color_; // LSB is used for flags. (R G B Flags)
f32 m_Intensity;
};
struct LightHandle
{
u8 m_Type;
u8 m_Generation;
u16 m_Index;
};
struct Light
{
union {
vec3 um_Position;
vec3 um_Direction;
};
f32 m_Range; // < 0.0 for invalid
u32 m_Color_; // LSB is used for flags. (R G B Flags)
f32 m_Intensity;
constexpr static u32 MAX_GEN = 0x40;
constexpr static u32 GEN_MASK = MAX_GEN - 1;
constexpr static u32 TYPE_MASK = 0xC0;
constexpr static u32 TYPE_INVALID = 0x0;
constexpr static u32 TYPE_DIRECTIONAL = 1 << 6;
constexpr static u32 TYPE_POINT = 2 << 6;
constexpr static u32 TYPE_SPOT = 3 << 6; // Currently Unused
constexpr static u32 COLOR_MASK = ~(GEN_MASK | TYPE_MASK);
};
struct LightManager
{
constexpr static u16 MAX_LIGHTS = MaxValue<u16>;
struct LightMetaInfo
{
// The number of directional lights is relatively low (1 - 2) and will almost never change in a scene.
// We can use that with Offset = 0, and point light at further offsets.
// This way we don't need to move point lights often.
systems::ResId<Buffer> m_LightBuffer; // 04 04
u16 m_PointLightMaxCount; // 02 06
u16 m_PointLightOffset; // 02 08
u16 m_DirectionalLightMaxCount; // 02 10
u16 m_UnusedPadding0 = 0; // 02 12
};
systems::ResourceManager *m_ResourceManager;
systems::CommitManager *m_CommitManager;
eastl::vector<Light> m_Lights;
// We don't need a Directional Light free list. We will just brute force iterate.
u16 m_DirectionalLightCount;
// TODO: A point light free list. We will brute force until we have a lot (100+) of point lights.
u16 m_PointLightCount;
LightMetaInfo m_MetaInfo;
// Using lower bit for flags. Use CAPACITY_MASK for value.
u16 m_GpuBufferCapacity_;
// Using lower bit. Capacity can be directly a multiple of 2
// Thus, range is up to MaxValue<u16>
constexpr static u16 UPDATE_REQUIRED_BIT = 1;
constexpr static u16 CAPACITY_MASK = Cast<u16>(~UPDATE_REQUIRED_BIT);
LightHandle AddDirectional(const vec3 &direction, const vec3 &color, f32 intensity);
LightHandle AddPoint(const vec3 &position, const vec3 &color, f32 radius, f32 intensity);
void Update();
void RemoveLight(LightHandle handle);
~LightManager() = default;
LightManager(systems::ResourceManager *resourceManager, systems::CommitManager *commitManager);
LightManager(LightManager &&other) noexcept;
LightManager &operator=(LightManager &&other) noexcept;
DISALLOW_COPY_AND_ASSIGN(LightManager);
};