IES 文件保存的不是一张灯光纹理,而是灯具在不同空间方向上的光强分布。这个工具的目标,是让技术美术和灯光美术无需离开 Unity,就能读取 IESNA LM-63、检查光度曲线、观察真实落地形状、编辑能量分布,并把结果重新保存成可被其他渲染器继续使用的标准文件。

问题:一份 IES 文件为什么难以直接判断
传统的纹理预览适合颜色和法线,却不适合 IES。IES 记录的是光强 I(C, γ):γ 表示相对灯具光轴的垂直角,C 表示绕光轴旋转的水平角。一个值的单位是 candela,它描述“向这个方向发出多强的光”,而不是屏幕上的最终亮度。
因此,工程里真正需要回答的是三类问题:文件是否有效,光束在角度域里是什么形状,以及它打到真实表面后会形成怎样的照度。只有极坐标图会缺少空间直觉;只把 IES 挂到场景灯光上,又会被曝光、材质、天气和渲染管线干扰。工具把这三层拆开,分别提供数据、物理投影和独立 3D 预览。
→
→
→
→
第一层:把 LM-63 解析成可工作的光度数据
解析器先读取版本头与方括号关键字,直到遇到 TILT=;随后把换行、空格、制表符和逗号统一视为数值分隔符。这样可以兼容不同厂商导出时的折行差异。数值读取使用 InvariantCulture,避免编辑器系统语言改变小数点语义。
| 数据段 | 主要字段 | 工具中的用途 |
|---|---|---|
| Header / Keywords | LM-63 版本、灯具名称、厂商描述 | 资产识别与保存时保留元数据 |
| Photometric header | 灯数、流明、倍率、角度数量、Type、单位和灯具尺寸 | 校验文件、显示摘要、确定数组尺寸 |
| Vertical angles | γ[0..V-1] |
描述离开光轴的采样角 |
| Horizontal angles | C[0..H-1] |
描述绕光轴的采样平面与对称性 |
| Candela table | cd[H,V] × multiplier |
预览、编辑与保存的核心数据 |
读取坎德拉表时,原始 multiplier 会立即乘进每个样本,内部始终使用绝对光强。同时遍历整张表得到峰值 candela 及对应的 (C, γ),后续的归一化、曝光参考和光束角计算都依赖这一组统计数据。
解析器能够跳过文件内嵌的 TILT 数据,使预览不会因额外数值段错位;但编辑和保存只允许 TILT=NONE。这是刻意的防御性约束:没有完整实现倾斜灯具的变换语义前,不应该写出看似合法、实际方向错误的文件。
第二层:极坐标图把“光往哪里走”画出来
极坐标图以灯具光轴为 0°,绘制 C0 和 C90 两个典型截面。半径表示光强,角度表示 γ。线性模式适合比较绝对能量,Log 模式能把弱尾部拉出来检查;Normalize 则让不同功率的灯具可以只比较光束形状。

Beam Angle 和 Field Angle 不是额外存储的字段,而是从峰值向两侧寻找阈值交点得到的派生指标。工具分别使用峰值的 50% 和 10% 作为阈值,用于快速判断主光束宽度与外围有效范围。它们适合资产筛选,但不能替代完整曲线,因为两个光束角相同的灯具仍可能拥有完全不同的肩部和尾部。
第三层:从坎德拉到表面照度
为了回答“打到地面或墙上是什么样”,工具提供纯 CPU 的表面投影。每个像素先从灯具位置构造方向,换算为 (C, γ),再在坎德拉表中做双线性插值。最终照度遵循点光源的基本关系:
E(p) = I(C, γ) · max(0, N · L) / r²
其中 I 是该方向的光强,N · L 是表面入射余弦,r² 是平方反比衰减。预览再用峰值和灯距做自动曝光,并经过指数型 tone mapping 与 sRGB 转换。这样既保留光束形状,又不会让不同量级的 IES 在编辑器里直接全白或全黑。
对称性展开是正确采样的关键
IES 文件为了节省数据,常常只保存部分水平角:一行代表轴对称,0° 到 90° 代表四象限对称,0° 到 180° 代表双边对称,接近完整一圈则按全方向数据处理。采样任意 C 角时,工具先按文件声明隐含的对称性折叠到已存区间,再在 C 和 γ 两个方向插值。忽略这一步,预览会出现缺扇区、断边或左右不一致。
第四层:不依赖渲染管线的 3D 实时预览
场景预览没有创建 Unity Light,也不要求 HDRP 的 IES Profile。CPU 先把分布烘焙为一张 360 × 181 的 RGBAHalf 查找纹理,U 对应 C 角 0° 到 360°,V 对应 γ 角 0° 到 180°,R 通道保存相对峰值归一化的光强。

GPU 侧通过一次 Graphics.Blit 执行全屏 ray caster。每个像素构造相机射线,与地面平面求交,在灯具局部基底中恢复 C 和 γ,再查询 IES LUT 并计算 I · cosθ / r²。地面网格只用于提供尺度与透视参照。因为整个过程只依赖一个隐藏 Shader 和一张 512² RenderTexture,所以 Built-in、URP 与 HDRP 编辑器环境都能使用同一套预览。
独立预览把 IES 本身与场景变量隔离开。它不会受到曝光卷积、阴影、材质 BRDF、体积雾或天气系统影响,因此非常适合判断“文件是否正确”。最终落地仍需回到目标渲染管线验收,两者解决的是不同问题。
编辑:修改的是能量分布,不是灯的 Transform
编辑器始终保留一份 Source,并在每次参数变化时深拷贝出 Edited Snapshot。所有操作都作用于坎德拉表,因此保存后的光束形状可以被其他支持 IES 的软件复现,而不是只在当前 Unity 场景里生效。

| 参数 | 实现方式 | 结果 |
|---|---|---|
| Brightness | 所有采样乘以全局 Scale Factor | 保持形状,改变绝对 candela |
| Beam Spread | 按比例反向重采样 γ 角距离 | 大于 1 展宽,小于 1 收窄 |
| Push Forward / Sideways | 把输出方向旋转回源分布后采样 | 光轴不动,能量峰值在 IES 内偏移 |
| γ Remap | 按垂直角应用 AnimationCurve 倍率 | 独立调整中心、肩部与远端能量 |
| C0 / C90 Freehand | 用归一化曲线覆盖指定光度平面 | 直接塑造两个关键截面 |
二维光束偏移是其中最容易被低估的一步。工具先把目标偏移量组合成一个峰值方向,再通过 Quaternion 构造“目标峰值到原始光轴”的旋转。对输出表中的每个方向,先做逆向方向映射,再回到源表双线性采样。这样避免直接平移数组造成角度空间变形。
轴对称文件只有一行水平角,无法表达偏向某个 C 平面的光束。一旦发生非零二维偏移,工具会把它扩展为 0° 到 360°、每 10° 一行的完整表,再进行方向重采样。这个扩展会增加文件数据量,却是打破轴对称后保持信息完整所必须付出的成本。

保存:不只把数组写回文本
序列化器保留原有关键字,把内部的绝对 candela 写回文件,并强制 multiplier 为 1,避免“数组已经乘过倍率、文件又重复乘一次”的二次放大。保存时还可以追加一条编辑历史说明;界面默认提供 Save As,并把覆盖原文件放在明确的危险操作中。
编辑后的总光通量通过球面积分重新估计:
Φ = ∫₀²π ∫₀π I(γ, C) · sin(γ) dγ dC
离散实现沿相邻 γ 区间积分,并对已存 C 范围求平均,再利用轴对称、四象限或双边对称扩展到完整 2π。结果乘以 Ballast Factor,写回 Lumens Per Lamp。峰值 candela 与峰值角度也会重新遍历计算,保证文件摘要与编辑后数据一致。
模块拆分与职责
| 模块 | 职责 | 设计价值 |
|---|---|---|
| Parser / IESData | LM-63 读取、字段归一化、峰值统计 | 让所有视图共享同一份明确数据模型 |
| Plot Renderer | C0/C90 极坐标曲线、线性/对数显示 | 快速检查角度域分布 |
| Light Projector | 对称性映射、双线性采样、地面/墙面照度 | 提供不依赖场景的物理形状参考 |
| Scene Previewer + Shader | LUT、全屏射线、相机和灯具交互 | 跨管线提供实时空间反馈 |
| Editor | 非破坏重采样、曲线覆盖、对称性扩展 | 把艺术控制落到标准光度数据 |
| Serializer | 元数据保留、流明积分、LM-63 回写 | 形成可交付、可复用的闭环 |
性能与工程边界
这是 Editor-only 工具,不进入 Player,也不会给游戏运行时增加 Pass、Draw Call 或常驻纹理。解析与编辑的主要复杂度是 O(H × V);默认 LUT 约 6.5 万个采样,3D 预览是一张固定 512² RT 的全屏 Pass。CPU 表面投影默认 256²,最大限制为 1024²,只有重建时发生。
| 边界 | 当前策略 | 后续可扩展方向 |
|---|---|---|
| TILT 非 NONE | 允许安全读取,禁止编辑保存 | 实现完整倾斜几何与外部 TILT 文件解析 |
| Photometric Type A/B | 保留数据;空间预览按常用 Type C 语义解释 | 加入 A/B 到 Type C 的坐标转换 |
| 异常水平角表 | 标准 0/90/180/360 对称;其他范围钳制 | 按 LM-63 边界情况增加更严格校验 |
| 高分辨率 CPU 投影 | 同步生成并限制分辨率 | 编辑防抖、Jobs/Burst 或 GPU Compute |
| 最终画面一致性 | 独立曝光与简化地面模型 | 增加目标管线适配层与基准场景对照 |
结论
这套工具的价值不在于多做了一个 IES 缩略图,而在于建立了一条完整、可验证的数据链:从标准文件读取方向光强,经过对称性正确的采样与物理照度预览,再以非破坏方式重塑分布,最后重算派生量并写回标准格式。它把灯光资产从“只能导入后试效果”的黑盒,变成可以检查、比较、编辑和交付的数据资产。
对生产工具而言,最重要的并不是把所有边界一次性覆盖,而是明确哪些数据已经被正确解释、哪些操作会改变物理量、哪些格式暂时只读。正是这些约束,让实时反馈不会以牺牲文件可靠性为代价。