0%

原神场景实现分析(木偶雪城截帧)

由 astra 生成 · 更新于 2026-09-27 18:44(北京时间)

分析日期:2026-09-27。范围为木偶所在的雪城,输入为本机 muou_light.rdc。重点是表面高度层、雪覆盖、烘焙阴影解压、环境反馈和最终颜色之后的时序重建。

本文完整展开本截帧的场景逻辑;角色内部算法见 角色分析。跨游戏结论另见 场景实现对比,回放定位见 证据索引。

本截帧最终画面

总览用于定位场景;算法旁的局部图采用同一区域对照,并写明可观察的变化。阶段配对保持一致显示设置,HDR 预览范围与最终输出颜色分别说明。图片直接从真实回放生成,未修改截帧资源。

1. 管线与数据依赖

阶段 处理逻辑 输出的作用
场景准备 更新局部风场、植被交互与表面高度候选,准备角色几何 为表面覆盖和动画提供随场景变化的数据
主材质 按地形、雪、植被、建筑和角色的不同规则生成颜色、法线与分类 将作者控制的材质信息交给公共光照
遮挡与环境 由分级深度处理可见性/AO;把烘焙阴影解压到缓存,结合动态阴影、空间查询与反射结果 得到当前表面的受光限制和环境贡献
照明与反馈 延迟光照按类别求值;环境传感器汇总场景颜色/阴影,为后续角色更新保留反馈 角色环境平滑与当前场景光照各有独立读写顺序
雾、透明与运动 完成颜色合成后,结束法线用途,把该纹理改写成相机/几何运动 让动画和相机移动都能定位上一帧对应像素
颜色处理与抗锯齿 先处理运动模糊、泛光与最终颜色,再做边缘检测、邻域混合和历史重建 历史累计的是经过颜色处理的画面,不能直接当作另一套 HDR 历史使用

这里最关键的依赖是:运动写入必须晚于法线的最后一次消费,时序融合必须晚于运动的最后一次写入。 角色传感器则先使用已有反馈,再更新结果,构成另一条跨帧依赖。

2. 公共表面数据、分类与深度

数据用途 本截帧的生成与编码
表面法线图:保存表面朝向,决定光照与遮蔽 材质阶段 RGB 直接编码方向,RGB10A2;后面复用为运动矢量图
材质颜色图:为后续着色提供表面颜色 RGBA8 sRGB;含角色已经过材质处理的颜色
HDR 光照颜色图:存放已计算的亮度与颜色 延迟光照写单独的 HDR 场景颜色,不占这六个材质输出槽位
运动矢量图:保存前后帧屏幕位移,定位历史像素 光照后把原法线图改写为运动矢量与控制标记,RGB10A2
附加材质参数图:控制表面如何接受后续光照 第二着色/材质参数图 RGBA8 sRGB,附加材质标量图 R8
材质类别/扩展标记图:选择处理分支 材质类别与时序控制 R8,打包扩展标记 R8
相机深度与模板图:遮挡测试、空间位置重建与分类 D32S8

表面法线以 RGB 保存方向,光照解码为 normalize(2×RGB-1)。材质类别图的低位用于选择着色分支,高两位参与历史控制;模板分类又是另一套存储,不可与类别纹理中的数值直接互换。

延迟光照先按模板掩码筛选像素,保留原深度,再消费对应材质数据;贴花更新颜色/法线时保留扩展标记图。主相机深度供位置重建和分级深度使用,阴影视图深度则记录光源可见性。

3. 表面高度缓存与可见雪材质

场景准备记录表面高度候选,可见材质按方向和作者遮罩决定覆盖;二者都属于雪场景的实际执行路径,但高度缓存的全部后续消费者尚未完全还原。

表面高度层更新

雪场景准备把几何投影到缓存区域,利用光栅覆盖调用像素程序,但不输出可见颜色或深度。像素程序经 UAV 更新2048² 的打包高度/高度差缓存与 256² 的更新标记图:一个保存精细表面候选,另一个标记哪些粗网格发生变化。

具体机制如下:

  • 先检查表面朝上程度:归一化法线的 y 必须大于约 0.642788,即与向上方向夹角小于约 50°。还检查经尺寸/高度范围换算的深度导数,阈值为约 1.191754,防止陡斜或不连续面进入该缓存。
  • 像素位置加环形偏移后,与 2048-1 按位相与,实现 2048×2048 周期寻址。本帧偏移为 (734,1038);不是每次移动都重建一张以世界原点固定寻址的贴图。
  • 每 8×8 个精细像素对应一个粗网格:坐标右移 3 位查 256² 的占据表。把 1-深度 分成 32 层,使用一个 32-bit 整数中的位表达占据高度。
  • 当前层加入已有占据位之后,仅继续处理集中在最低两个相邻层内的情况,避免多组分离表面被当成同一连续高度层。
  • 精细高度采用 round(saturate(1-深度)×65532) 量化,保留特殊端点处理;与旧高度比较,只接受正向且在允许厚度内的更新。
  • 将量化高度放在高 16 位、高度差放在低 16 位,对输出执行整数原子最大值。只有赢得更新的像素才给对应粗网格写入标记 1。

本帧高度范围参数为 32,允许层厚系数为 1.2,对应量化空间比较阈值 ceil(65532×1.2/32)=2458。这些行为支持将其解释为可用于雪/表面处理的高度层候选与更新缓存;还未完成全部后续消费者的物理意义映射,因此不将该缓存直接称作完整雪变形、GI 体素或地形碰撞系统。

证据:高度层更新程序、本帧网格与范围参数。

双层覆盖与闪光控制

光照前的材质颜色 最终雪城局部
光照前的材质颜色 最终雪城局部

观察中间栏杆顶面、两侧台阶和树冠。 材质阶段已经形成积雪与基底的颜色分区,最终画面再出现明显的蓝色环境受光和台阶阴影。这里能看出雪覆盖先进入材质、再参与光照;这是材质到最终输出的阶段对照,不是“关闭雪材质”的结果。

可见雪材质具有两套基础表面层:原物体底色/法线/材质控制,以及覆盖层颜色/法线/控制。当前两层均开启。每层分别处理 UV 缩放偏移、颜色调制、法线强度及材质参数,然后才按覆盖权重组合,而不是只在最后把像素调白。

本帧覆盖方向为世界向上 (0,1,0)。方向判断使用几何法线与第二层法线的混合,混合系数约 0.499;再叠加选定的顶点颜色通道。当前选择顶点颜色 B,偏置为 -0.75,过渡宽度为 1:

1
2
3
覆盖参考法线 = lerp(几何法线,第二层世界法线,0.499)
t = saturate((dot((0,1,0),覆盖参考法线)+顶点色.B-0.75)/1)
方向覆盖 = 顶点色.B × t²×(3-2t)

该事件还以顶点色 B 再乘一层遮罩;因此在这组具体开关下,两层混合因子包含 顶点色.B²×smoothstep结果。这说明顶点颜色既可作为作者绘制的覆盖许可,又会改变方向阈值,法线贴图也能影响雪在表面上的分布。颜色、法线与材质参数分别有自己的混合控制,不能只插值颜色后沿用原法线。

同一程序后半还有专用雪细节:

  • 采样世界雪法线和闪光遮罩,不仅使用物体自身的普通法线贴图。
  • 根据输入位置的屏幕导数总量构造 max(1-24×导数量,0),压低不稳定的细微偏移,避免远处或高频区域的闪光坐标过于敏感。
  • 闪光遮罩使用约 0 到 -4 的动态 mip 偏置区间,并在条件成立时增加一次由视角相关量偏移约 0.015 的采样。
  • 使用 (1-saturate(视线与法线点积))³ 类型的边缘增强项调制雪颜色。
  • 最终把雪相关状态左移 6 位后加入 R8 材质类别图,即高两位与普通材质类别共用一个字节;第 9 节的时序阶段恰好读取这些高位选择处理规则。

最后一项建立了可追踪的生产者/消费者关系:雪材质不仅生成颜色,还告知时序处理应该如何保留或约束历史。这比看到 FSR2.0 名字就认为所有像素使用同一历史策略更具体。

证据:雪材质程序、本帧双层材质参数。本节展开代表变体,其他地形、石材、植被变体仍应分别核对。

局部风场与植被交互还提供独立动态输入;完整植被弯曲、交互衰减和其他地形混合公式仍待进一步拆解。

4. 阴影:压缩静态数据与动态几何汇合

角色与场景几何从光源方向生成动态深度;静态部分另从烘焙压缩数据解码到阴影缓存。两者在可供比较采样的深度图集中汇合,后续着色不必知道某个深度样本来自实时几何还是解压结果。压缩结构见下文。

图集子区块采用不同分辨率,并为边界留出内缩区域:例如 256、512、1024 的分配格分别只使用 252、508、1020 的可绘制范围,起点内缩 2 像素。这为边界过滤提供隔离空间;完整采样越界处理尚未全部还原。

阴影随后经历低分辨率解析、过滤与全分辨率合成,最终由 RG8 屏幕阴影图把遮挡量交给光照。每个材质可以读取公共结果,不必重复完成整条阴影解析链;两通道各自对应的阴影来源仍待进一步确认。

分块索引和两种深度压缩记录

阴影解压通过覆盖目标区域的矩形运行像素程序,并直接输出深度。输入分成分块索引纹理与元素步长 4 bytes 的压缩记录数组:先查某块的数据在哪里,再按当前像素位置恢复深度,而不是读取一张现成的深度图。

解压程序先把目标局部像素坐标右移 5 位,找到一个 32×32 像素块的元数据。因此该代表元数据表描述的逻辑深度范围为 1024×1024;写入较大的阴影图集由矩形绘制的位置和 viewport 决定,不意味着元数据表本身有图集那么大。

每个像素按以下流程查找压缩记录:

  1. 块头的高 8 位控制是否进入分层节点查找;另有数据地址部分。
  2. 节点描述符每项 10 bit,三个描述符打包在一个 32-bit 整数中,用整数除以 3 和余数选择目标字段。
  3. 节点最低位参与“继续下降还是到达叶子”的判断;像素的 x/y 位组合成 0–3 的象限号。
  4. 程序最多执行四次实际象限寻址,逐级使用块内坐标较高位到较低位。叶子再从描述符中取 8-bit 数据索引,读取深度载荷。

载荷最低位选择两种解码形式:

压缩模式 恢复方法 适用的数据形态
平面深度 从位段恢复两个斜率和一个截距,经过半精度浮点转换;将截距校正到当前 32×32 块原点,再对像素中心坐标做一次平面求值 倾斜但局部近似平面的阴影深度可用少量系数表达
2×2 分量量化 用像素 x/y 奇偶选择位起点 6、12、19、25;横向两个分量分别取 6 或 7 bit,再结合共享尺度恢复深度 保存小块内独立深度差异

平面模式可以概括为 深度=ax×块内归一化x+ay×块内归一化y+c。整数常量在 DXBC 文本中有部分被显示为极小浮点数,本文没有凭显示为 0.000000 的文本猜出完整地址掩码或共享指数偏置;分块尺寸、描述符宽度、象限查找与两种解码结构则有直接指令证据。

这种组织把存储与采样分开:离线结果按局部深度形态压缩,使用前恢复为常规深度附件,从而接入与动态阴影相同的比较采样和过滤流程。

证据:阴影解压程序、本帧路径绑定。

5. 空间查询、间接项与角色环境反馈

这条路径先建立三维索引表与结构化数据,再把它们同屏幕法线、深度和颜色联合使用,生成较低分辨率的 HDR 间接/反射候选结果。结果经过整理与不同分辨率之间的合成后,由延迟光照消费。

三维索引表与颜色体积的职责不同:前者用于查询和组织空间数据,后者才是可以直接参与着色的光照结果。目前已确认这条生产和消费关系,但索引字段、追踪过程以及漫反射间接光与镜面反射的分离规则尚未全部还原,不能把整条链直接命名为 DDGI 或某种光追 GI。

场景结果还通过角色环境采样形成反馈:采集材质颜色与阴影、过滤无效点、平滑已有结果,供角色使用,详见 原神角色的环境反馈。

6. 环境遮蔽与反射结果的整理

屏幕环境遮蔽先从深度/法线相关数据生成半分辨率 R8 结果,再经过计算过滤和空间遮蔽场处理,与屏幕阴影/遮蔽结果结合。分级深度为邻域和不同尺度的空间查询提供输入。

延迟反射与空间数据处理衔接,生成较低分辨率候选颜色,再整理为延迟光照所需的颜色图。已确认的是这些结果如何进入光照;AO 的完整采样分布、空间遮蔽场内部字段和反射追踪/回退策略尚未全部还原。

这里不能把空间索引表直接当作光照颜色,也不能把间接候选结果全部归为同一种反射模型。原始输入输出见 场景绑定证据。

7. 体积雾:结合空间光照和遮挡再合成

局部体积更新读取灯光、阴影、雾参数、历史体积和噪声,写入 160×68×128 的三维网格。三维位置线性展开给工作线程:每个线程对应一个体素,分别计算空间中的介质贡献。

后续继续处理体积与历史、过滤结果,再把雾合成到主 HDR 颜色。这意味着雾受空间光照和遮挡影响,并非只根据一个表面到相机的距离套固定指数颜色。完整散射相函数与历史权重仍未逐项还原。

8. 法线结束使用后复用为运动图

公共光照消费完表面朝向后,相机与几何运动阶段重新写同一纹理:由当前与前一帧投影位置得到屏幕差,压缩到 RG;附加通道保留控制标记。

原始运动数据预览 用于核对通道,其中紫色角色轮廓主要反映附加标记。实际时序重建效果见下一节的输入/输出局部对照。时序消费者按下式还原运动:

1
2
3
q = 编码RG - 127/255
位移 = sign(q) × (2q)²
历史UV = 当前UV - 位移

这条复用关系要求严格的阶段边界:法线最后一次被读取后才能改写;相机、动画几何与相关效果都写完运动后才能融合历史。角色变形也必须提供一致的前后位置,详见 原神角色分析。

9. 空间抗锯齿与历史重建

当前帧的边缘和邻域处理

处理步骤 输入的意义 输出的意义 对画面的作用
亮度边缘检测 后处理颜色图、材质类别图 RG8 横向/纵向边缘图 找出需要抗锯齿的轮廓,并按材质类别筛选
边缘权重计算 边缘图、面积权重查找表、边缘搜索查找表 RGBA8 邻域混合权重图 根据边缘形状决定向哪些邻居混合、混合多少
邻域颜色混合 原颜色、权重图、边缘图 RGBA8 空间抗锯齿颜色图 平滑当前帧的锯齿轮廓
颜色回写 空间抗锯齿结果 当前后处理颜色图 把邻域混合结果交给后续时序阶段
历史重投影与融合 当前颜色、采样偏置上限查找表、深度图、运动矢量图、分类图、历史状态与历史颜色 RG8 新历史状态、RGBA8 新历史颜色 按运动寻找上一帧对应位置,并结合状态控制历史复用

亮度边缘检测使用系数 (0.2126, 0.7152, 0.0722),左右/上下邻域亮度差与 0.1 比较,输出两方向 edge。它先检查分类纹理约 0.019608(5/255) 的值,因此不是全画面完全同一套空间边缘处理。

边缘权重阶段用面积权重表和边缘搜索表,将边缘形状转为邻居的混合权重;邻域阶段据此平滑当前画面,构成 SMAA 型形态学处理。后面的时序阶段才读取历史颜色与状态,并由采样偏置上限表限制重建核的尺度。

这条链在相同分辨率上处理当前图与历史图,作用是轮廓平滑和时序重建;本帧没有执行从低分辨率到高分辨率的放大。

原始程序:亮度边缘检测、邻域混合权重计算、历史重投影与融合。

邻域择近、颜色重建与历史状态

时序融合输入 时序融合输出
时序融合输入 时序融合输出

观察左侧栏杆的细碎亮点与右侧雪坡。 输入保留大量孤立亮点和较硬的细边缘,融合后亮点更集中、局部纹理和轮廓也更柔和。这组同区域、同显示设置的图直接展示本次时序重建的变化,同时能看到细节变软的代价;单帧对照不证明运动中的拖影或闪烁表现。

时序重建分别处理“沿哪个表面重投影”“如何重建当前与历史颜色”“什么时候约束历史”“还能积累多少历史”:

  1. 从前景表面取得运动。 比较中心深度与四个 (±2,±2) 像素位置的深度,排除越界位置,取反向深度值更大的位置,再读该位置的运动与类别。这让细轮廓附近优先沿前景表面的运动重投影。
  2. 解码压缩运动。 q=运动.RG-127/255,v=sign(q)×(2q)^2,历史 UV 为当前 UV 减 v。零点不是 0.5;若按 0.5 解码会引入固定偏差。分类字节取高两位 ((uint(255×类别值+0.5)>>6)&3),与延迟光照用的低位材质类别分开。
  3. 重建历史颜色。 根据历史坐标的小数部分构造三次多项式权重,合并采样位置,以五次颜色采样重建历史 RGB;四个外围采样与中心采样组合后归一化。历史可信状态单独读取,历史颜色 alpha 也单独参与判断。越界时颜色及状态清零。
  4. 重建当前颜色。 显式读取当前颜色的 4×4 共 16 个 texel。滤波宽度受到状态和 16×16 的采样偏置上限查找表约束;在边界上将采样坐标裁到有效 texel。不是用一张双线性采样就代表当前颜色。
  5. 按类别和历史状态约束旧颜色。 一类采用逐通道最大值保留规则;其他分支在状态到期时,使用当前帧对角样本构造可容许颜色区间,再把历史 RGB 限制进去。区间扩展还依赖运动与亮度差。
  6. 以累积量决定混合比例并回写状态。 当前帧滤波权重总和与已有历史累积量共同决定输出;速度还会压低下一帧可用的累积量上限。

当前 4×4 重建核的每个样本权重可写为:

1
2
3
4
5
d² = min(dot(样本到重建中心的偏移×滤波尺度,
样本到重建中心的偏移×滤波尺度), 4)
w = [1.5625×(0.4×d²-1)²-0.5625] × (0.25×d²-1)²
当前重建色 = sum(w×样本色) / 有效权重和
当前重建色 = clamp(当前重建色, 16样本逐通道最小值, 16样本逐通道最大值)

分母先把总权重限制为非负;不足 0.001 时用 1 避免除以接近零的数。核存在负瓣,因此最后的邻域颜色限制有实际作用,不能将它理解为普通均匀平均。

记这次总权重为 W,已经过控制量限制的历史累积状态为 H,最终当前颜色比例为:

1
2
3
当前比例 = W / (W + 12×H)
输出颜色 = lerp(受约束历史颜色, 当前重建色, 当前比例)
下一次累积量的速度上限 = 12 - 10×saturate(6000×length(v))

速度为 UV 单位;上限在静止时为 12,快速运动时降至 2。这是累积量上限,不是直接把历史颜色乘以 12 或 2。历史量更新还包含当前覆盖控制量,不应只摘上限公式就声称完全复现了该程序。

两张输出的通道职责也可以进一步细分:

输出 通道意义 具体行为
RG8 历史状态 R 颜色约束的延迟/保留状态 普通路径每次减去 1/(参数+1),本帧为 1/9;高位类别为 1 的分支置 1;状态到期后启用更强颜色约束
RG8 历史状态 G 归一化历史累积量 将下一次累积量乘 1/12 保存,下一次读取后参与历史权重
RGBA8 历史颜色 RGB 时序融合后的颜色 下次历史采样的颜色来源
RGBA8 历史颜色 A 当前运动图 B 控制标记的历史副本 直接从当前运动图继承;用于前后控制状态比较,并非本次重新估计的连续置信度

当前采样偏置的常量换算到像素约为 (0.375,0.222222);这是本帧值,单帧不足以还原完整抖动序列。状态控制参数为 8,额外分支开关为 0。证据:完整时序程序、本帧常量。

10. 颜色后处理与时序输入的关系

运动模糊、泛光和最终颜色处理先完成,再执行空间抗锯齿与历史融合。时序输入已经经过亮度和颜色调整,所以它的邻域范围与历史约束针对的是后处理画面;不能直接移到 HDR 光照前面而假定行为不变。

11. 分析边界与证据

已拆解雪高度候选、代表雪材质、烘焙阴影压缩和主要时序重建。空间 GI/反射链仍有索引、追踪与分量分离细节未确认,不能用某个引擎或产品名称代替这些未知逻辑;连续帧缓存交换与不同材质变体也需单独查证。

场景绑定附录 保留原始管线状态,资源语义索引 对照各资源用途;各算法段落的程序与常量链接可用于重新核对。