后处理、阴影、遮挡与图形辅助库:grpostfx / grshadowmap / grlightprepass / grcustom / rmocclude / softrasterizer / grprofile / video / jpeg / squish / stb
本页覆盖 RAGE 图形层中围绕“完整渲染器”的可选模块与辅助库。阅读这些目录时最重要的事实是:它们在 GTA V 中的地位差别极大——softrasterizer(软件光栅化遮挡剔除)、grprofile(计时条/PIX)、jpeg、squish、stb 被游戏实际链接和调用;而 grpostfx、grshadowmap、grlightprepass、grcustom、rmocclude 是 RAGE 早期为样例/其他项目提供的通用实现,GTA V 的后处理、阴影与遮挡都由游戏层(game/renderer)自行实现。本页先用构建证据划清边界,再按重要度展开。
背景与相关页面#
- 游戏的后处理、延迟光照与级联阴影实现:../11-rendering/deferred-lighting-and-shadows.md、../11-rendering/render-pipeline-and-phases.md。
- 场景扫描与可见性(
fwscene使用本页的 Hi-Z 查询):../04-rage-framework/scene-graph-and-visibility.md;地图数据中的遮挡体(框架层mapdata.h与游戏层MapData.h都引用BoxOccluder/OccludeModel类型src/dev_ng/rage/framework/src/fwscene/mapdata/mapdata.h:19-20、src/dev_ng/game/scene/loader/MapData.h:21):../05-world/map-data-and-lod.md。 sysTask/sysDependency任务系统:../01-runtime/threading-and-render-thread.md。profile(计时条宏与回调槽)与诊断:../02-rage-core/system-and-diagnostics.md;性能/调试工具:../23-debug-security/debug-tools.md。- 视频录制/回放(
rage/framework/src/video):../19-persistence-replay/replay-and-video.md。 - 设备层(硬件遮挡查询、
grcImage):grcore-device-and-effects.md。
相关源码文件#
| 目录 | 关键文件 | 在 GTA V 中的地位 |
|---|---|---|
rage/suite/src/softrasterizer | softrasterizer.h/.cpp、scansetup.h、tiler.h/.cpp、scan.h/.cpp、boxoccluder.h/.cpp、occludeModel.h/.cpp、scanwaterreflection.*、tsklib.*、occluders.psc、*.job/*.frag | 核心,游戏使用 |
rage/base/src/grprofile | timebars.h/.cpp、pix.h、pix_*.cpp、ekg.h/.cpp、drawmanager.h、profiler.h、chart.h、trail.h、stats.h、gcmtrace.h | 游戏使用(调试/性能) |
rage/base/src/jpeg | IJG libjpeg 6b | 经 grcore/image_jpeg.cpp 使用 |
rage/base/src/squish | squish.h、squishspu.h/.cpp、各 fit 实现 | 游戏使用(运行时 DXT 压缩) |
rage/base/src/stb | stb_dxt.h/.cpp | 游戏使用(运行时 DXT 压缩) |
rage/base/src/grpostfx | postfx.h/.cpp、rage_postfx.fx、PS3 edgepost*、*spu.frag | 未进入游戏构建 |
rage/base/src/grshadowmap | cascadedshadowmap.*、charactershadowmap.*、cubeshadowmap.*、spotlightshadowmap.*、cloudshadowmap.*、shadowcollector.*、*.fx、*.psc | 未进入游戏构建 |
rage/base/src/grlightprepass | lightprepass.h/.cpp | 死代码 |
rage/base/src/grcustom | customlighting*.{h,cpp} | 仅样例/工具 |
rage/base/src/rmocclude | occluder*.{h,cpp} | 未进入游戏构建(遗留) |
rage/base/src/video | 仅 makefile.txt 与 vcxproj | 空壳;实现在 rage/framework/src/video |
1. 构建边界:哪些模块被游戏链接#
| 证据 | 内容 |
|---|---|
| 游戏解决方案 | RageMisc 与 RageGraphics 等 RAGE 工程被列入 src/dev_ng/game/VS_Project_NM/game.slndef:28、src/dev_ng/game/VS_Project_NM/game.slndef:40-50;其中没有 RageGraphics2 |
RageGraphics | 包含 grprofile、jpeg(以及 grcore/grmodel/rmcore 等)src/dev_ng/rage/base/src/vcproj/RageGraphics/RageGraphics.txt:7-22 |
RageGraphics2 | 只含 grshadowmap、rmocclude、text,不在游戏解决方案中 src/dev_ng/rage/base/src/vcproj/RageGraphics2/RageGraphics2.txt:1-11 |
RageMisc | 包含 squish、stb、softrasterizer(及 scaleform、bink、fragment、rmptfx 等)src/dev_ng/game/VS_Project/RageMisc/ragemisc.txt:23-44 |
| 失效的 makefile | grpostfx/makefile.txt.dead、grshadowmap/makefile.txt.dead、rmocclude/makefile.txt.dead(文件名本身表明已退役);grlightprepass 没有任何工程/makefile |
引用侧佐证(#include "<dir>/ 检索):grpostfx/ 只被 rage/suite/samples/*、suite/src/shadercontrollers、rageShaderViewer 与 grcore/device_d3d11.cpp 包含,而后者只有 #include 与一行被注释的 PARAM_nopostfx 检查 src/dev_ng/rage/base/src/grcore/device_d3d11.cpp:72、src/dev_ng/rage/base/src/grcore/device_d3d11.cpp:2549;grshadowmap/ 只被 suite/src/rmlighting、suite/src/manylights 与样例包含;rmocclude/ 只被自身与 base/samples/sample_rmocclude 包含;grlightprepass/ 无任何包含者;grcustom/ 只被 rageShaderViewer 与 sample_grcore 包含。相反,softrasterizer/ 被 game/renderer/occlusion.*、game/scene/loader/MapData.h、game/Vehicles/Vehicle.cpp、fwscene/scan/*、fwscene/mapdata/mapdata.h 等包含(见 §2.6)。
2. softrasterizer:软件光栅化 Hi-Z 遮挡剔除(游戏核心)#
2.1 解决的问题#
在 CPU/SPU 上把少量“遮挡体”(地图中摆放的盒子与简化网格,以及水面)光栅化成一张很小的深度图,再生成分层 Z(Hi-Z);随后场景扫描对每个实体/批次的屏幕空间包围盒做保守查询,提前剔除被遮挡对象,避免把它们送进 drawlist。整套流程以 sysTask 依赖图并行执行。
2.2 固定分辨率与缓冲尺寸#
| 宏 | 值 | 说明 |
|---|---|---|
RAST_NUM_TILERS_ACTIVE | 4 | 并行 tiler(分桶)任务数 |
MAX_TILER_TRIS | 384+64 = 448(4 tiler 时) | 每 tiler 可容纳三角形 |
RAST_NUM_TILES_WIDE × HIGH | 4 × 3 = 12 | 屏幕分块,每块一个 scan 任务 |
RAST_BLOCK_WIDTH/HEIGHT | 8 / 6(因 TILES_HIGH == 3) | 每块的 4×4 像素块数 |
RAST_TILE_WIDTH/HEIGHT | 32 / 24 | 每块“单元”尺寸 |
RAST_SCREEN_WIDTH/HEIGHT | 128 × 72(编译期断言) | Z 缓冲单元网格 |
RAST_SCREEN_*_PIXELS | 256 × 144 | 等效像素分辨率 |
RAST_HIZ_WIDTH/HEIGHT | 64 × 36(2304 个 Vec4V,36864 B) | Hi-Z 缓冲 |
RAST_STENCIL_SIZE_VEC | 72 + 4 = 76 | 模板(水面)缓冲 |
证据:src/dev_ng/rage/suite/src/softrasterizer/scansetup.h:13-75。注释与代码不一致:行尾注释仍按“4×2 块、每块 36 高”书写(例如 // 9*4 = 36、// 36*2 = 72),但当前 RAST_NUM_TILES_HIGH = 3 使 RAST_BLOCK_HEIGHT = 6、RAST_TILE_HEIGHT = 24;屏幕总高仍为 72,两种配置在总尺寸上等价,读代码时应以宏为准。
2.3 遮挡体数据#
| 类型 | 布局 / 职责 | 证据 |
|---|---|---|
BoxOccluder | 16 字节压缩 OBB:中心 xyz、cos/sin 绕 Z 旋转、长宽高,全部 s16 且以 0.25 m 为单位;CalculateVerts 展开 8 顶点;Empty() 放在 z = -1000 | src/dev_ng/rage/suite/src/softrasterizer/boxoccluder.h:38-87 |
CBoxOccluderBucket / COccludeModelBucket | 指向一个 mapdata 槽中的遮挡体数组(pArray/pElements/count/mapDataSlotIndex),16 字节对齐以便 DMA | src/dev_ng/rage/suite/src/softrasterizer/boxoccluder.h:28-36、src/dev_ng/rage/suite/src/softrasterizer/occludeModel.h:53-61 |
OccludeModel | 任意简化网格:AABB、打包顶点(VFMT_11_11_10 4 B/顶点 或 VFMT_F32)+ u8 索引;MaxIndexedVerts = 256、MaxWaterOccluders = 64;FLAG_WATER_ONLY | src/dev_ng/rage/suite/src/softrasterizer/occludeModel.h:63-110 |
| 容量 | MAX_NUM_BOX_OCCLUDERS 4000、MAX_NUM_BOX_OCCLUDERS_RASTERIZED 512、MAX_NUM_OCCLUDE_MODELS 416 | src/dev_ng/rage/suite/src/softrasterizer/boxoccluder.h:15-16、src/dev_ng/rage/suite/src/softrasterizer/occludeModel.h:15 |
| parser 反射 | occluders.psc 把两者声明为 simple 结构(地图数据中直接序列化) | src/dev_ng/rage/suite/src/softrasterizer/occluders.psc:1-27 |
2.4 运行时结构#
rstTransformToScreenSpace:裁剪平面、合成矩阵、相机位置、屏幕范围(w分量存深度缩放),由grcViewport构造src/dev_ng/rage/suite/src/softrasterizer/tiler.h:34-47。rstFastTiler:一个 tiler 的三角形缓冲(PreTri2边方程C/DX/DY/minMax)与每块索引表、计数表m_cntTable[12*2](大三角/小三角两组)src/dev_ng/rage/suite/src/softrasterizer/tiler.h:57-110、src/dev_ng/rage/suite/src/softrasterizer/scan.h:32-55。rstTileList持有 4 个 tiler 和一个水面 tilersrc/dev_ng/rage/suite/src/softrasterizer/softrasterizer.h:33-58。ScratchPadAllocator<Alloc>:每帧线性分配器,16 字节对齐,End()时检查溢出;BANK 下可把指定对象改为静态分配以便调试显示src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.h:61-205。游戏每帧用它为每个遮挡阶段分配rstTileList与水面遮挡缓冲src/dev_ng/game/renderer/occlusion.cpp:961-979。SoftRasterizer : datBase:持有 Z/Hi-Z/模板缓冲、变换、每 tiler 的盒/模型分包TileDataPacket<T>、阴影方块、水面遮挡输出;以及两套任务表示——sysDependency数组和DependantTaskList(m_useSysDependencyTasks选择);支持父子 rasterizer 共享 tilersrc/dev_ng/rage/suite/src/softrasterizer/softrasterizer.h:560-748。构造函数把m_useSysDependencyTasks固定为false(无公开 setter),因此运行路径是DependantTaskList/sysTask版本src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.cpp:283-333。
2.5 每帧流程与任务图#
游戏侧(COcclusion,见 ../11-rendering/render-pipeline-and-phases.md)对每个遮挡阶段调用:BeginSubmit(&vp) → SelectAndRasterizeBoxOccluders(...) → SelectAndRasterizeModelOccluders(...) →(主阶段且启用时)PrepareSubmitGenerateWaterTris(...) → EndSubmit(NULL, false) src/dev_ng/game/renderer/occlusion.cpp:654-677。
图中证据:BeginSubmit src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.cpp:350-359;选择任务的参数(PS3 scratch 48 KB,其他 32 KB)src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.cpp:724-812;boxselector 选出最多 512 个盒、按屏幕面积降序排序(打包值低 16 位为索引),再按排序后序号轮转分给 4 个 tiler 以平衡负载,并用 BoxOccluder::Empty() 填充对齐 src/dev_ng/rage/suite/src/softrasterizer/boxoccluder.cpp:365-448;tiler 任务 boxoccluder 读入本 tiler 的盒与模型分包并 AddIndexedTriList src/dev_ng/rage/suite/src/softrasterizer/boxoccluder.cpp:254-348、src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.cpp:843-870;依赖装配(tiler 依赖两个 selector,scan 依赖 tiler,水面三角与模板任务插入,父 rasterizer 等子 rasterizer 发射后才 scan)src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.cpp:483-593;12 个 scan 任务按 3 行 × 4 列创建,每块写入 zbuffer + index*TILE_W*TILE_H src/dev_ng/rage/suite/src/softrasterizer/tiler.cpp:1856-1903;模板与水面任务 src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.cpp:714-721、src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.cpp:873-967。
补充:
- 父子 rasterizer:
DependsOn(parent)让一个 rasterizer 复用父对象的 tiler;子对象的 tiler 任务要等父对象 scan 结束,父对象的 scan 依赖计数 +1 直到子对象发射(RemoveChildDependancy)src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.h:630-639、src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.cpp:490-564。这表明游戏的多个遮挡阶段(例如主视图与级联阴影)可以串联共享中间缓冲(推断;阶段划分在游戏层)。 - 若没有 selector 任务被设置(“简单情形”),
EndSubmit直接创建 scan 任务并可选perfWait等待src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.cpp:565-590。游戏在非_USE_DEPENDANT_TASKS_RASTERIZER时退化为主线程逐盒RasterizeModelsrc/dev_ng/game/renderer/occlusion.cpp:678-705。 - 每个任务入口都有
.job/.frag包装,供 PS3 SPU 以作业/片段形式运行;PC/主机上以sysTask在工作线程运行(TASK_INTERFACE(...))。
2.6 查询接口与使用者#
Hi-Z 的生成与比较语义:每个 scan 任务把本块三角形扫描进 Z 缓冲,随后 GenerateHiZTile 对相邻 Z 样本做 Min 归约写入 Hi-Z(Hi-Z 分辨率为 Z 缓冲的一半),同时累计本块的“最近深度”(对各 Hi-Z 值取 Max 后求倒数写入 nearZVal)与有效覆盖范围 minMaxBounds(供查询方做平凡接受)src/dev_ng/rage/suite/src/softrasterizer/scan.cpp:664-700、src/dev_ng/rage/suite/src/softrasterizer/scan.cpp:725-756、src/dev_ng/rage/suite/src/softrasterizer/scan.cpp:1476-1485。查询侧 rstScanQueryHiZLargeApprox 取对象屏幕包围盒最近深度的倒数 1/scmin.z,把矩形钳制到 64×36 的 Hi-Z 网格后以 2×2 单元步进,只要任一 Hi-Z 值小于 1/scmin.z 就判“可见”;每行开始前检查已有结果以提前退出——注释记录该早退在 360 上使 TestOcclusion 提速约 35–45% src/dev_ng/rage/suite/src/softrasterizer/scan.h:143-242。这表明缓冲中保存的是深度倒数(越大越近),Hi-Z 的 Min 即“最远遮挡深度”,因而测试是保守的(推断:依据是 Invert/Min 的使用方式,未追踪顶点变换中的深度定义)。
| 函数 | 作用 | 证据 |
|---|---|---|
rstCalculateScreenSpaceBound(IsVis) | 用 SoA 一次变换 AABB 的 8 个角,齐次裁剪、透视除法得到屏幕空间 min/max(含深度);IsVis 版本先做全外裁剪拒绝,并处理 w<0 | src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.h:280-416 |
rstScanQueryHiZLarge(Approx) | 屏幕矩形 vs Hi-Z 的保守可见性测试 | src/dev_ng/rage/suite/src/softrasterizer/scan.h:143-245 |
rstTestAABBExactEdgeList / rstTestOOBBExactEdgeList / rstTestModelExact / rstTestAABBExact | 精确边表测试(返回可见面积),支持正交投影(阴影) | src/dev_ng/rage/suite/src/softrasterizer/tiler.h:302-314 |
rstCalculateOcclusion / rstCalculateOcclusionAABBExactEdgeList | 批量 AABB 查询,写结果位 | src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.h:750-765 |
使用者:fwscene 扫描在 ScanEntities.cpp 中直接 #include "softrasterizer/scan.cpp"(把实现编进扫描作业),对实体包围盒调用 rstTestAABBExactEdgeList(级联阴影阶段用正交模式)与 rstScanQueryHiZLargeApprox(注释称其结果与 rstScanQueryHiZLarge 极接近且有提前退出)src/dev_ng/rage/framework/src/fwscene/scan/ScanEntities.cpp:55、src/dev_ng/rage/framework/src/fwscene/scan/ScanEntities.cpp:1367、src/dev_ng/rage/framework/src/fwscene/scan/ScanEntities.cpp:1415-1420;游戏 COcclusion 暴露 GetHiZBuffer(phase) 并用 rstTestModelExact 测试二十面体/圆锥等体积(例如灯光体积)src/dev_ng/game/renderer/occlusion.cpp:475-476、src/dev_ng/game/renderer/occlusion.cpp:758-760。扫描与可见性的完整流程见 ../04-rage-framework/scene-graph-and-visibility.md。
2.7 约束与边界#
- 分辨率、tiler 数、每 tiler 三角形数均为编译期常量;超出
MAX_TILER_TRIS的输入由IsFull判定(调用方需处理)src/dev_ng/rage/suite/src/softrasterizer/tiler.h:72-75。 - 每帧最多光栅化 512 个盒遮挡体;超出部分被选择任务丢弃(按面积排序后截断)。
- 遮挡结果是保守的:查询失败只会导致多画,不会错误剔除(这是 Hi-Z 测试的设计意图;具体阈值如
THRESHOLD_PIXELS_SIMPLE_TEST在 BANK 下可调)。 __RASTERSTATS(非 FINAL、非 SPU)启用统计计时器src/dev_ng/rage/suite/src/softrasterizer/scansetup.h:13;BANK 下可把 Hi-Z/模板拷贝到grcTexture调试显示(256×144 L8)src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.cpp:289-298。
3. 硬件遮挡/条件渲染查询(grcore)#
与软件 Hi-Z 并存,grcDevice 暴露 GPU 遮挡查询与条件渲染:CreateOcclusionQuery(Xenon 下需考虑平铺)、Begin/EndOcclusionQuery、GetOcclusionQueryData(返回通过深度测试的像素数),以及 Create/Begin/EndConditionalQuery、Begin/EndConditionalRender src/dev_ng/rage/base/src/grcore/device.h:2469-2505。D3D11 实现直接映射到 D3D11_QUERY_OCCLUSION,GetData 非阻塞,未就绪返回 false src/dev_ng/rage/base/src/grcore/device_d3d11.cpp:6429-6472。游戏在何处使用(例如镜头光晕/日光可见性)由 ../11-rendering/render-pipeline-and-phases.md 说明。
4. rmocclude:遗留的几何遮挡系统(未链接)#
rmOccluderSystem(注释强调“不是单例”)基于多面体/多边形遮挡体(rmOccludePolyhedron、rmOccludePoly、rmOccludeFacet/Edge)、span buffer 与 PVS 视图,提供 LoadDataset、StartNewFrame/EndFrame、IsSphereOccluded、IsSphereSpanBufferOccluded、IsHotDogOccluded 等 src/dev_ng/rage/base/src/rmocclude/occluder.h:278-600。大量文件是空壳或整体禁用:occluder_hom.h 用 #if 0 包裹全部内容 src/dev_ng/rage/base/src/rmocclude/occluder_hom.h:6-8,occluder_umbra.h、occluder_vu0.h(PS2 VU0)、occluder_fusion.h 只剩 include 守卫。它属于 RageGraphics2,不进入游戏构建(§1)。GTA V 的遮挡完全由 §2 的 softrasterizer 承担。
5. grpostfx:RAGE 通用后处理管线(未链接)#
- 设计:
grPostFX : datBase管理后处理 RT、着色器与预设(grcPPPPreset:DOF、bright-pass、bloom、色调映射等参数),Process()执行已注册的效果,BeginFrame()、CreateRenderTargets(w,h);效果插件基类grPostFXEffect { virtual Process(grPostFX*) },内置None/Edge/ToneMapping/ToneMappingDepthOfField/...GaussFog/Fog等src/dev_ng/rage/base/src/grpostfx/postfx.h:129-200、src/dev_ng/rage/base/src/grpostfx/postfx.h:861-961。编译开关(Kawase streak、blue shift、MC4 运动模糊等)全为 0src/dev_ng/rage/base/src/grpostfx/postfx_cfg.h:1-8。 - PS3:
edgepost_task.cpp与一组*spu.frag(bloom capture、DOF、下采样、高斯、ILR、运动模糊、ROP、上采样)把后处理卸载到 SPU(基于edge/post的预编译程序);旧 makefile 列出了这些文件与嵌入式着色器src/dev_ng/rage/base/src/grpostfx/makefile.txt.dead:1-41。 - 目录附带 HDR、gamma、PPP 使用指南等文档(
Doc/)。 - GTA V 的后处理在
game/renderer/PostProcessFX*与game/shader_source/PostFX,见 ../11-rendering/deferred-lighting-and-shadows.md。
6. grshadowmap:RAGE 通用阴影图(未链接)#
| 类 | 职责 | 证据 |
|---|---|---|
CShadowMap + CShadowMapTile | 级联(瓦片)阴影图;平台默认尺寸 PC/PS3 640²、Xenon 800²;mip 级 8;瓦片参数(近/远切片、深度缩放、偏移、斜率偏移、FOV 除数)可由 .psc 加载 | src/dev_ng/rage/base/src/grshadowmap/cascadedshadowmap.h:39-60、src/dev_ng/rage/base/src/grshadowmap/cascadedshadowmap.h:137-175、src/dev_ng/rage/base/src/grshadowmap/cascadedshadowmap.psc:8-25 |
CCascadedShadowCulling | 级联的光空间视锥平面裁剪 | src/dev_ng/rage/base/src/grshadowmap/cascadedshadowmapculling.h:21-85 |
CCharacterShadowMap、CCubeShadowMap/CShadowedPointLight、CShadowedSpotLight/CShadowCache、CloudShadowMap、CShadowCollector | 角色专用阴影、点光立方阴影、聚光阴影与缓存、云影、屏幕空间阴影收集 | src/dev_ng/rage/base/src/grshadowmap/charactershadowmap.h:55-137、src/dev_ng/rage/base/src/grshadowmap/cubeshadowmap.h:42-85、src/dev_ng/rage/base/src/grshadowmap/spotlightshadowmap.h:29-159、src/dev_ng/rage/base/src/grshadowmap/cloudshadowmap.h:15-36、src/dev_ng/rage/base/src/grshadowmap/shadowcollector.h:32 |
不一致:CShadowMap 构造注释写“The maximum # is 4”,而 CShadowMapTile::MAX_TILES = 8 src/dev_ng/rage/base/src/grshadowmap/cascadedshadowmap.h:58、src/dev_ng/rage/base/src/grshadowmap/cascadedshadowmap.h:140-146;由于模块不在游戏构建中,未进一步核实实现取哪一个。GTA V 自己的级联阴影(CRenderPhaseCascadeShadows、wdcascade technique group)见 ../11-rendering/deferred-lighting-and-shadows.md;共享 HLSL 阴影头(rage_shadow*.fxh、rage_shadow_config.h)在 shaderlib 中,与本目录的 .fx 不同。
7. grlightprepass:死代码#
头文件守卫与注释仍是 sagrender/lightprepass.h,依赖 lighting/spotlight.h 与 sagSpotLight 类型;renLightPrePassLightsMgr 提供 light pre-pass(先渲染光照累积再主颜色 pass)的点/方向/聚光灯绘制与裁剪矩形计算,PS3/360 专用的 Hi-Stencil 与深度边界辅助 src/dev_ng/rage/base/src/grlightprepass/lightprepass.h:1-100。目录中没有 makefile/工程,也没有任何代码包含它(§1)。这表明它是从其他项目(“sag” 前缀)复制来的参考实现,未在 RAGE 当前树中维护(推断,依据:命名与缺失的构建入口)。
8. grcustom:可切换光照模型(样例/工具)#
grcCustomLightImplementation 是光照模型插件基类:构造时自动向管理器注册,Register() 在着色器加载前调用(用于注册 technique group),SetLightingGroup(const grcLightGroup&) 实现具体光照模型;grcCustomLighting 管理所有实现并按名切换,SafeInitImplementations 把最后一个初始化成功的设为默认 src/dev_ng/rage/base/src/grcustom/customlighting.h:22-110。具体实现有 grcRageLightImplementation、grcGtaLightImplementation、grcMp3LightImplementation、grcRdr2LightImplementation(各项目的光照约定)src/dev_ng/rage/base/src/grcustom/customlighting_gta.h:19、src/dev_ng/rage/base/src/grcustom/makefile.txt:1-13。使用者是 rageShaderViewer 与 sample_grcore(例如 src/dev_ng/rage/base/samples/sample_grcore/sample_grcore.cpp:27),用于在工具中用接近游戏的光照预览 shader。
9. grprofile:计时条、PIX 标记与 pfDraw#
9.1 计时条(timebars)#
- 动态装配:
profile/timebars.h中的PF_START_TIMEBAR/PF_PUSH_TIMEBAR/PF_POP_TIMEBAR/PF_AUTO_PUSH_TIMEBAR只是调用pfTimebarFuncs::g_StartCb/g_PushCb/g_PopCb函数指针src/dev_ng/rage/base/src/profile/timebars.h:36-85,默认是空操作src/dev_ng/rage/base/src/profile/timebars.cpp:39-41;grprofile的pfTimeBarMgr::Init把它们替换为grProfileCallbacks::Start/Push/Pop等实际实现src/dev_ng/rage/base/src/grprofile/timebars.cpp:2102-2115。因此底层模块(如grcore)可以无依赖地打计时条,而图形化显示由grprofile提供。 - 启用条件
RAGE_TIMEBARS = (!__FINAL || __FINAL_LOGGING) && !__PROFILE && !__TOOL;PC/主机最多 10 组计时条集合(其他 5);5 重缓冲;函数栈深 15;平均值平滑系数 0.95;DEV/BANK 才包含 detail 计时条src/dev_ng/rage/base/src/grprofile/timebars.h:17-47。 - 预定义分桶
eTIMEBAR_BUCKET:流式、人口、动画、人物/物体/载具更新、物理、脚本、渲染更新、可见性、构建 drawlist、GBuffer、阴影、反射、SSAO、方向/环境光、透明、VFX、SSA、PostFXsrc/dev_ng/rage/base/src/grprofile/timebars.h:52-77——这份清单本身就是 GTA V 帧预算的分类。 pfTimeBars每条记录名称、起止时间、预算、父子/兄弟链、超预算/空闲/detail 标志、层与桶src/dev_ng/rage/base/src/grprofile/timebars.h:84-108;pfTimeBarMgr提供启动条/GPU 条、FrameInit/FrameEnd、Start/Push/Pop、超预算跟踪src/dev_ng/rage/base/src/grprofile/timebars.h:333-360。
9.2 PIX 与其他#
PIXBegin/PIXBeginN/PIXEnd/PIXIsGPUCapturing(Cached)按 Xenon/PC/Durango、GCM、Orbis 分别实现(pix_pc.cpp/pix_gcm.cpp/pix_gnm.cpp);PIXBeginFrame每帧刷新“是否在 GPU 捕获”的缓存src/dev_ng/rage/base/src/grprofile/pix.h:13-80。grcore 用这一缓存决定是否为每个 pass 打详细标签(见 grcore-device-and-effects.md)。pfEKGLog等(__STATS)绘制滚动曲线(每日志 300 个采样)src/dev_ng/rage/base/src/grprofile/ekg.h:19-50;pfDrawManager/pfDrawGroup/pfDrawItem与PFD_DECLARE_*宏声明可在 RAG 中开关的调试绘制项src/dev_ng/rage/base/src/grprofile/drawmanager.h:36-57(rmcDrawable::ProfileDraw即在__PFDRAW下使用);pfProfileRenderer/pfStatsView、pfChart、pfTrail、pfStatsManager、PS3pfGcmTrace构成其余的屏显与追踪工具。- GPU 计时(
grcGpuTimer)在grcore/gputimer.*,见 grcore-device-and-effects.md。
10. video:空壳目录#
rage/base/src/video 只有 makefile.txt、vcxproj 与 guid;makefile 与工程列出的 mediaencoder_buffer*、mediaencoder_params、mediaencoder_win 源文件不在该目录中 src/dev_ng/rage/base/src/video/makefile.txt:1-14。游戏代码 #include "video/..." 实际解析到 rage/framework/src/video(媒体编码/解码、录制接口、VideoPlayback、PS4 内容导出等)。该模块属于视频录制/回放主题,见 ../19-persistence-replay/replay-and-video.md。
11. jpeg:IJG libjpeg 6b#
第三方 Independent JPEG Group 库,版本字符串 6b 27-Mar-1998(jversion.h),文件改为 .cpp 编译;makefile 只收录编解码核心(jc*/jd*/jf*/ji*/jm*/jq*/jutils)而不含命令行工具(cjpeg/djpeg/...)src/dev_ng/rage/base/src/jpeg/makefile.txt:1-63。唯一使用者是 grcore/image_jpeg.cpp(grcImage::LoadJPEG/SaveJPEG、LoadJPEGToRGBA8Surface/DXT1Surface,截图与照片/头像纹理),见 grcore-device-and-effects.md。
12. squish:libsquish DXT 压缩 + 任务化包装#
- 第三方 libsquish(Simon Brown,MIT 许可头),API 标志:
kDxt1/3/5、kColourIterativeClusterFit(最慢最好)、kColourClusterFit(默认)、kColourRangeFit(快)、感知/均匀误差度量、按 alpha 加权src/dev_ng/rage/base/src/squish/squish.h:39-67。 - Rockstar 包装
sqCompressState:把grcTexture→ DXT 纹理(或多级 mip)的压缩拆成多个“切片”任务(sysTaskManager),调用方每帧Poll()推进或Wait()阻塞;状态对象必须存活到完成,析构时断言未等待src/dev_ng/rage/base/src/squish/squishspu.h:21-82。Xenon 改用 VMX 快速压缩并边压缩边去平铺,SQUISH_USE_STB_COMPRESSION关闭src/dev_ng/rage/base/src/squish/squishspu.h:84-87。 - 游戏使用者:人物头像(
PedHeadshotManager)与人物伤害贴图(PedDamage)以kColourIterativeClusterFit压缩运行时生成的纹理src/dev_ng/game/Peds/rendering/PedHeadshotManager.cpp:995-996、src/dev_ng/game/Peds/rendering/PedDamage.cpp:5061-5062;MeshBlendManager.h也包含该头;工具侧fwtextureconversion与 ragebuilder 纹理转换使用它。
13. stb:stb_dxt v1.04#
单头文件 DXT1/DXT5 压缩器(原作者 ryg,public domain),STB_DXT_HIGHQUAL 做两次细化;stb_dxt.cpp 只负责定义 STB_DXT_IMPLEMENTATION 生成实现 src/dev_ng/rage/base/src/stb/stb_dxt.h:1-30、src/dev_ng/rage/base/src/stb/stb_dxt.cpp:1-7。游戏在三处用它逐 4×4 块压缩:MeshBlendManager(人物头部混合纹理)src/dev_ng/game/renderer/MeshBlendManager.cpp:4822、PedHeadshotManager src/dev_ng/game/Peds/rendering/PedHeadshotManager.cpp:227、DownloadableTextureManager(可下载纹理,如云端/社交图片)src/dev_ng/game/scene/DownloadableTextureManager.cpp:157。头部混合细节见 ../06-peds/ped-motion-and-rendering.md。
约束与边界行为(汇总)#
- 不要把
grpostfx/grshadowmap/rmocclude/grlightprepass当作 GTA V 的实现来读:它们不在游戏解决方案或无任何包含者;游戏有自己的后处理、阴影与遮挡。 - 软件遮挡的分辨率与任务并行度是编译期常量(128×72 单元 / 64×36 Hi-Z / 4 tiler / 12 scan),注释中的旧数值(2 行瓦片)已过时。
- 遮挡体选择有硬上限(每帧 512 个盒,网格 416),按屏幕面积排序截断。
sqCompressState生命周期必须覆盖整个异步压缩过程;运行时 DXT 压缩在主机上走任务系统,结果写入调用者提供的 DXT 纹理(其格式优先于 flags)。- 计时条宏在 FINAL(无
__FINAL_LOGGING)、PROFILE 与工具构建中为空;在pfTimeBarMgr::Init之前调用只是空操作。
未决问题 / 证据不足#
scan.cpp(87 KB)与tiler.cpp(82 KB)的光栅化内核(边方程增量、大/小三角形分流、Hi-Z 生成)只做了接口级阅读;水面模板(scanwaterreflection.*、stencilwriter)细节未展开。COcclusion的阶段划分(主视图、级联阴影、水面反射等)与阈值调优属于游戏层,未在本页核实。grpostfx、grshadowmap、grcustom只做了结构级盘点,未阅读实现;它们是否在其他 RAGE 工具(如rageShaderViewer)中仍可用未验证。grprofile中profiler.cpp、stats.cpp、trail.cpp的具体屏显逻辑未展开。