atdunbg
3403822a52
feat(engine): C++ native script system (ScriptBehavior + registry)
...
ScriptComponent stores only a script name string (POD, serializable);
instances are reconciled by ScriptRuntime each frame (PhysicsWorld
pattern): orphan/rename cleanup with OnDestroy, per-name instantiation
from a file-level self-registering registry (ENGINE_REGISTER_SCRIPT),
OnCreate on bind, OnUpdate after physics step on scaled dt. Engine
framerate loop only sees the base interface, so future Lua/C# behaviors
plug in as foreign ScriptBehavior implementations with zero engine
changes. Ships a Spinner sample script and Inspector script picker.
2026-10-03 18:02:49 +08:00
atdunbg
ea6beee593
fix(physics): editor drag teleports dynamic bodies
...
SyncScene only reconciled static/kinematic transforms into Jolt bodies;
dragging a dynamic entity (esp. while paused, where Writeback never runs)
moved the visual but left the body -- and the collider debug wireframe --
at the old pose. Dynamic bodies now get the same drag reconciliation
(teleport + zero velocity + activate), and Writeback syncs
lastPos/lastRot to the body pose so physics motion is never misread as
editor dragging (which would teleport the body back).
2026-10-03 17:51:11 +08:00
atdunbg
d5a86c170e
fix(renderer): mesh collider source positions in render space for skinned meshes
...
Skinned meshes keep vertices in raw mesh space (bakeTransform=false);
rendering transforms them via bind palette (global(bone) x invBind, folds
FBX unit scale). Physics MeshShape/ConvexHull and the mesh bounding sphere
consumed the raw positions directly -> M1911 hull measured ~10x the visual
size. ParseFromDisk now bakes bind-palette-skinned positions per vertex
(same formula as the skinning shader) into ParsedMesh::cpuPositions; Mesh
uses them for m_CpuPositions and bounds. GPU vertex data and rendering are
untouched.
2026-10-03 17:43:55 +08:00
atdunbg
e1cef53158
physics: character controller (Jolt CharacterVirtual)
...
- CharacterControllerComponent: capsule params (radius/halfHeight, mass,
max slope, step height); entity origin = feet via shape offset
- CharacterController per-entity wrapper: gravity integration + grounded
clamp, ExtendedUpdate (sweep/slide + stick-to-floor + walk-stairs),
SetLinearVelocity/Jump/IsGrounded facade
- PhysicsWorld: SyncCharacters reconcile (create/rebuild on param
change, editor-drag teleport), UpdateCharacters after physics Update
(Jolt recommended order), writes back to Transform
- Inspector: params + grounded/velocity telemetry + jump debug button
- Serialization: params only, state rebuilt by reconcile
2026-10-03 16:34:20 +08:00
atdunbg
82910c41e8
physics: joint constraints (fixed/hinge/ball)
...
- JointComponent: type, target UUID, per-body local anchors, hinge axis
+ angle limits (data only, zero Jolt deps)
- PhysicsWorld::SyncConstraints: create/remove/rebuild on snapshot
change; body rebuild contagion via invalidated-bits list; target
resolved lazily by UUID each sync (no two-pass load needed)
- Jolt FixedConstraint/HingeConstraint/PointConstraint in
LocalToBodyCOM space (anchors minus shape COM); fixed frames lock
creation-time relative pose; hinge axis aligned across bodies
- Inspector: Joint section with target entity name dropdown
- Serialization: Joint map with UUID target, as<T> fallbacks
2026-10-03 16:26:20 +08:00
atdunbg
a744b332eb
physics: capsule/cylinder/compound collider shapes
...
- ColliderType + Capsule/Cylinder/Compound; CompoundChild list (Box/
Sphere/Capsule, local pos/quat, non-recursive)
- CreateBody: CapsuleShape/CylinderShape (ctor param orders differ) +
StaticCompoundShape; empty/failed compound falls back to Box
- BodyRecord caches radius/halfHeight/compound; SyncScene rebuilds on
change (per-collider param extraction)
- Inspector: combo entries + shape params + compound child list editor
- Serialization: new fields with as<T> fallback, compound seq round-trip
2026-10-03 16:17:44 +08:00
atdunbg
6c81bfd70d
physics: rigid body drive API (force/impulse/torque/velocity)
...
PhysicsWorld facade methods addressed by entity bits via body records:
AddForce/AddImpulse/AddTorque (dynamic bodies only, auto-wake), Set/
GetLinearVelocity/SetAngularVelocity (dynamic + kinematic). Inspector
RigidBody block gains impulse debug controls for manual response tests.
Transient by design — nothing serialized.
2026-10-03 16:10:22 +08:00
atdunbg
fae6614e70
editor camera: dedicated Scene-view camera decoupled from camera entities
...
EditorCamera (UE FEditorViewportClient semantics) owned by SceneRenderer:
own TransformComponent + reused Camera controller. BuildFrame dispatches
render source by display mode — editor form always renders from the
editor camera (usable in empty scenes), game form renders from the
scene's primary camera entity. AlignTo copies an entity pose into the
editor camera ("Align Viewport to Camera" button in Inspector). F focus
and viewport gizmo now follow the same dispatch. main.cpp stripped of
dangling sandbox camera/spinner state; onSceneLoaded hook removed.
2026-10-03 15:52:28 +08:00
atdunbg
e2a9c21e68
fix(serialization): load failure on hardened yaml-cpp + flow-style arrays
...
yaml-cpp master hardens zombie nodes: operator=, size(), Type() and
chained operator[] all throw InvalidNode instead of silently passing.
Storing per-component nodes via Node::operator= threw for every key
that was absent, so all 7 entities were skipped on load (0 loaded).
Reads are now level-by-level guarded (copy-init + IsDefined), which
only uses the safe surface (as<T>(fallback), begin(), IsDefined).
Save side switched from node-tree streaming to a manual Emitter:
vector/quat fields emit as single-line flow arrays ([0, 1.2, -6])
and model refs as inline maps, with 9-digit float precision for
lossless float32 round-trips.
Verified offline against the previously saved scene: 7/7 entities
parse with correct component counts; emitter output round-trips.
2026-10-03 15:30:36 +08:00
atdunbg
007d175314
serialization: scene save/load (Unity-style YAML + UE-style GUID registry)
...
Engine-layer SceneSerializer (yaml-cpp submodule): entities/components
to versioned YAML, atomic clear-and-rebuild on load with per-entity
fault tolerance, missing-field defaults, unknown-component skip and
UUID dedup. Asset references are {Guid, Path} pairs resolved through
the new AssetManager GUID registry (assets/asset_registry.yaml) with
path fallback; procedural:// pseudo-paths rebuild from parameters.
Editor File menu gets Save/Load Scene modals; app re-resolves stale
entity handles via onSceneLoaded callback.
2026-10-03 14:47:02 +08:00
atdunbg
ffe33e9967
camera: UE Scene-view semantics — RMB fly, MMB focus-orbit, wheel dolly, F focus
...
Key conflict fix (UE semantics): while RMB is held the keyboard belongs
to the camera, so WASD no longer collides with the gizmo W/E/R tool
hotkeys. Editor mode gates fly movement behind RMB; game mode keeps
always-on WASD. Viewport tool hotkeys (W/E/R/T/F) are suppressed while
RMB is held.
Focus orbit (pivot): MMB drag rotates the camera around a pivot keeping
distance; first orbit picks a pivot 5m ahead on the view ray. Shift+MMB
pans in screen plane (camera and pivot move together). Mouse wheel
dollies toward/away from the pivot with exponential steps (no pivot:
move along view ray). F focuses the selected entity (frame-selection):
pivot set to its position, camera slides along the view ray; orbit
distance persists.
Window gains a polled scroll-delta channel (ConsumeScrollDelta) that
respects ImGui mouse capture; Camera::Update mutates orbit state (no
longer const).
2026-10-03 13:02:55 +08:00
atdunbg
9ff08651f0
editor: revert self-drawn scale gizmo, clip degenerate axes instead
...
User feedback: the self-drawn scale handles clash visually with the
ImGuizmo translate/rotate rods (different size/style, clearly not one
widget). Keep the library widget for all three ops for visual
consistency and prevent mis-drags by masking degenerate axes via
SetAxisMask:
- translate: axis ~ parallel to camera-to-object line (sin < 0.25)
- scale: axis ~ perpendicular to camera-to-object line (|dot| < 0.1,
intersection numerator identically zero -> grab fails/values jump)
OR axis ~ parallel to view direction (|dot| > 0.98, zero screen
displacement -> value never changes)
- rotate: screen-space math, no degeneracy, no mask
Masked axes are neither drawn nor activatable; a slight view change
restores them. Center uniform-scale square (MT_SCALE_XYZ, pure screen
space) stays available in any view.
2026-10-03 12:46:07 +08:00
atdunbg
c9d4eed043
editor: scale gizmo fully self-drawn (screen-space, view-independent)
...
ImGuizmo scale hover/drag relies on ray-plane intersection with the
axis as plane normal; in front views (axis ⟂ camera-to-object) the
intersection numerator is identically zero, so handles can't be
grabbed and values jump randomly; axes parallel to the view have zero
screen displacement. Submodule is read-only and AxisMask can only hide
degenerate axes, not replace them.
Replace the library scale path entirely with a screen-space gizmo:
- three axis rods (line + end square) + center uniform-scale square,
constant screen size in any view
- axis drag: mouse delta projected onto the axis' screen direction
- axis pointing at camera: radial mapping (drag away = grow)
- center square: uniform scale (library MT_SCALE_XYZ semantics)
- Ctrl snapping quantizes the result; scale clamped >= 0.01
- pick suppressed while hovering/dragging the self-drawn handles
2026-10-03 12:23:00 +08:00
atdunbg
21b33d7d7f
fix(editor): 缩放轴病态判据与平移互补,按 op 分派 AxisMask
...
缩放独有老问题根因(源码实证):缩放 hover(GetScaleType)与拖拽
(HandleScale ratio 分母)依赖"法线=轴"平面求交,交点距离分子 numer
= -dist·dot(camToObj, 轴)。正对视角相机与物体无横偏时 numer≡0 →
len=0/垃圾 → 杆 hover 不到、ratio 分子分母乱跳(数值随机猛变)。
平移 hover 是纯屏幕距离、平面法线经正交化自适应;旋转是屏幕角数学
——故唯独缩放有此病。SCALE op 下判据换 |dot(camToObj,轴)|<0.1,
ROTATE 不 mask,TRANSLATE 保持 sinθ<0.25。中心块等比缩放
(MT_SCALE_XYZ,屏幕空间数学)不受 mask 恒可用。
2026-10-03 12:11:16 +08:00
atdunbg
a130850276
feat(editor): Gizmo 退化轴自动隐藏(调用层 SetAxisMask,UE 语义)
...
正对视角 + 物体竖直偏移时,单轴拖拽灵敏度 sinθ(轴与相机连线夹角)→0:
拖拽投影系数趋 0("数值不变"),激活平面与鼠标射线共面(IntersectRayPlane
denom→0 返回 -1 被当交点距离)。按灵敏度 <0.25(θ<14.5°)将病态轴
SetAxisMask 隐藏(库公开 API,按轴关绘制+激活,保留含该轴的平面手柄
与中心块兜底),相机移动后自动恢复——可激活性决定可见性,零库改动。
2026-10-03 12:03:07 +08:00
atdunbg
1d360369c9
revert: 删除 SetPlaneLimit 覆盖,Gizmo 参数与 Horizon 对齐(全默认)
...
对照 Horizon 实现(同官方 ImGuizmo submodule、零定制、Manipulate 全
默认参数)确认库默认行为就是可用的出货行为。0.034 把轴隐藏阈值从
11.5° 抬到 20°,常规视角轴被过早隐藏("箭头又没了");之前 0.35 同
根因。两次阈值折腾全部推翻:自行覆盖库内部可见度参数本身就是错的方向。
2026-10-03 02:27:46 +08:00
atdunbg
af241857af
fix: 轴可见度阈值 0.35→0.034(量纲修正,0.35 会隐藏所有轴)
...
前次 0.35 的错误:把阈值当成 0~1 的 sinθ 直接比较。实际库内 gizmo
恒定屏幕尺寸(mGizmoSizeClipSpace=0.1),可见判定 =
sinθ > 阈值/0.1 —— 0.35 ⇒ sinθ>3.5 永假 ⇒ 所有轴消失。
仿真量纲(MVP 复刻 + ScreenFactor 机制确认):⊥视线轴 clip 长度
恒 ≈0.97·screenFactor=gizmoSize;视线向轴 = gizmoSize·sinθ。
0.034 ⇒ sinθ>0.34 ⇒ θ<20° 隐藏(UE 正对轴隐藏语义),≥20° 可拖。
2026-10-03 02:02:37 +08:00
atdunbg
5cc9b14d73
fix: 旋转 snap 单位修正(度非弧度)+ 轴可见度阈值对齐 UE 正对轴隐藏语义
...
两个实锤问题(源码数学 + 数值仿真定位):
1. 旋转 snap 传了 glm::radians(15°)≈0.26,而库按"度"解释
(docs/documentation.md:snap angles are in degrees,库内自行
DEG2RAD)→ 实际步进 0.26° 形同虚设。改传 15.0
2. 正对视角两症状同根因(view-aligned axis degeneracy):
- 轴⊥视线:悬停检测的射线-垂直平面求交 denom=0 → len=-1 →
无法 hover(动视角即恢复)
- 轴∥视线:屏幕投影无一阶位移 → 怎么拖都不动
默认 mPlaneLimit=0.02 太小,"有高度差"视角下投影 sinθ≈0.17~0.34
刚好高于阈值 = 看得见但几何上不可操作。提至 0.35:夹角 <20° 的
轴自动隐藏(UE 同语义),>20° 正常可拖
2026-10-03 01:49:42 +08:00
atdunbg
83c1600947
feat: Gizmo local/world 空间切换 + Ctrl 吸附 + Inspector 轴色手输行
...
- GizmoState.localSpace(默认 local,模型轴旋转直观),T 键切换
Manipulate 的 LOCAL/WORLD 模式;无父层级两模式 world 矩阵同源,
decompose 写回链路不变
- Ctrl 按住吸附(UE Grid Snap 语义):平移 0.25m / 旋转 15° /
缩放 0.1x;ImGuizmo 约定旋转 snap 单位为弧度
- 视口左上角 drawlist 叠加状态提示(Space/Snap,不占布局行)
- Inspector Transform 三行升级 UE 风轴色输入行(对齐 Gizmo 轴色):
拖拽粗调 + Ctrl+Click 键入精确值
2026-10-03 00:56:27 +08:00
atdunbg
e5161439dd
refactor: TransformComponent 旋转存储改四元数(UE FTransform 语义)
...
欧拉角内部存储每帧矩阵↔欧拉往返,是 Gizmo 拖拽乱跳/缩放串轴的
结构性根源(74d2f6c 的单点公式修复治标不治本)。对齐 UE/Unity
方案:内部存 glm::quat,欧拉只在 UI 表皮。
- Components.h:m_Rotation 改 quat;Compose 用 mat4_cast;
SetRotation(euler) 转存(q=qy·qx·qz);新增 SetRotationQuat/
GetRotationQuat;GetRotation() 改派生欧拉(YXZ 序矩阵反解,
仅 UI 显示/编辑用)
- ViewportPanel:Gizmo 写回 decompose 的 quat 直写,删除整个
欧拉提取块
- PhysicsWorld:删 QuatToEulerYXZ/EulerYXZToQuat,改 ToJolt/
ToGlm 分量直转;物理写回 SetRotationQuat;BodyRecord.lastRot
改存 quat
验证(1 万随机姿态 round-trip):Gizmo 链路矩阵差 7.9e-07
(旧欧拉方案 3.56e-04,好 3 个数量级);万向锁 pitch=±90° 穿
表皮恒定;欧拉表皮误差 4.5e-04 为欧拉参数化固有病态(随
pitch→±90 指数增长,仅影响 UI 显示数值),热路径不经过。
2026-10-03 00:47:11 +08:00
atdunbg
74d2f6cdaa
fix: Gizmo 旋转/缩放写回乱跳——eulerAngles 序约定与 Compose YXZ 失配
...
glm::eulerAngles 假定 XYZ 系约定,与 TransformComponent::Compose 的
YXZ 旋转序不一致:复合旋转下(如 Dynamic 实体被物理写入非零姿态)
decompose 出的角度按错误序重组 → 写回的 R ≠ 拖拽时的 R → 下一帧
Manipulate 拿到歪矩阵 → 旋转乱跳、缩放串轴。
改为按引擎 YXZ 序(R = Ry·Rx·Rz)从旋转矩阵直接提取欧拉角:
- 常规区:atan2 分子分母 cx 约掉,pitch 任意角精确(含 ±90° 邻域)
- float 真奇异(|pitch|=90°):组合角归 yaw、roll=0(UE 同策略),
±90° 两支 atan2 符号不同
验证(round-trip 1e4 样本,矩阵 Frobenius 差判据):
- 欧拉链 2.67e-04、全 SRT 链 3.56e-04(float32 极限)
- 万向锁邻域专项覆盖
2026-10-03 00:27:16 +08:00
atdunbg
ce5e07879c
fix: Gizmo 无法拖动 + Dynamic 提示行顶视口抖动
...
- Editor::Draw 每帧首调 ImGuizmo::BeginFrame():不调则
mbOverGizmoHotspot hover 一次杆后永久置位(仅 BeginFrame 清零),
GetMoveType 恒返 MT_NONE → 杆可见但永远抓不住
- Dynamic 刚体提示改 drawlist 叠加(Image 内左下角、纯英文):
TextDisabled 占布局行 → 滚动条出现/消失循环 → avail 抖动 →
渲染分辨率每帧重报(视口疯狂顶动);且默认字体无中文字形
2026-10-02 23:30:04 +08:00
atdunbg
3ec96acc0f
feat: Editor Gizmo——ImGuizmo 平移/旋转/缩放操纵杆
...
- ImGuizmo 接入:Lib/ImGuizmo(src/ 布局)静态库,IMGUI_DEFINE_MATH_OPERATORS
- ViewportPanel:Vulkan→GL 投影转换(Y 翻回 + 深度 [-1,1])、
SetDrawlist/SetRect 叠加绘制、decompose 写回 TransformComponent
- W/E/R 切换(UE 语义);拖拽中 BlockingMouse 门控(输入归 Gizmo)
- Dynamic 刚体选中提示:物理每帧写回,编辑被覆盖
- 修复:GizmoState.op 初值 0 无轴位(ImGuizmo::TRANSLATE=7)导致杆不绘制
- 点击拾取门控:抓杆时(IsOver/IsUsing)不发 pick 请求
2026-10-02 23:16:52 +08:00
atdunbg
56bb31638e
添加windows构建适配,禁用ImGui多视口功能
2026-10-02 21:53:26 +08:00
atdunbg
b0d5ed4550
refactor: ShaderManager 引用计数句柄——shader 生命周期自动化
...
- ShaderObject 值类型 → ShaderRef(shared_ptr 语义,UE TShaderRef
对标):拷贝共享所有权,最后一个引用析构时自动销毁 VkShaderEXT,
持有方零清理代码——"新 pass 忘销毁"整类 bug 被机制消灭
- 删除公开 Destroy 与全部持有方手工 destroyShaderEXT(8 处);
各类析构只清 sampler/layout/set 等其余原生句柄
- RecordFullscreen 参数收窄为 const ShaderRef&(裸 handle 无法
再被误传);bind 点统一 GetHandle()
- Outline/SelectionMask 撤掉上一轮补的 Device&(不再需要)
- 验证:5s 探针自动退出 → exit 0、无 VUID-05137 泄漏、无 SIGSEGV
2026-10-02 20:20:07 +08:00
atdunbg
47dd879977
fix: 退出 SIGSEGV 与 VkShaderEXT 泄漏——生命周期三层秩序
...
- 根因:~Application 体内 Logger::Shutdown() 先于成员析构执行,
Device 销毁期间 Vulkan validation 回调仍打日志 → spdlog 悬空调用
- 修复:app 置于 main 独立作用域,所有成员析构完毕后再 Shutdown
- 退出序 = waitIdle(~Application 体内)→ 成员析构(shader 等
Device 子对象销毁)→ Logger::Shutdown
- 顺带注释掉窗口全透明(调试期遗留)
2026-10-02 20:09:12 +08:00
atdunbg
1449bea86d
feat: HitProxy GPU 拾取 + UE 选中描边 + 编辑器拾取交互
...
- HitProxy 拾取:RG 管线渲染实体 id → host readback,点击帧
PickEntity 精确命中;拾取按视觉几何(Model 联合包围球射线求交),
与 Collider 解耦(UE/Unity 编辑器语义),命中打印实体名+碰撞体参数
- 选中描边(UE 语义):SelectionMask pass(R8Unorm 完整投影轮廓,
无深度测试透墙可见)→ Outline pass(边缘检测 + alpha 叠加,
必须注册在 Tonemap 后);edgeCut 贴视口边缘;widthPx=6 可调
- shader object 实证修复:VUID-08879 同程序 set layouts 超集一致、
VUID-10065 push block 4×float 平铺、新 pass 析构销毁 VkShaderEXT
- RG:SideEffect() 保活"产出无 RG 内消费者"的 pass 链
- Editor:层次面板点击选中、Inspector 姿态编辑、Stats 面板拾取信息
- 相机 Update 改 const(姿态写入 Transform 引用,Camera 本身无状态变更)
2026-10-02 20:09:05 +08:00
atdunbg
1c4b6f37ff
feat: Jolt 物理系统——刚体/碰撞体/物理调试图元 + 引擎时间单源
...
- PhysicsWorld:Jolt 集成,Dynamic/Kinematic/Static 刚体,姿态写回
Transform(Unity FixedUpdate 语义,吃 scaled dt,暂停自动冻结)
- 碰撞体:Box(默认/手动 halfExtents)+ Mesh 碰撞体(Static→精确
MeshShape / Dynamic·Kinematic→ConvexHull,数据源 = Mesh ctor 缓存
的 CPU 位置副本,退化三角剔除,失败回退 Box 并告警)
- PhysicsDebugPass:物理调试图元每帧上传绘制(debug_line shader)
- Time:引擎时间单源(BeginFrame 落定 FrameTime,scaled/unscaled 分离)
- JoltPhysics 以 submodule 接入(官方 url)
2026-10-02 20:08:54 +08:00
atdunbg
bfbb18f1a4
build: meshoptimizer 改为 git submodule(--depth=1)
...
Lib 依赖一律 submodule 不入库;历史中的在树源码记录已用 filter-branch 全量清洗
2026-09-30 09:22:30 +08:00
atdunbg
20f0035baa
feat: ImGui docking Editor + 显示链/帧同步/输入语义重构
...
- App/editor: Hierarchy/Inspector/Viewport/Stats 四面板 + DockBuilder 默认布局,main.cpp 瘦身为场景搭建与生命周期
- 显示链: Tonemap→PresentTarget 经 ImGui::Image 呈现(零色偏),backbuffer 仅承载 ImGui;Direct/Viewport 双显示模式 + 面板分辨率上报
- 帧首同步 BeginFrameSync: resize/vsync/尺寸/模式意图统一帧首落定(修描述符悬垂);修复 vsync 意图未落 swapchain 导致的每帧重建交换链
- 输入: Editor 每帧判定键盘/鼠标归属(打字让位、Viewport hover/focus 放行、Fullscreen 全放行)
- 材质: roughness 独立槽位 + 非 glTF 金属/粗糙贴图映射;透明队列 depthWrite=FALSE + translucent 独立 shader + scratch 清帧
- FBX: 非蒙皮网格烘焙节点链全局变换(Z-up 旋转/单位换算落顶点)
- Hierarchy 行 ImGui ID 以 UUID 作用域(重名不冲突、改名不丢选中)
2026-09-30 00:24:53 +08:00
atdunbg
b25fa29fe5
feat: 透明材质 alpha blending——独立队列 + 线性 over 混合 + 距离排序
...
透明来源:glTF alphaMode=BLEND(解析期读取,OBJ/FBX 恒不透明——
资产格式定义写死);MASK 后续演进。Material 加透明语义(入缓存键),
程序化测试资产 CreateTransparentPlane(RGBA 纯色纹理)。
SceneRenderer:透明材质实例收集进独立 scratch(仅主视图,不投
阴影——alpha 阴影后续演进),batch 按平均距离降序排序(远→近,
batchMats 同步重排),SSBO 扁平化顺序 = 排序后顺序。
ForwardPass 两段绘制:不透明(无混合 + 深度写)→ 透明(Shader
Object 动态状态切 SRC_ALPHA/ONE_MINUS_SRC_ALPHA 线性 over + 深度
只测不写);velocity 附件透明段直写(透明表面 velocity 即自身运动)。
frag alpha = albedo 贴图 a 直通,预乘在 tonemap 段(hard constraint
不变)。已知边界:TAA alpha 时域混合(透明边缘几帧渐显);同 batch
多实例不做实例级排序。
2026-09-25 16:57:27 +08:00
atdunbg
8dbfb9f554
feat: LOD 运行时开关(ImGui Features 横排,关 = 实例收集恒选 LOD0)
2026-09-25 16:39:16 +08:00
atdunbg
a975845214
perf: BuildFrame 收集段优化——实体级粗剔除 + 数组化 batch 查找 + 合并矩阵写
...
定位数据(100 背包 + SunTemple,RTX 5060):GPU 全帧仅 ~3ms
(Forward 1.91 + Shadow 0.82),CPU BuildFrame 收集段 5.94ms 才是
帧率瓶颈。三段细分测量:pre 0.2 / each+cull 5.0 / flatten 0.4。
优化(collect 5.94 → 4.6ms,-23%):
1. Mesh 全局连续槽位(GetSlot);ViewScratch batch 查找 hash →
数组寻址(slot × kMeshLodCount 槽)
2. Model 级联合包围球(各 mesh bounds 并集):实体在四视图全部
不可见 → 跳过整个 mesh 循环(多 mesh 模型的粗剔除)
3. worlds/prevWorlds 合并为 stride-2 InstanceMatrices 单次写
(每实例每视图 2 次随机堆访问 → 1 次,cache miss 减半)
遥测:Renderer::GetCollectMs 暴露收集段耗时。剩余 4.6ms 的进一步
压缩(并行收集 / GPU-driven culling)单独立项。
2026-09-25 08:08:51 +08:00
atdunbg
d9b1742327
feat: LOD 网格分级——meshopt 解析期简化 + 按距离/级联选级
...
vendored meshoptimizer 1.2(submodule 环境故障改直接 vendor)。Mesh
多 LOD:各级索引连续拼进同一 index buffer(共享顶点,LodRange 区间
选择),解析期 meshopt_simplify 生成链(LOD0=原始,每级目标减半,
相对误差 1e-2,小网格复用上级);都在 worker 线程,加载零额外卡顿。
SceneRenderer 按 (mesh, LOD) 聚合 batch(lookup key = 指针<<8|lod):
主视图按屏占比近似 radius/dist 选级(阈值 10/20 倍半径);阴影级联
按级联序降级(越远越简)。Draw 按 batch.lod 选索引区间。
A/B 对比(100 背包 10×10,RTX 5060 Laptop,vsync off):
- 纯背包:LOD 开 93-95 fps / 关 90-107 fps —— 无显著差异
- 加 SunTemple:LOD 开 52-56 / 关 51-55 —— 无显著差异
结论:当前场景瓶颈不在顶点数(5060 顶点吞吐富余),LOD 基础设施
保留(几何复杂资产/低端 GPU/更大场景生效),帧率问题转向 Tracy
GPU 时间线定位真实瓶颈。
坑:LodRange 记录"LOD 不足复用最后一级"时 first 不得继续累加
(buffer 无重复数据,累加必越界——VUID-08798 抓的)。
2026-09-24 20:53:19 +08:00
atdunbg
34b593f734
fix: TRACY_ON_DEMAND——GPU context 宣告随连接重发
...
GpuNewContext 消息只在 TRACY_ON_DEMAND 下 DeferItem(连接后重发)。
程序启动即建 Tracy GPU context 而 GUI 晚连接,宣告丢失 → GUI 不认识
GPU context → pass zone 全部不显示(只见 CPU lane)。启用按需剖析:
连接建立后的帧才活跃,语义即 tracy 官方推荐用法。
2026-09-24 20:16:30 +08:00
atdunbg
3bfe28b027
feat: Tracy GPU 时间线——RG pass 级 GPU zone
...
RenderGraph 新增 IGpuProfiler 可选注入(pass 边界 Begin/End 钩子 +
帧尾 Collect,zone 覆盖 barrier+lambda+postBarriers),RG 本体不感知
任何 profiler 实现。Renderer 侧 TracyGpuProfiler 实现:TracyVkContext
(校准用临时 cb,池必须带 RESET_COMMAND_BUFFER_BIT——tracy 校准流程
对同一 cb 连续 begin 三次)+ TracyVkZoneTransient(pass 名是运行时
字符串)。TRACY_ENABLE 关闭全链路退化为空。
用法:Tracy GUI(0.14.1 配对)连接后按 pass 名看 GPU 段时间线,
与 ImGui 数表互补;LOD 调优的测量前置。
2026-09-24 19:45:17 +08:00
atdunbg
99e6712cdf
feat: 模型异步加载——assimp 解析移后台线程(SunTemple 3s 卡顿消除)
...
Model 拆两段式:ParseFromDisk(static 纯 CPU,assimp 解析 → 几何 +
材质引用,worker 可调)/ FromParsed(GPU 构建:纹理上传 / mesh 缓冲 /
材质描述符,主线程),同步路径等价两段串行。第二个异步任务类型落地,
线程收割骨架抽成 Core/AsyncTask<T>(thread + atomic + Take,覆盖式
Run;pending 接力语义留调用方)。
实测(SunTemple 1056 mesh):解析 2.5s 全程在 worker,主线程持续
渲染;GPU 构建 0.56s。assets 层经 IAssetUploader/AssetManager 重载
传预解析产物(路径缓存去重,路径已缓存则产物丢弃)。
已知边界:纹理解码(backpack 4k PNG ~1s)仍在 GPU 段主线程——
Texture 需支持预解码像素注入,后续演进。
2026-09-24 19:31:14 +08:00
atdunbg
6df3be2846
feat: 透明窗口 + 实例预算扩容(修复斜光阴影静默截断)
...
透明窗口:SceneSettings 加 ClearColor/DrawSkybox,随 FrameSceneData
每帧下发到 SkyboxPass(替换硬编码清屏色);GLFW 透明帧缓冲已开,
tonemap 预乘 alpha 直通已有,链路全通。TAA alpha 时域混合为已知边界。
实例预算:kMaxInstances 16384 → 65536(四视图共享预算,100 实体
斜光时需求 16.4k 超限,cascade 2 实例被静默丢弃 = 用户看到的
"拖灯光方向部分背包阴影消失")。截断状态每帧落遥测 + ImGui 红字
(原 warn-once 对动态穿越阈值的场景等于没有告警)。
2026-09-24 18:54:01 +08:00
atdunbg
fa9681aa41
fix: GPUDriven batch 实例连续性——多实体共享 mesh 时实例数组错乱
...
实例数组按实体序收集([实体A的mesh][实体B的mesh]),而 GPU 端
batch 语义要求同一 mesh 的实例连续(firstInstance 基址 +
gl_InstanceIndex 直查 SSBO)。多实体共享 Model 后 mesh i 的各实例
分散在数组各处,batch.first+i 落到别的 mesh 的变换上——第二颗
背包的几何全画到第一颗的相邻 mesh 位置(碎裂/缺失/近看缺块)。
修:剔除期实例先归入各自 batch(ViewScratch 持有 per-batch 实例
列表),拼接时按 batch 扁平化为连续区间,batch.first = 扁平化基址。
单实体路径行为不变(每 mesh 单实例天然连续),容量跨帧复用。
2026-09-24 16:23:47 +08:00
atdunbg
25a365fce7
feat: 环境异步加载——HDR 解码移后台线程,运行时切换不卡主线程
...
decode 是切换耗时大头(4k ≈ 130-160ms),搬出主线程后运行时切换
只剩 GPU 段(~40ms)。IblGenerator 拆两段式:DecodeHdr(static,
纯 CPU 无线程状态,worker 可调)+ FromDecoded(GPU 生成,主线程);
FromHdrEquirect 保留为同步便捷路径。Assets 层经 IAssetUploader
重载 + AssetManager 重载传递预解码产物(路径已缓存则丢弃去重)。
App 层单 in-flight 状态机:worker 只产出纯 CPU 像素数据,忙肋期
新请求记 pending 接力(只保留最终意图),OnUpdate 每帧收割 +
SetEnvironment 换绑,析构 join。
实测(RTX 5060 Laptop,4 实例网格 + 运行中连切 3 环境):
~180fps 无感知尖峰;0 validation。
2026-09-24 14:32:39 +08:00
atdunbg
641f79d89e
fix: GPUDriven batch lookup 索引语义混淆——多实体共享 mesh 越界崩溃
...
ViewScratch.lookup 误存 worlds 索引却被当 batches 索引用。单实体时
每个 mesh 恰好只出现一次、两序号恒等,潜伏不炸;多实体共享同一
Model(2x2 实例网格实测)后 worlds 与 batches 分叉,first-insert
用 worlds.size() 索引 batches → vector 断言越界。
修:lookup 存 batches 索引,batch.first(GPU firstInstance 基址)
保持 worlds 索引,两语义各归其位。
2026-09-24 14:32:39 +08:00
atdunbg
08439ed015
fix: ImGuiLayer 析构提前到 Logger Shutdown 之前 + UI 计时段收窄
...
m_ImGuiLayer 在 Application 析构体显式 reset(否则成员析构序在
Logger::Shutdown 之后);UI 计时范围从 Run 循环收窄到实际 ImGui
构建段(ImGui 未启用时不再计零段)。
2026-09-24 13:44:15 +08:00
atdunbg
b65856b8a5
feat: ImGui 调试面板分组整理
...
Scene/Rendering/Environment/GPU Timings/Frame 五个 CollapsingHeader;
功能开关用 checkbox 条件显隐联动参数(Bloom 勾选才出现 threshold/
strength),无参数开关横排平铺。
2026-09-24 13:44:15 +08:00
atdunbg
1d690067bd
feat: IBL 预积分 GPU compute 化 + 环境资产入 Assets 层(动态切换)
...
CPU 逐像素卷积(venice 4k 阻塞 7.36s)→ 4 个 compute shader 一次性
提交:equirect→cube / irradiance / prefilter×5mip / BRDF LUT。
Cubemap 瘦身为纯资源持有类,生成职责移交 IblGenerator;
环境经 AssetManager 缓存(EnvRef),Renderer::SetEnvironment
动态换绑(RenderPass::OnEnvironmentChanged 广播)。
调试视图 +4:EnvCube / Irradiance / Prefilter / BRDF LUT。
性能前后对比(RTX 5060 Laptop,venice_dawn_1_4k.hdr):
- 改造前 CPU:7.36 s(主线程阻塞)
- 改造后 GPU:HDR decode 127-134ms + 资源 22-35ms + compute 17-19ms
≈ 165-190ms(约 40×);Neutral 兜底 ~6ms
- 运行中动态切换环境同量级(ms 级 GPU,decode 占大头)
冒烟:两构建目录 0 警告;运行期 0 validation(含两次环境切换 +
调试视图 9-12 轮播自动化验证)。
2026-09-24 13:23:59 +08:00
atdunbg
705250df76
feat: spdlog 显式初始化——控制台彩色 + 文件双 sink
...
Application 构造时 Logger::Initialize(APP logger:stderr 彩色 +
HelloVulkan.log 双写,warn 以上立即 flush),析构 Shutdown。
2026-09-24 13:23:52 +08:00
atdunbg
a1c6ad20be
feat: 特性开关 + Pass 调试视图接口(ImGui 可控,统一帧契约)
...
三个运行时开关(Shadows/TAA/Bloom)与 9 种调试视图(Final/
TemporalDiff/HDR/TAAColor/Bloom/Velocity/ShadowMap0-2)。
统一设计:开关状态收敛 FrameSceneData 契约,SceneRenderer 唯一
写入、各 pass 只读(零虚接口路由);调试视图经 tonemap push
int 路由已绑定的中间目标(声明超集、运行时零重绑);HDR 域
资源过同一 tonemap 保证观感可比。
- Shadows:ShadowPass lambda 空转 + frag cascadeSplits.w 短路
- TAA:alpha=0 直通 + SceneRenderer 停投影抖动(同一持有者同步)
- Bloom:3 子 pass 空转 + tonemap 强度归零
- Renderer 门面 Get/Set 转发,App ImGui 3 Checkbox + Combo
- PostProcessParams 瘦身为纯数值参数,showTemporalDiff 被取缔
2026-09-24 13:03:00 +08:00
atdunbg
708d714459
fix: 阴影采样器 CompareOp 反转(诊断残留 eGreater)+ 移除截图调试设施
...
根因:shadow sampler 停留在诊断期的 eGreater——比较语义全反,
全场 shade 被压到 0.3 变暗,唯独真影区 lit=1 反而全亮,
即"影子比环境亮、像光源"的现象。修回 eLess 后影子正常。
顺带清理:第 60 帧截图管线(HDRColor/ShadowMap0 → BMP)、
CPU 投影诊断日志、GetCaptureTarget 及 TRANSFER_SRC extraUsage。
2026-09-24 12:42:24 +08:00
atdunbg
d3c3d0cdd9
fix: 影子中镜面高光残留导致"影子比天空亮"
...
掠射角下 GGX spec 分母 (4·NdotV·NdotL) 变小,HDR 值可达 8+;
阴影只把它乘 0.3,30% 的刺眼白仍比天空亮——观感即"影子发白"。
- spec 项按 shade 重映射(0.3→0,1.0→1):光源被遮挡,其镜面像
应完全消失;diffuse 保留 0.3 作间接近似
- ShadowPass 改正面剔除渲阴影图(标准 acne 治法):封闭网格只写
背面深度,正面深度天然比 ref 大一个表面厚度,从根上消自阴影
acne;代价是单面薄片在光背面时漏写(plane 单面朝上不受影响)
2026-09-24 12:10:15 +08:00
atdunbg
42fd9d5f30
fix: 阴影光源错误绑定 FillLight + 截图 usage 警告 + nodiscard
...
- LightComponent 增加 castShadow 标志;灯收集排序键改为
castShadow 方向光 > 方向光 > 点光(此前稳定排序把收集序靠前的
FillLight 排到 lights[0],KeyLight 方向滑条自然不影响阴影)
- TextureDesc 增加 extraUsage:HDRColor 声明 TRANSFER_SRC,
消除截图 copy 的 3 条 usage 不匹配运行时警告
- waitForFences nodiscard 返回值显式丢弃,消除编译警告
2026-09-24 11:59:18 +08:00
atdunbg
4d3963e291
fix: 阴影不可见——灯序依赖遍历顺序 + 光比失衡,新增帧截图调试能力
...
- 灯序修复(根因):entt Each 遍历序不保证创建序,lights[0] 曾落到
点光(params.x=1)→ shader 阴影分支整个跳过。收集后 stable_sort
方向光排前,确立"lights[0] = CSM 阴影光源"契约
- 光比失衡:IBL 环境与点光淹没主光阴影。KeyLight 5.0 + exposure
默认 0.6 + ambientColor 0.07;阴影区环境光同步衰减(简化遮蔽)
- ShadowPass depth bias 0.006(acne 均值形态 vs 推过头丢阴影的折中)
- Renderer 帧截图能力:第 60 帧自动截 HDRColor/ShadowMap 落 BMP
(ACES+gamma 还原屏幕观感),视觉调试自闭环不再依赖肉眼
- KeyLight 增加 intensity slider(0-20 运行时可调)
2026-09-24 01:49:11 +08:00
atdunbg
8c0a11d2e8
feat: CSM 软阴影——sampler2DShadow 硬件 PCF + 3×3 纹素 tap
...
- 阴影采样器开启硬件深度比较(compareOp=eLess + linear filter):
单次采样 = 2×2 深度比较插值,clamp-to-border 白色语义不变
- ShadowFactor 改 3×3 纹素偏移 tap(等效 36 次比较),影中保留
0.3 环境感并按 PCF 结果插值——阴影边缘软过渡,消除二值硬边锯齿
2026-09-23 23:18:36 +08:00
atdunbg
960bdf2662
refactor: 移除贴图文件名探测——资产读取保持确定性
...
按用户决定:OBJ/FBX 按材质定义(MTL/assimp 槽位)写死读取,
不做文件名猜测补槽;贴图缺失走默认纹理 + INFO 日志可见。
补槽职责归将来手动材质编辑接口。
2026-09-23 19:51:03 +08:00
atdunbg
2b875c9284
feat: OBJ 全量贴图接入——Material 加 AO 槽 + OBJ 工作流适配
...
- Material 槽位 4→5(+AO),参数 UBO binding 4→5;shader ambient
diffuse 项乘 ao(IBL 遮蔽),AO 默认纹理白色
- OBJ 槽落点补全:map_Bump→HEIGHT(5)、map_Ns→SHININESS(7)、
map_Ka→AMBIENT(3)(assimp OBJ importer 约定)——backpack 的
法线贴图此前也从未加载
- MTL 导出遗漏(roughness.jpg/ao.jpg 在目录未被引用):约定文件名
探测补槽(roughness/ao/occlusion × jpg/png),命中留 INFO 锚点
- 因子按工作流分支:glTF 用声明因子(MR 合图 B=金属度);
OBJ metallic=0(specular 工作流无金属概念),roughness 有图→1,
无图→Blinn-Phong Ns 换算 R=sqrt(2/(Ns+2))(补偿默认贴图 G=0.5)
2026-09-23 19:49:36 +08:00
atdunbg
9cc36af3f0
fix: 金属渲染塑料感——glTF MR 贴图未加载 + UV 翻转错误
...
- assimp 5.x glTF2 importer 把 MR 合图落在 METALNESS(15)/
DIFFUSE_ROUGHNESS(16),不是 UNKNOWN(18)——此前 metallic 恒 0
全走电介质路径。槽位查找改为优先级数组(先到先得)
- glTF 的 UV 本就是左上原点,aiProcess_FlipUVs 会把全部贴图上下
颠倒(法线/MR 分布全反)——按扩展名区分 flip
- 材质加载 INFO 日志(贴图槽缺失会静默退化默认纹理,留诊断锚点)
2026-09-23 19:35:06 +08:00
atdunbg
d2b878c077
refactor: Cubemap 拆掉 17 参超级构造——资源三元组 EnvTexture
...
- image/view/显存分配收口为 EnvTexture 单元(RHI 惯例:三者同生共死),
Cubemap = 4 个 EnvTexture + 2 采样器的组合,构造 17 参 → 8 参
- UploadCube/UploadTexture2D 直接返回完整资源单元(view 创建收进
helper),工厂函数只做"生成数据 → 上传 → 组装"
- 析构循环成对释放,杜绝半套泄漏;删除无调用者的 Get()/GetFaceSize()/
GetPrefilteredMipCount()(shader mip 上限以常量契约)
2026-09-23 19:25:32 +08:00
atdunbg
bd4ac6aa12
fix: IBL 全黑根因——RadicalInverseVdC 误用 bit_cast,Hammersley 序列错乱
...
- bit_cast<f32>(bits) 把反转后的整数当 IEEE754 位型解读(LearnOpenGL
原文 float(bits) 是整数值转换)→ xi.y 越出 [0,1] → sqrt(负数) →
BRDF LUT NaN + pre-filter 数据全垃圾 → ambient NaN 整屏黑
- 分离出的积分程序实测:texel(0,2) 样本 10 xi.y=2 → NaN;修后无 NaN
- 加 CPU 侧 fp16 NaN 自检(上传前最后一道防线),数据异常拒绝加载
走中性兜底(不再解引用空指针)
- 中性兜底 1×1 图只建 1 mip(修 mipLevels=5 validation 警告)
- prefilter mip 拷贝偏移改累积制(此前用当前 dim×序号错位)
- prefilter/irradiance 绑定换带 mip 的环境采样器(shadowSampler
maxLod=0 把 textureLod clamp 到最锐 mip)
2026-09-23 19:18:06 +08:00
atdunbg
6e107ac2ba
fix: IBL 模型全黑——prefilter mip 拷贝偏移错位 + 采样器 maxLod 错误
...
- UploadCube 的 mip buffer 偏移误用当前 mip 尺寸×序号(mip 面递减,
正确应为累积偏移)→ 各 mip 拷到 staging 错位数据,含未初始化 fp16
NaN → 污染 ambient 输出整屏黑
- prefilter/irradiance 绑定改用环境采样器(maxLod=mipCount-1):
shadowSampler maxLod=0 会把 textureLod 显式 lod clamp 到 0,
pre-filter 永远停在最锐 mip
2026-09-23 19:07:53 +08:00
atdunbg
9269afaa18
feat: IBL 阶段③——pre-filtered cubemap + BRDF LUT,split-sum 镜面项接入
...
- pre-filter:GGX 重要性采样(Hammersley + van der Corput 位反转),
128²×5 mip 分级 roughness,采样数 32<<mip 上限 256;UploadCube 泛化
支持 mip 链([mip: 6面] 紧凑排布逐 mip 逐面拷贝)
- BRDF LUT:128² R16G16Sfloat 积分表((NdotV,roughness)→F 缩放/偏置),
纯数学与环境无关,中性兜底同样生成;专用 clamp-to-edge 采样器
(共享 border 白采样器在 uv=1.0 混入白色导致高 roughness 偏大)
- shader:specular = prefiltered(R, roughness×4) × (F·A+B),
ambient = (diffuse + specular) × ambientColor
- Hammersley 分母修正为当次积分采样数(低 mip 偏差 bug)
- Debug 构建预积分 26s→14s(采样预算收敛 + pow 改乘法链;
env 1024² 重采样为大头,compute 迁移后归零)
2026-09-23 19:04:25 +08:00
atdunbg
fa25cb3348
feat: IBL 阶段②——漫反射辐照度卷积,PBR ambient 接入环境光
...
- Cubemap 构造期同步 CPU 半球 Lambert 积分(64×32 网格 ≈2048 采样/像素)
生成 32² irradiance cube(漫反射是超低频信号,分辨率无需高)
- shader:kD 用粗糙度感知 FresnelSchlickRoughness + (1-metallic),
N 采样 irradianceMap(Set2 binding 3)替换常数 ambient;
ambientColor 保留为强度/色调乘子
- CreateNeutral 兜底:无 HDR 资产时 1×1 常数 cube,描述符恒有效
- FaceDir 改为返回单位方向(equirect 查表要求,修掉未归一化的畸变)
2026-09-23 18:50:34 +08:00
atdunbg
4b5990e6c8
feat: 环境背景管线(IBL 阶段①)——HDR 等距柱状转 cube + Skybox pass
...
- Cubemap:stbi_loadf 加载 .hdr,CPU 双线性重采样 6 面(GL 规范方向表),
f32→fp16 转换后整块上传 eCubeCompatible image(R16G16B16A16Sfloat)
- SkyboxPass:HDRColor 的 first writer,承担清屏职责;无环境贴图自动
退化为纯清屏(Forward 不受影响)
- frag 逐像素 NDC 反投影取世界方向(invVP push,投影变换不可线性插值)
- Forward color 附件 Clear→Load:几何合成在天空之上
- SceneRenderer 产出 skyInvVP = inverse(proj × mat4(mat3(view)))
2026-09-23 18:37:01 +08:00
atdunbg
89bf4256e8
feat: 解析式 PBR(Cook-Torrance GGX,metallic-roughness 工作流)
...
- 修 void* 指针算术警告(Texture::InitFromDds)
- Material:slot2 语义切为 metallicRoughness(glTF 约定 G=粗糙度
B=金属度)+ 新增材质因子参数 UBO(binding 4,per-slot ring,
创建时写死,metallic/roughness 因子乘 MR 贴图)
- simple_shader.frag:Blinn-Phong → Cook-Torrance(GGX 分布 +
Smith 几何 + Schlick Fresnel,k=(r+1)²/8 解析光源版);金属不参与
漫反射;环境光暂为常数(IBL 后续)
- Model:读 aiTextureType_UNKNOWN(glTF MR 落点)+ AI_MATKEY_
METALLIC/ROUGHNESS_FACTOR(旧资产缺键退化为电介质 0/0.5);
材质缓存键含因子
- main.cpp:演示场景换回 backpack(旧资产走因子路径验证 PBR 全链路)
- 旧 specular 贴图不再使用(语义被 MR 取代)
2026-09-23 18:01:14 +08:00
atdunbg
2c4efc5165
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
2026-09-23 17:46:25 +08:00
atdunbg
d8c481ce48
fix: Tracy 主线程命名(未命名线程在 GUI 显示 Unknown)
2026-09-23 16:44:55 +08:00
atdunbg
b79df3c60e
fix: tracy 子模块钉到 v0.14.1,与 GUI 协议版本对齐
...
master 开发提交(81c5005)的协议号已偏离 0.14.1 release,
GUI 连接报 incompatible protocol。子模块记录精确 commit hash,
clone --recursive 的机器拿到的一直是锁定的版本
2026-09-23 16:39:06 +08:00
atdunbg
b6982d426f
feat: Tracy profiler 接入(CPU 帧时间线)
...
- vendored tracy 子模块;TRACY_ENABLE 全局生效,宏关闭时零开销
- 插桩:Application::Run FrameMark(帧边界)、Renderer::Render、
SceneRenderer::BuildFrame(ZoneScopedN)+ GPUDriven Collect
(ZoneNamedN——同作用域第二个 zone 不能用 ZoneScopedN,变量名
固定会重声明)、Scene::UpdateTransforms
- 覆盖 CPU 侧关键路径:帧时间线 / 场景收集 / transform 重算 / 录制提交
- 用法:游戏运行时打开 Tracy GUI(release 下载)即自动连接(8086 端口)
2026-09-23 16:10:46 +08:00
atdunbg
7d137fa9b1
refactor: Transform 字段封装 + dirty 标记(对齐 UE USceneComponent 真实现)
...
- 修正上一版"全量暴力重算":UE 实为 dirty 标记 + 惰性计算,前提是
字段私有(SetRelativeLocation 等 setter 标脏 + 子级传播)
- TransformComponent:SRT 字段私有化,Set/Get/World()/IsDirty 访问器;
Set* 变更才标脏;AddRotationY 便捷接口
- Scene::UpdateTransforms 只重算脏实体——静止实体零成本;
层级(父子)传播在脏标记基础上扩展
- 迁移 Camera/SceneRenderer/main.cpp 到封装 API
2026-09-23 15:35:20 +08:00
atdunbg
57ab8901a9
refactor: transform world 矩阵改由帧循环统一重算,删除手动 Compose
...
- Scene::UpdateTransforms():渲染前全量 Compose(UE transform-update
阶段模式),Application::Run 在 FlushDestroyQueue 后调用
- 用户代码永远不需要手动 Compose——Set*/直接写字段均安全;
Compose 降级为引擎内部调用
- 选择全量而非 dirty 标记:字段直接写(t.rotation.y = x)无法可靠
追踪脏,无条件重算零脚枪;万级实体内成本可忽略,更大规模再引入
dirty+封装
- main.cpp/Camera 所有手动 Compose 调用点删除
2026-09-23 15:26:58 +08:00
atdunbg
1bc44e261b
refactor: Camera 位姿统一到 TransformComponent(单一事实源)
...
- Camera 删除内部 position/yaw/pitch 状态:Update 把鼠标旋转与 WASD
移动直接写回实体 Transform(rotation.y=yaw / rotation.x=pitch,
移动基向量由实体旋转推导,有变更才 Compose)
- GetView(transform) = 实体世界矩阵的逆——相机即实体,视图矩阵无
第二来源;Scene::GetPrimaryCamera 可选带出实体 Transform
- 默认朝向约定变化:rotation.y=0 = 看向 -Z(与旧 yaw=-90 等价)
- 消除 CameraComponent 位置与 Transform 脱节的遗留债
2026-09-23 15:14:29 +08:00
atdunbg
019c17c7e7
feat: 实体出生即挂 TransformComponent(UUID + Transform 固有化)
...
- CreateEntity 自动挂 IdComponent(已有)+ TransformComponent(identity),
对齐 UE/Unity 语义(GameObject↔Transform 不可分离 / AActor 必有
RootComponent)——游戏实体的本质是"空间中存在的东西"
- 调用点 AddComponent<Transform> 改 GetComponent(重复 emplace 会断言)
- 遗留不一致记录在案:CameraComponent 位置存于 Camera 内部而非
Transform,后续统一
2026-09-23 15:07:00 +08:00
atdunbg
0ed7b4c5b8
perf: CSM 每级联独立剔除 + 光向 caster pad
...
- 场景剔除从 [主|阴影] 两视图扩展为 [主|级联0|级联1|级联2] 四视图:
每级联只画自己盒内的 batch,消除原先 3× 全量阴影 draw 的浪费
- 实例数组拼接为四段,batch.first 加段基址保持段内连续;
ViewScratch 分桶收集复用容量,稳态零堆分配
- ComputeCascades 沿光方向扩展级联深度范围(pad=30)——切片盒外
caster(高树/城墙)投影进级联的影子不会被剔除裁掉,per-cascade
剔除正确性的前提;只扩 z 不缩 XY,分辨率不受影响
- 遥测 shadow 计数 = 各级联求和
- SunTemple 1056 mesh 全量加载,validation 零警告
2026-09-23 14:59:08 +08:00
atdunbg
c54f60c5ea
feat: 材质系统 v1——4 纹理槽(albedo/normal/specular/emissive)+ 法线贴图
...
- Material:单贴图 → 4 槽(binding=Slot 枚举),MakeCacheKey 组合键
保持材质去重(同贴图组合共享描述符集)
- Model:读取 aiTextureType DIFFUSE/NORMALS/SPECULAR/EMISSIVE 四类路径;
aiProcess_CalcTangentSpace 生成切线(Vertex +tangent 属性,location 3);
每槽默认纹理兜底(白/平法线(128,128,255)/黑/黑,1x1)
- 纹理 sRGB 语义按槽位:颜色图 SRGB 变体,数据图(Normal/Specular)线性
UNORM——Texture 路径加载加 srgb 参数;修复 InitFromPixels 图文 format
不一致的 validation 警告
- UBO 尾部追加 cameraPos(Blinn-Phong V 向量)
- simple_shader.frag:TBN 法线贴图(无切线/平法线退化回几何法线)+
Blinn-Phong 高光(specular 图强度系数)+ 自发光直加
- SunTemple 实测:148 张 DDS 全槽位加载(96 张线性变体)、1056 mesh、
validation 零警告
2026-09-23 14:50:10 +08:00
atdunbg
8253c31ad5
fix: 视锥剔除平面归一化(透视因数误剔)+ 材质去重 + 描述符池可增长
...
- Frustum::FromMatrix 平面归一化:Gribb-Hartmann 提取的 left/right/
bottom/top 法线模长含 1/tan(fov/2) 因子(>1),未归一化时包围球
距离测试被放大,视锥边缘物体被误剔(SunTemple 全场景可见)——
修正注释:必须传 [0,1] 重映射矩阵
- 材质去重:Model 新增 MaterialCache(按贴图路径共享 Material),
Mesh 改持 Material* 非拥有指针。1056 mesh 渲染只需 48 个描述符集
(对齐 UE/Unity 材质实例化思路,大场景第一道闸门)
- DescriptorManager 池改可增长分块(chunk=4096,OutOfPool/Fragmented
自动续块):材质集数量不可预估(1G 资产可能上万),固定上限迟早爆
2026-09-23 14:32:35 +08:00
atdunbg
a0c92af5db
feat: DDS 纹理加载器(BC 压缩直传 + mip 链,参考 Horizon 实现)
...
- Assets::Dds 解析器:中性 DdsFormat 枚举(Assets 层禁 Vulkan 头铁律),
支持 legacy fourcc(DXT1/3/5/ATI1/2)+ DX10 头(BC1..BC7/RGBA8/BGRA8)
+ 未压缩 32bpp + 2D mip 链;数据不解码,直接上传由硬件采样解码
- Texture:按扩展名分发(.dds → InitFromDds);渲染侧负责格式映射与
sRGB 语义(颜色图走 SRGB 变体,BC4/5/6H 数据图保持线性);view/sampler
覆盖完整 mip 链;逐 mip copyBufferToImage(紧凑排布)
- Model::GetOrLoadTexture:FBX/DCC 路径反斜杠归一化(否则 Linux 全挂)
- DescriptorManager 池 1000 → 4096(SunTemple 1056 材质集打爆过;
材质去重属材质系统任务)
- main.cpp 临时挂 SunTemple 场景验证:48 张 DDS 全部加载(2048²、12 mips),
1056 mesh 渲染正常,validation 零警告
2026-09-23 14:21:39 +08:00
atdunbg
0328d4aaeb
feat: CSM 级联阴影(3 级联 × 1024²,实用分割 + 纹素对齐)
...
- SceneRenderer::ComputeCascades:相机视锥实用分割(λ=0.6)→ 反投影
取切片角点 → 光空间 AABB 拟合 → 纹素对齐(消除相机移动时阴影边缘
闪烁)→ [0,1] 深度重映射
- Shadow pass 单 pass 渲 3 个 region,每级联 push 各自光空间 VP
- Forward:UBO lightSpace[3]+cascadeSplits(视图深度选级联),Set2
三张级联图按 binding 0/1/2 采样;vertex 输出 fragViewDepth
- 光源视锥剔除用最远级联(覆盖全阴影范围);双视锥独立剔除铁律保留
- 旧单张 2048 全场景图退役;近处级联分辨率 ~128px/unit(约 2× 提升)
- 编译零错误、validation 零警告、8 秒冒烟通过(10 pass 全活跃)
2026-09-23 13:48:43 +08:00
atdunbg
27b7f8785c
feat: TAA 时域抗锯齿(velocity + 邻域 clamp + 子像素抖动)
...
- Velocity buffer:Forward 第二颜色附件,vertex 计算 clip 空间运动向量
(UBO 尾部追加 projNoJitter/prevView/prevProj;上一帧实例矩阵 SSBO
Set0 binding2,与当前实例数组平行对齐——转动的物体速度正确不鬼影)
- 子像素抖动:SceneRenderer Halton(2,3)×8 序列,抖动只进光栅化投影
- TAA resolve pass:velocity 反推历史位置 + 3×3 邻域 clamp 去鬼影 +
mix(cur,hist,0.9) 时域累积;TAAColor 自引用历史
- RG 历史读补 post-barrier:采样后恢复镜像 resting layout(TAA 的历史
是 ColorAttachment layout,不恢复则下帧 entry oldLayout 脱节)
- 管线:Forward(HDR+Velocity) → TAA(TAAColor) → Bloom/Tonemap 改源 TAAColor
- 编译零错误、validation 零警告、8 秒冒烟通过(10 pass 全活跃)
2026-09-23 13:29:31 +08:00
atdunbg
a29aed2803
feat: Pause Animation 开关(帧历史 diff 冻结验证用)
2026-09-23 13:11:29 +08:00
atdunbg
c75832e73e
feat: RenderGraph 帧历史资源(ReadHistory)+ TemporalDiff 验证 pass
...
- PassBuilder::ReadHistory:读上一帧槽位 ((slot-1+F) mod F) 的物理镜像,
TAA/运动模糊等时域效果的前置能力,RG 最后一个已知边界补齐
- 历史读不建拓扑边(跨帧依赖由同队列提交序保证)、不入本帧状态链、
不改生命周期;剔除照常参与(生产者存活判定)
- 历史 barrier:首帧走 first(old=Undefined),之后走 steady 且
src=ALL_COMMANDS|MEMORY_WRITE 显式闭合跨帧可用性+可见性;
有历史读的资源,常规 entry steady 的 src 同样升级(历史读打破了
同槽位 fence 全等保前提)
- TemporalDiff 调试 pass:|上一帧−当前帧|×增益,静止=黑/运动边缘发光
即链路正确;Tonemap binding2 经 push 开关切调试视图
- 编译零错误、validation 零警告、8 秒冒烟通过(9 pass 全活跃)
2026-09-23 13:05:10 +08:00
atdunbg
0de8498350
feat: 显存分配器迁移到 VMA(P1 路线第一项)
...
- vendored VulkanMemoryAllocator 子模块,唯一实现编译单元 VmaImpl.cpp
- MemoryAllocator 重写为 VMA 后端:接口从"Allocate(reqs)+手绑"升级为
"创建即分配即绑定"(CreateBuffer/CreateImage/Destroy/Flush),
VMA 要求资源与内存成对释放,约束成单一出口
- Buffer/Texture/RenderGraph 三处调用方迁移;staging 持久映射 + 按分配
精确 flush(原来按整块 flush)
- 获得:TLSF 通用分配、DedicatedAllocation 自动启用、memory budget 感知、
内存别名基础(TAA/复用前置)
- 编译零错误、validation 零警告、8 秒冒烟通过
2026-09-23 12:51:11 +08:00
atdunbg
6f10fd624d
chore: gitignore 屏蔽本地 Docs 目录
2026-09-23 12:43:42 +08:00
atdunbg
718a658f5d
refactor: 解耦重构——还清四处架构债(对齐 UE/Unity 分层)
...
- SceneRenderer:场景→渲染数据翻译层(UE FSceneRenderer / Unity CullingResults
模式),收口相机/灯光/光空间矩阵/双视图剔除,Renderer 只编排
- pass 对象化(Unity ScriptableRenderPass 模式):8 个 pass lambda 拆为
Passes::{Shadow,Forward,Bloom,Tonemap,ImGui,Present},BuildGraph 超级函数消失;
SceneGpu/FullscreenGpu 承接共享装配
- 中性 AssetRef(Core 层):ECS 组件不再依赖 Assets 模块(Unity InstanceID 思路)
- IAssetUploader 接口:AssetManager 不感知 Vulkan 具体类,上传服务由渲染层
VulkanAssetUploader 提供
- Renderer 公共 API 不变(App 层零改动),编译零错误 validation 零警告
2026-09-23 12:02:49 +08:00
atdunbg
91880d88fe
fix: tonemap 输出预乘 alpha 匹配 PRE_MULTIPLIED 合成模式 + 调整地面位置
2026-09-23 11:35:05 +08:00
atdunbg
fa9082706b
feat: 双视图视锥剔除(相机/光源各自剔除)
...
- Frustum(Gribb-Hartmann):从 view-proj 行组合提取 6 平面,
包围球相交测试;按 Vulkan [0,1] 深度约定取 near=row2
- Mesh 构造时缓存局部空间包围球(顶点包围盒 → 中心+半径)
- 实例收集重写:单趟遍历,每个 (实体, mesh 部件) 对相机视锥与
光源视锥分别做剔除——相机外实体仍可投影子进视野,Shadow 必须用
光源视锥独立剔除,不能用相机结果
- 实例矩阵数组 = [主视图段 | 阴影视图段],batch.first 全局下标;
两视图共享同一份 ObjectBuffer SSBO
- 聚合改哈希(unordered_map),单趟填充替代原两趟遍历
- 面板显示 instances main/shadow 计数(剔除效果实时可见)
实测:1 背包 80 main / 80 shadow(修复前 shadow=21——near 平面
按 [-1,1] 矩阵误用 [0,1] 公式,光锥近半段被误剔)
2026-09-23 11:21:28 +08:00
atdunbg
df4871a49b
feat: 透明窗口支持 + 退出确认流程 + ImGui 总开关
...
用户自主改进批次:
- 透明窗口:GLFW_TRANSPARENT_FRAMEBUFFER + 窗口 opacity 0.5,
swapchain composite alpha 按能力自适应(Opaque/Pre/PostMultiplied),
Forward 清屏 alpha=0,tonemap 透传 HDR alpha——物体实体、背景透明
- 退出确认:Window 挂 WindowCloseCallback 发事件,App 侧 OnWindowClose
置确认标记,OnRenderOverlay 弹 ImGui 确认框后 Close();
主循环退出条件改为 m_Running(close 事件驱动)
- ImGui 总开关:` 键切换 ImGuiLayer::SetEnabled,禁用时跳过
NewFrame/OnRenderOverlay/BuildDrawData 整段
- 帧率控制简化:去掉 LimitFps 开关,非 vsync 时恒按 target 限帧
(默认 60,可调 ≥24);m_VSync 默认 false(Mailbox 不限速)
- 清理:Model.cpp const 修正,swapchain 日志带 present mode,
GPU 遥测暂时注释
验证:0 error 0 warning,composite alpha 实测选 PreMultiplied(0x2),
present=Mailbox
2026-09-23 10:57:48 +08:00
atdunbg
d8274e8bdc
feat: 帧率控制——手动限帧 + VSync 开关
...
- Application 帧率控制 API:SetLimitFps/SetTargetFps/SetVSync。
限帧目标最低 24fps(防止过低刷新导致交互卡死),无上限;
vsync 开启时 present 自带节奏,手动限帧不生效
- 限帧策略:sleep 到剩 ~2ms 后自旋,精度高且不烧 CPU
- Swapchain 加 VSync 开关:ChoosePresentMode 按开关选
Mailbox(低延迟垂直同步)/ Immediate(不限速可撕裂),
FIFO 兜底;切换经 SetVSync → 重建 swapchain(复用 HandleResize)
- Scene Debug 面板新增 Frame 区块(vsync/limit/目标滑条)
- Run 循环新增 CPU 归属遥测(update/ui/render/total,每 120 帧)
2026-09-22 20:33:10 +08:00
atdunbg
cef32ea1ba
fix: Shadow pass 接入 GPUDriven batch,实例上限提至 16384
...
100 背包掉帧 + 警告刷屏的根因与修复:
1. backpack.obj 有 44 个 mesh 部件,100 实体 × 44 = 4400 实例
打爆 4096 上限 → 每帧截断 + 告警刷屏。上限提至 16384
(1MB/slot),告警改一次性
2. Shadow pass 仍逐实体逐部件画(4400 draw,CPU 提交瓶颈)。
改为与 Forward 共用同一批 batch:Set0 绑 ObjectBuffer,
lightVP 一次 push,44 draw 完成。shadow.vert 经
gl_InstanceIndex 从 SSBO 取模型矩阵
3. 遥测补全:Application::Run 每 120 帧输出 CPU 归属
(update/ui/render/total),Render 输出实例收集耗时——
实测 100 背包 CPU 2.0ms/帧 GPU 0.6ms/帧 ≈ 500fps
2026-09-22 20:17:05 +08:00
atdunbg
6a3fcac072
fix: Shadow pass 接入 GPUDriven batch,实例上限提至 16384
...
100 背包掉帧 + 警告刷屏的根因:
1. backpack.obj 有 44 个 mesh 部件,100 实体 × 44 = 4400 实例
打爆 4096 上限 → 每帧截断 + 告警刷屏。上限提至 16384
(1MB/slot),告警改一次性
2. Shadow pass 仍逐实体逐部件画(4400 draw,CPU 提交瓶颈)。
改为与 Forward 共用同一批 batch:Set0 绑 ObjectBuffer,
lightVP 一次 push,44 draw 完成。shadow.vert 经
gl_InstanceIndex 从 SSBO 取模型矩阵
实测(100 背包):GPU 总耗时 ~5.7ms(Shadow 2.9 + Forward 2.6 +
后处理 0.1),0 警告,帧率受 mailbox 垂直同步 pacing 限制
2026-09-22 20:06:43 +08:00
atdunbg
7fca721a24
feat: GPUDriven 实例化渲染——draw 数与实体数解耦
...
- UniformBuffer ring 支持 eStorageBuffer usage(GPUDriven 实例矩阵
per-frame-slot,正确性保证与 UBO 一致:fence 等待后写入)
- DescriptorManager 加 UpdateStorageBuffer;池补 STORAGE_BUFFER 类型
- Set0 新增 binding1 = 实例矩阵 SSBO(vertex 读取,std430)
- Forward pass 重写:每帧从 ECS 收集实例矩阵(按 mesh 聚合 batch,
两趟遍历保证 batch 区间连续),同 mesh 的 N 个实体合并为
一次 drawIndexed(instanceCount=N),firstInstance 指向 batch 起点;
vertex shader 经 gl_InstanceIndex 取模型矩阵,forward 不再用 push
- draw 数 = 唯一 mesh 数,与实体数量解耦(4096 实例上限,
超出截断告警;聚合改哈希为后续 TODO)
验证:8 pass 全活,validation 0 error 0 warning,GPU Timings 面板
实测各 pass 毫秒,场景渲染与阴影正确
2026-09-22 19:46:17 +08:00
atdunbg
41e4cc85d5
feat: RenderGraph GPU timestamp profiling
...
- RG::SetQueryPool 可选注入;Execute 期每 pass 前后各写一枚
writeTimestamp2(BOTTOM_OF_PIPE),索引按帧槽位分区 + 执行序排布
- 每帧录制开头 reset 本槽位查询区间(上一轮结果已在 fence 等待后读取)
- Renderer 在 WaitFence 后读 64bit 结果换算毫秒(timestampPeriod 缓存),
经 GetPassNames/GetPassGpuMs 透出给 ImGui 面板显示
- 每槽位首帧跳过读取(查询尚未 primed,避免 VUID-09401)
2026-09-22 19:25:42 +08:00
atdunbg
908e688178
feat: ACES tonemap + Bloom 后处理链(Extract/BlurH/BlurV 半分辨率)
...
- ACES(Narkowicz) 经 push 开关启用,exposure 接 ImGui 滑条
- RG: TextureDesc 支持 sizeScale 相对尺寸;per-pass 渲染尺寸解析
(半分辨率 pass 的 viewport 由此决定)
- RG Toposort 重写:RAW+WAR+WAW 按声明序逐资源建边,支持多写者
ping-pong 资源(旧逻辑对 reader 连接所有 writer,ping-pong 成环)
- GetPhysicalView 缺物理镜像时 throw(ENGINE_FATAL 只记日志不中止)
- 全屏 pass 通用 16B push + 公共录制 lambda,Extract/Blur/Tonemap 复用
2026-09-22 19:18:51 +08:00
atdunbg
601fd8997c
feat: 输入隔离——ImGui WantCapture 在 Window 层门控事件与轮询
2026-09-22 19:18:51 +08:00
atdunbg
952ba8135d
feat: HDR 管线 + Tonemap pass,显示变换显式建模
...
管线:Shadow → Forward(写 HDRColor R16G16B16A16F) → Tonemap →
ImGui(loadOp=Load) → Present。对齐 UE/Unity 结构:场景线性值
进 HDR 离屏图,Tonemap(全屏三角,exposure push + gamma 编码)
显式完成显示变换,Backbuffer 只接收显示空间颜色。
- Swapchain 改 B8G8R8A8Unorm:Srgb 附件会硬件二次提亮,UI 泛白
(#4296FA→#8CCBFC);Unorm 下写什么显示什么,编码责任归 Tonemap
- Shader object push range 规则落地:程序级声明——同一 pass 的
全部 shader EXT range 定义必须一致(VUID-08878),layout 同样
按 vertex|fragment 声明,push 调用点覆盖全部声明 stage(VUID-01796)
- Tonemap 装配:Set0 = HDR 图(per-frame-slot 描述符 + GetPhysicalView),
clamp 占位待 ACES 替换,bloom/FXAA 等后处理在 HDR 域插 pass
- CMake 加 imgui_demo.cpp(ShowDemoWindow 链接)
- 修复:m_TonemapDescriptorSets 未 resize 即下标写入(启动即崩)
验证:5 pass 全活,validation 0 error 0 warning,UI 原生色彩无泛白
2026-09-22 19:00:56 +08:00
atdunbg
4fd88248fc
fix: ImGuiLayer 显式启用深色主题(ImGui 默认是灰白 Classic,非深蓝 Dark)
2026-09-22 17:14:08 +08:00
atdunbg
07792c34d7
feat: ImGui 叠加层接入 RenderGraph(docking 分支,dynamic rendering)
...
框架与 UI 的职责边界:
- ImGuiLayer(Engine/ImGui):只做管线桥接——上下文初始化、
NewFrame/BuildDrawData、draw data 录入 cmd;框架自身永不绘制
任何 ImGui 控件,UI 内容全部由派生类在 OnRenderOverlay() 定义
- 每帧顺序:NewFrame → OnRenderOverlay(声明控件)→ BuildDrawData →
Renderer.Render(RG: Forward → ImGui(loadOp=Load 叠加) → Present)
- ImGui pass 常驻 RG,未启用叠加层时空转,无图结构开销
- 后端共存:VK_EXT_shader_object 引擎无 vk::Pipeline,ImGui 用
UseDynamicRendering + PipelineInfoMain.PipelineRenderingCreateInfo
(swapchain 格式),不需要 RenderPass
- 析构序:ImGuiLayer 在 Application 成员序中后声明(先于 Renderer
析构),析构内 waitIdle 保证后端资源安全销毁
App 示例(证明职责边界):Scene Debug 面板实时拖动阴影光方向,
` 键反折叠加层
2026-09-22 17:09:55 +08:00
atdunbg
bc63f76fc1
refactor: 主渲染改为框架固定行为,派生类渲染扩展走 OnRenderOverlay
...
原设计 OnRender() 既承载默认渲染又是虚钩子,派生类一 override
主渲染就丢失(钩子语义与框架行为耦合)。现在 Run() 固定调
Renderer.Render(scene),OnRenderOverlay() 只做叠加层(ImGui/
调试视图/编辑器 UI),不覆写则无叠加层——runtime 零渲染代码,
editor 扩展不破坏主渲染。
2026-09-22 16:44:39 +08:00
atdunbg
07a3b87001
feat: Shadow pass 接入 RenderGraph,支持 SRT 变换与程序化平面
...
阴影(本修正的核心根因):
- Shadow pass 光源正交写深度(2048 D32),Forward 采样比较;
写入与采样共用同一 lightSpace 矩阵,杜绝姿态/镜像不一致
- 修复:push constant range 64B→128B(原 Shadow pass 推 {lightVP,model}
超出 layout 声明范围 = UB,阴影中模型矩阵读到垃圾导致旋转错乱)
- 修复:ShadowFactor 缺少 NDC→UV 映射(*0.5+0.5),采样区域整体错位
- 修复:RG ShaderRead stage 位值直转(eFragment=0x10 在 PipelineStage2
是 TESSELLATION_CONTROL),改为逐位显式映射
- Camera perspective 深度重映射到 Vulkan [0,1](公式与 ortho 不同:
M22=M22*0.5-0.5, M32*=0.5);光源 ortho remap 用 M32=M32*0.5+0.5
引擎配套:
- TransformComponent 重构为 position/rotation/scale + Compose()
- Texture::CreateSolidColor / Model::CreatePlane 程序化资产
(两段式上传公共路径),AssetManager.CreatePlane 带缓存入口
- RG 新增 GetPhysicalView(h, slot):按帧槽位把 RG 资源绑进外部描述符
(阴影图 per-slot 物理镜像各自绑定)
验证:validation 0 error 0 warning,阴影随实体旋转正确
2026-09-22 16:40:54 +08:00
atdunbg
394bfd3d0c
refactor: 实体句柄表皮——实体自己管理组件的 API 形态
...
- 新增 EntityHandle:e.AddComponent<T>() / e.GetComponent<T>() /
e.Destroy() / e.GetUUID(),转发 entt registry,零存储开销
- Scene::CreateEntity 返回 EntityHandle;Scene 层组件接口保留
(给渲染器/系统批量遍历用)
- 语义分层:应用层"实体管组件"(句柄表皮),
数据层组件存储仍集中在 registry(ECS 性能根基)
2026-09-22 13:59:18 +08:00
atdunbg
b73e197783
refactor: ECS 迁移到 entt,移除自研 Registry
...
- Entity = entt::entity(内部自带版本号),Registry = entt::registry
- Scene 对外接口不变(AddComponent/GetComponent/Each/延迟销毁/UUID),
Renderer 与 App 层零改动完成迁移
- Each 转发 entt view(自动最小池遍历),延迟销毁队列保留
- 删除自研 Registry.h/Entity.h
2026-09-22 13:51:48 +08:00
atdunbg
8afdd9b245
feat: 引入 RenderGraph、Application 框架、ECS 与资产句柄系统
...
架构分层(自上而下):
App(SandboxApp) → Application(生命周期+事件) → Scene(ECS) / AssetManager(句柄) → Renderer → RenderGraph → Vulkan 模块
- RenderGraph:声明式帧图。虚拟资源+生成号句柄、死 pass 剔除、
拓扑排序、资源生命周期、barrier 编译期预算(Synchronization2)、
物理镜像池按帧槽位隔离(帧间竞争从根上消除)
- 帧同步修复:per-frame-slot 命令缓冲与 UBO ring(原先单份存在
数据竞争);统一 kMaxFramesInFlight / FrameContext
- Application:生命周期钩子(OnInit/OnUpdate/OnRender/OnShutdown)
+ 事件系统(GLFW 回调 → POD 事件 → 类型化钩子);main 只 new 派生类
- ECS:自研稀疏集 Registry(Entity=(index,generation) 防悬空,
O(1) 增删查,Each 取最小池遍历);Scene 延迟销毁队列;
IdComponent{UUID} 稳定外部身份
- Assets:AssetManager + AssetHandle。组件存句柄不存裸指针/Ref
(单一所有者 + 多使用者),Renderer 删除 LoadModel 改为纯消费
- 修复退出析构:成员析构前 GPU waitIdle(资产层先于 Renderer
析构导致 VUID-00922 资源销毁时仍在使用)
- 引入 entt 子模块备用
validation 全程零错误零警告(RTX 5060 实测)
2026-09-22 13:46:05 +08:00
atdunbg
7d628f8d8a
添加多模型渲染,添加贴图渲染,添加平行光, 暂时不上传assets
2026-09-21 14:07:20 +08:00
atdunbg
381b7c0aa6
feat: 搭建 Vulkan 1.4 渲染器骨架,绘制旋转 3D 立方体
...
使用 Vulkan 1.4 现代路径初始化引擎骨架:
- 用 Shader Object (VK_EXT_shader_object) 替代传统 VkPipeline
- 用 Dynamic Rendering 替代 RenderPass/Framebuffer
- 用 Synchronization2 管理 barrier
核心模块:
- Window:GLFW 封装,GLFW_NO_API 模式,兼容 Wayland
- Log:spdlog 封装
- Types:u32/u64/f32 类型别名
Vulkan 后端:
- Device:Instance、PhysicalDevice、LogicalDevice、Queue 及 feature 查询
- Swapchain:Image、ImageView、DepthBuffer、Recreate
- ShaderManager:SPIR-V 加载与 ShaderEXT 创建
- CommandManager:CommandPool 与主 CommandBuffer
- SyncManager:per-frame Fence 与 ImageAvailable semaphore,per-image RenderFinished semaphore,2 frames in flight
- MemoryAllocator:内存子分配器,256MB block,persistent mapping
- Buffer:VertexBuffer、IndexBuffer、UniformBuffer 封装
- UniformBuffer:每帧上传 MVP 矩阵
- DescriptorManager:DescriptorSetLayout、DescriptorPool、DescriptorSet 及更新
Renderer:
- 协调所有子系统
- 绘制每面不同颜色的旋转 3D 立方体
- 启用 depth test,MVP 矩阵由 GLM 计算
构建:
- CMake 组织 Engine 静态库与 App 可执行文件
- glfw、glm、spdlog 通过 add_subdirectory 引入
2026-09-20 23:09:40 +08:00