视野计算系统
目录
简介
本文件系统化梳理 Cataclysm-DDA 的视野与光照计算体系,重点覆盖以下方面:
- Bresenham 光线投射与阴影投射算法在可见性判定中的应用
- 3D 视野遮挡检测(含地板/屋顶影响)与可见性缓存机制
- visibility_variables 变量系统、apparent_light_at 光照计算与 get_visibility 可见性判断
- 不同光源类型(太阳光、实体光源、角色/怪物光源、车辆光源等)的处理流程
- 动态遮挡物与视野范围限制策略
- 视野优化技巧、性能分析方法与常见视觉效果实现
- 算法示例与调试工具使用指南
项目结构
视野与光照系统主要由以下模块构成:
- 阴影投射与可见性:src/shadowcasting.*(3D 视野扫描、透明度累积、四象限光照)
- 光照图生成:src/lightmap.*(太阳光缓存、光源叠加、最终光照等级)
- 地图接口与缓存:src/map.*(透明度缓存、可见性缓存、apparent_light 计算)
- 测试用例:tests/vision_test.cpp、tests/shadowcasting_test.cpp(功能验证与性能基准)
图表来源
- shadowcasting.cpp
- lightmap.cpp
- map.cpp
- vision_test.cpp
- shadowcasting_test.cpp
章节来源
- shadowcasting.cpp
- lightmap.cpp
- map.cpp
- vision_test.cpp
- shadowcasting_test.cpp
核心组件
- 四象限光照模型:用于记录从四个方向(东北、东南、西南、西北)到达的光照强度,支持墙角等复杂视角下的光照合成。
- 3D 视野扫描器:基于水平/垂直扇形的 span 切片与斜率比较,逐距离推进并按透明度累积衰减,同时处理地板/屋顶遮挡。
- 透明度缓存:按子图块批量构建,考虑地形/家具/场地上透明度与天气视距惩罚。
- 光照图生成:自上而下累加太阳光,叠加角色/NPC/车辆/物品光源,并应用局部覆盖与方向性光照。
- apparent_light 计算:结合可见性缓存、相机缓存、邻域可见性与四象限光照,综合得出“表观亮度”。
章节来源
- shadowcasting.h
- shadowcasting.cpp
- lightmap.cpp
- lightmap.cpp
- lightmap.cpp
架构总览
视野与光照的端到端流程如下:
图表来源
- lightmap.cpp
- shadowcasting.cpp
- lightmap.cpp
详细组件分析
Bresenham 光线投射与可见性判定
- 在测试中对比了旧版 Bresenham 可见性检查与新阴影投射算法的一致性,确保两者在典型场景下结果一致或可解释差异。
- Bresenham 路径上的每个格点若遇到不透明则阻断,否则路径可达;该方法用于验证阴影投射的正确性。
图表来源
- shadowcasting_test.cpp
章节来源
- shadowcasting_test.cpp
3D 阴影投射与遮挡检测
- 水平/垂直扇区扫描:通过主/次斜率界定当前行/列的可视区间,按距离推进并累积透明度衰减。
- 地板/屋顶遮挡:当目标格点位于玩家上下方时,若对应层存在地板/屋顶,则视为不可见(或以不透明处理),避免“看到天花板/地板下方”的异常。
- span 分割:当透明度发生变化时,将当前 span 切分为最多四段,分别处理已处理/当前行剩余/未处理区域,防止漏检或重复处理。
图表来源
- shadowcasting.cpp
- shadowcasting.cpp
章节来源
- shadowcasting.cpp
- shadowcasting.cpp
visibility_variables 变量系统与 apparent_light_at
- visibility_variables 缓存:地图维护多层透明度、可见性与相机缓存,按需重建与失效。
- apparent_light_at:综合玩家位置、未受损视野距离、绝对可见性与相机可见性、邻域可见性与四象限光照,得到表观亮度;对不透明目标采用邻域四象限合成,对透明目标采用全向合成。
- 遮挡判断:当目标或其邻域被遮挡时,obstructed/abs_obstructed 标志用于后续渲染与交互逻辑。
图表来源
- lightmap.cpp
章节来源
- lightmap.cpp
get_visibility 可见性判断
- 2D 与 3D 可见性:2D 使用 castLightAll,3D 使用 cast_zlight;两者均以透明度为输入,输出可见性缓存。
- 透明度缓存构建:按子图块批量填充,考虑地形/家具/场地上透明度、天气视距惩罚与“半透明”标志位。
- 视觉透明度缓存:额外处理玩家蹲伏/趴卧/低姿态导致的邻域遮挡,以及“半透明”地形对视线的影响。
图表来源
- lightmap.cpp
- shadowcasting.cpp
章节来源
- lightmap.cpp
- shadowcasting.cpp
光源类型与光照叠加
- 太阳光:自顶向下累加,考虑天气视距惩罚与楼层遮挡,快速填充四象限光照。
- 实体光源:角色、NPC、怪物、物品、车辆部件等,按缓冲区批量应用,减少重复光线投射。
- 局部覆盖与方向性:对建筑开口进行外部光照渗透,对特定方向应用定向光照,提升真实感。
- 局部覆盖优先级:某些场地上可覆盖整体光照,如强光源覆盖。
图表来源
- lightmap.cpp
章节来源
- lightmap.cpp
动态遮挡物与视野范围限制
- 动态遮挡:玩家蹲伏/趴卧/低姿态时,邻域遮挡生效;半透明地形对视线进行额外遮挡。
- 视野范围:基于最大视距常量与指数衰减,超过一定距离后透明度累积降至阈值以下。
- 地形/场地上透明度:玻璃等半透明材质在光照上可能不衰减,在可见性上按不透明处理。
章节来源
- lightmap.cpp
- lightmap.h
依赖关系分析
图表来源
- shadowcasting.cpp
- lightmap.cpp
- map.cpp
- vision_test.cpp
- shadowcasting_test.cpp
章节来源
- shadowcasting.cpp
- lightmap.cpp
- map.cpp
- vision_test.cpp
- shadowcasting_test.cpp
性能考虑
- 批量化与缓存
- 透明度缓存按子图块批量构建,避免重复计算。
- 光源缓冲区批量应用,显著降低光线投射次数(例如大型火堆)。
- 3D 扫描优化
- 通过 span 切分与斜率裁剪,减少无效格点访问。
- 对首行/首列 skip 标记,避免重复扫描同一行/列。
- 距离衰减
- 使用指数衰减函数,透明度累积随距离增加而快速下降,缩短有效扫描半径。
- 测试与基准
- 提供阴影投射与 3D 扫描的性能基准测试,便于回归与优化。
章节来源
- lightmap.cpp
- shadowcasting_test.cpp
- shadowcasting.cpp
故障排除指南
- 可见性不一致
- 使用 Bresenham 可见性检查作为对照,定位阴影投射边界情况(如墙角、柱子间隙)。
- 遮挡异常
- 检查地板/屋顶遮挡逻辑与视觉透明度缓存,确认半透明地形与玩家姿态设置。
- 性能退化
- 关注光源数量与分布,利用光源缓冲区批量应用;减少不必要的 3D 扫描层数。
- 调试工具
- 使用测试用例中的网格打印与计时,定位问题区域与热点。
章节来源
- shadowcasting_test.cpp
- vision_test.cpp
结论
Cataclysm-DDA 的视野与光照系统通过 3D 阴影投射、四象限光照与多层缓存实现了高效且真实的视觉体验。系统在性能与正确性之间取得平衡,支持多种光源类型与动态遮挡物,并提供了完善的测试与调试工具链,便于持续优化与扩展。
附录
常见视觉效果实现要点
- 半透明材质:在光照上可透光但在可见性上按不透明处理,避免“看到墙体另一侧”的错觉。
- 车辆光源:根据部件类型(圆锥/宽锥/半圆)应用不同角度与强度的光弧。
- 场地上光覆盖:对强光源进行局部覆盖,保证高亮区域的真实感。
章节来源
- lightmap.cpp
- lightmap.cpp