feat: 多光源——点光源类型(距离衰减,位置来自 Transform)

- LightComponent 加 Type(Directional/Point)+ radius;点光位置取
  实体 Transform(固有组件首次实际受益)
- LightData shader 契约扩为 4×vec4(color/direction/position/params,
  每灯 64B,未用字段置零);UBO 688→816B
- 光照循环按类型分支:方向光无衰减;点光 L 指向光源 + 平方距离衰减,
  衰减半径外跳过;CSM 阴影只来自第 0 盏方向光
- main.cpp:SunTemple 场景加暖橙火坑光 + 冷蓝填充光(点光);
  KeyLight/FillLight 改 designated initializer
This commit is contained in:
2026-09-23 17:46:25 +08:00
parent d8c481ce48
commit 2c4efc5165
11 changed files with 108 additions and 40 deletions
+2 -2
View File
@@ -20,9 +20,9 @@
namespace Engine {
Application::Application(std::string title, u32 width, u32 height)
Application::Application(const std::string& title, u32 width, u32 height)
{
m_Window = CreateScope<Window>(std::move(title), width, height);
m_Window = CreateScope<Window>(title, width, height);
// 事件通道:GLFW 回调 → 本类 DispatchEvent → 派生类钩子
m_Window->SetEventCallback(
+25 -10
View File
@@ -168,24 +168,39 @@ namespace Engine
ubo.ambientColor = scene.GetSettings().ambientColor;
// ---- 2. 灯光(第一个灯作为阴影光源)----
// ---- 2. 灯光(第一个方向光作为 CSM 阴影光源;点光位置来自 Transform)----
u32 lightCount = 0;
glm::vec3 shadowDir{0.0f, -1.0f, 0.0f}; // 无灯兜底:头顶正射
scene.Each<LightComponent>([&](Entity, LightComponent& light) {
scene.Each<TransformComponent, LightComponent>(
[&](Entity, TransformComponent& t, LightComponent& light) {
if (lightCount >= kMaxLights) return;
glm::vec3 dir = glm::length(light.direction) > 0.0f
? glm::normalize(light.direction)
: glm::vec3(0.0f);
ubo.lights[lightCount].direction = glm::vec4(dir, 0.0f);
ubo.lights[lightCount].color = light.color;
auto& dst = ubo.lights[lightCount];
dst.color = light.color;
dst.params = glm::vec4(
light.type == LightComponent::Type::Point ? 1.0f : 0.0f,
light.radius, 0.0f, 0.0f);
if (lightCount == 0) shadowDir = dir;
if (light.type == LightComponent::Type::Point) {
dst.position = glm::vec4(t.GetPosition(), 1.0f);
dst.direction = glm::vec4(0.0f);
} else {
glm::vec3 dir = glm::length(light.direction) > 0.0f
? glm::normalize(light.direction) : glm::vec3(0.0f);
dst.direction = glm::vec4(dir, 0.0f);
dst.position = glm::vec4(0.0f);
}
// CSM 阴影光源 = 第一个方向光(点光不做级联阴影)
if (lightCount == 0 &&
light.type == LightComponent::Type::Directional) {
shadowDir = glm::length(light.direction) > 0.0f
? glm::normalize(light.direction) : shadowDir;
}
++lightCount;
});
for (u32 i = lightCount; i < kMaxLights; ++i) {
ubo.lights[i].direction = glm::vec4(0.0f);
ubo.lights[i].color = glm::vec4(0.0f);
ubo.lights[i] = {};
}
ComputeCascades(shadowDir);
ubo.cameraPos = glm::vec4(camTransform->GetPosition(), 1.0f);
+4 -4
View File
@@ -61,7 +61,7 @@ namespace Engine {
}
MemoryAllocator::Allocation MemoryAllocator::CreateBuffer(
vk::DeviceSize size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags props)
vk::DeviceSize size, const vk::BufferUsageFlags usage, const vk::MemoryPropertyFlags props) const
{
VkBufferCreateInfo bi{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
bi.size = size;
@@ -92,7 +92,7 @@ namespace Engine {
}
MemoryAllocator::Allocation MemoryAllocator::CreateImage(
const vk::ImageCreateInfo& imageInfo, vk::MemoryPropertyFlags props)
const vk::ImageCreateInfo& imageInfo, const vk::MemoryPropertyFlags props) const
{
VkImageCreateInfo ii = imageInfo; // 同布局,隐式转换
@@ -116,7 +116,7 @@ namespace Engine {
return out;
}
void MemoryAllocator::Destroy(Allocation& alloc)
void MemoryAllocator::Destroy(Allocation& alloc) const
{
if (!alloc.Valid) return;
@@ -131,7 +131,7 @@ namespace Engine {
alloc = {};
}
void MemoryAllocator::Flush(const Allocation& alloc)
void MemoryAllocator::Flush(const Allocation& alloc) const
{
if (!alloc.Valid || !alloc.Handle) return;
// HOST_COHERENT 时 VMA 内部自动跳过