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
|
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
|
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
|
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
|
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
|
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
|
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 |
|