Files
HelloVulkan/App/main.cpp
T
atdunbg 3907868417 fix: 阴影不可见的真正根因——深度重映射矩阵公式错误
诊断方法:日志打印 lightVP/lightProj/lightView 矩阵分解定位。
修复前 lightVP 在原点处 z=-14.70(应 ∈[-1,1])——深度全部越界被裁。

根因:remap 公式把偏移量 0.5 错加进了 z 缩放系数:
  错:M[2][2] = M[2][2]*0.5 + 0.5   (0.5 混入 z 系数)
  对:M[2][2] *= 0.5                (z' = 0.5z + 0.5w,偏移属于 w 列)
      M[3][2] = M[3][2]*0.5 + 0.5
正交投影 w=1,错误的 0.5*z 项使深度随距离线性发散,shadow map
内所有深度越界,采样对比永不成立。透视投影同错(被 w 除法稀释
成近似常数偏移,此前一直"看起来正常")。修复 Camera + lightProj。

同批修复:
- 深度 bias 1.25 → 0.0025/0.003(NDC 空间,1.25 会饱和全部深度)
- 光源位置 lightDir*30 → -lightDir*30(原方向反了:从地下往上照)
- lookAt 垂直光 up 退化(叉积为零 → NaN 矩阵)
- 地面改纯色纹理(Texture::CreateSolidColor,1x1 程序化生成)

矩阵诊断验证:lightVP 原点深度 -14.70 → 0.30,物体(0.30) < 地面(0.32)
遮挡关系正确。validation 零错误零警告。
2026-09-22 15:35:52 +08:00

143 lines
4.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// Created by atdunbg on 2026/9/20.
//
// SandboxApp:第一个基于 Application 框架的程序。
//
// main 的全部职责:定义一个 Application 派生类并运行它。
// 窗口、渲染器、事件泵、帧计时、场景容器全部由框架管理;
// 这里只写"程序逻辑":创建实体、逐帧更新组件、事件响应。
//
#include <Engine/Core/Application.h>
#include <Engine/Core/Log.h>
#include <Engine/Core/Stats.h>
#include <Engine/ECS/Scene.h>
#include <Engine/ECS/EntityHandle.h>
#include <Engine/ECS/Components.h>
#include <Engine/Assets/AssetManager.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <GLFW/glfw3.h>
using namespace Engine;
using namespace Engine::ECS;
class SandboxApp final : public Application
{
public:
SandboxApp()
: Application("HelloVulkan", 1280, 720)
{
}
protected:
// ---- 生命周期 ----
void OnInit() override
{
Scene& scene = GetScene();
// 模型资产(AssetManager 负责加载/缓存/生命周期,返回句柄)
auto backpack = GetAssets().LoadModel("assets/models/backpack/backpack.obj");
// 地面:接收阴影(中性灰纯色,衬托影子)
auto ground = GetAssets().CreatePlane(30.0f, {140, 140, 145});
auto groundEntity = scene.CreateEntity("Ground");
groundEntity.AddComponent<TransformComponent>().world =
glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, -2.0f, 0.0f));
groundEntity.AddComponent<MeshRendererComponent>(MeshRendererComponent{ground});
// 相机实体(primary = 当前渲染视角)
m_Camera = scene.CreateEntity("MainCamera");
auto& camera = m_Camera.AddComponent<CameraComponent>();
camera.primary = true;
camera.camera.SetPosition(glm::vec3(0.0f, 0.0f, 7.0f));
// 背包实体 × 3
for (int i = 0; i < 3; ++i) {
auto e = scene.CreateEntity("Backpack" + std::to_string(i));
e.AddComponent<TransformComponent>().world = glm::translate(
glm::mat4(1.0f),
glm::vec3((i - 1) * 1.5f, 0.0f, 0.0f));
e.AddComponent<MeshRendererComponent>(MeshRendererComponent{backpack});
m_Spinners.push_back(e);
}
// 灯光实体(主光较平,影子拉长可见)
scene.CreateEntity("KeyLight")
.AddComponent<LightComponent>(
LightComponent{glm::vec3(-0.5f, -0.6f, -0.35f),
glm::vec4(1.0f, 0.95f, 0.9f, 1.0f)});
scene.CreateEntity("FillLight")
.AddComponent<LightComponent>(
LightComponent{glm::vec3(0.5f, -0.5f, 0.3f),
glm::vec4(0.3f, 0.5f, 1.0f, 0.8f)});
}
void OnUpdate(f32 deltaTime) override
{
m_Time += deltaTime;
// 相机(WASD/Space/Shift 移动)
m_Camera.GetComponent<CameraComponent>()
.camera.Update(GetWindow(), deltaTime);
// 旋转动画:直接写实体组件
for (size_t i = 0; i < m_Spinners.size(); ++i) {
f32 angle = m_Time * glm::radians(60.0f) + static_cast<f32>(i) * 0.7f;
auto& transform = m_Spinners[i].GetComponent<TransformComponent>();
glm::mat4 t = glm::translate(
glm::mat4(1.0f),
glm::vec3((static_cast<f32>(i) - 1.0f) * 1.5f, 0.0f, 0.0f));
glm::mat4 r = glm::rotate(glm::mat4(1.0f), angle, glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 s = glm::scale(glm::mat4(1.0f), glm::vec3(0.5f));
transform.world = t * r * s;
}
}
// ---- 事件 ----
void OnKeyPress(const Event& event) override
{
if (event.key == GLFW_KEY_F1) {
STATS.PrintComparison();
}
if (event.key == GLFW_KEY_ESCAPE) {
Close();
}
}
void OnWindowResize(const Event& event) override
{
ENGINE_INFO("App: window resized to {}x{}", event.width, event.height);
}
private:
EntityHandle m_Camera{}; // Scene::CreateEntity 之前为空
std::vector<EntityHandle> m_Spinners;
f32 m_Time = 0.0f;
};
int main()
{
SandboxApp app;
try {
app.Run();
}
catch (const std::exception& e) {
ENGINE_FATAL("Exception: {}", e.what());
return -1;
}
return 0;
}