Preface
同上次封笔算是承上启下了,刚好能从琢磨卡通渲染的部分(重新)入手…毕竟旧工作这方面留下的问题远远比解决的多()
集训前时间也算充裕,看看能写多少吧
- 版本: 日服 5.0.0 (烤森更新)
- 设备:Mac Mini M4 (2024)
1. 预备工作
之前有在 Android 实机(注:Pixel 2 XL)上用 RenderDoc 跑过捕捉…除了设备性能相对羸弱和捕捉死慢以外可用性其实不错
不过如今有了 Mac 这方面也许可以不用强加这种限制
先前捣鼓 GPTK 的时候读过它的 README,注意到这段相当有趣:
…and inserting the following environment variables to enable Metal debugging and processing of debug information: MTL_CAPTURE_ENABLED=1 D3DM_DXIL_PROCESS_DEBUG_INFORMATION=1
改个环境变量就能调试…比在 Win 上捕捉第三方 Game 得方便太多;应付后者用 RenderDoc/PIX 还学会了各种奇怪的注入方式(?)——不过,回到正题,这个变量放到wine + D3DMetal
转译层以外好用吗?
游戏准备
Apple Silicon 的 Mac 无一例外都可以原生跑 iPhone/iPad OS 上的 App —— CPU,GPU零 overhead
不过注意“可以”,AppStore上并搜不到多少能直接装的应用…
但是万幸还有PlayCover可以直接装解密过的 IPA;后者 armconverter 上一搜即得
环境变量
凭 Windows 上的肌肉记忆竟然想直接去设置找 = =
不过除了从shell调变量后启动以外其实mac上还真有这样的东西:EnvPane
尝试开启MTL_DEBUG_LAYER
;这里MTL_HUD_ENABLED
只是全局开启 Metal 性能HUD
话说回来Xcode里也能直接设置,此步可以略过
Xcode 配置
从空项目开始
不知道为什么Debug > Attach To Process
一直不刷新,索性直接使用Debug > Debug Executable
注意选择目标时不要选PlayCover创建的App图标 - Xcode会把它当成iOS应用处理导致之后没有调试Destination
这里需要选择App自己的二进制ProductName
,位置如下
⌘⇧+G定位到所在文件,选择即可
Options > GPU Frame Capture
调成Metal
;这里后面也可以通过Product > Scheme > Edit Scheme
修改
直接启动,可以观察到游戏吐了一些log
暂时没用;启动后可以观察到HUD指标
设置里解放FPS以后进入3D MV(脳内革命ガール - https://www.youtube.com/watch?v=ZKuk7PeBc0U,https://www.bilibili.com/video/BV1Xz4y147c1)
原生4K120…这里告诉我们至少两件事情
- 24款Mac Mini真的很香😋
- 同大多数移动game一样 - 管线比较基础;有种挑了软柿子捏的感觉()
2. GPU捕捉!
有趣的是PJSK在暂停3D PV预览时并不会暂停渲染thread
点一下屏幕回来捕捉即可,按下Capture
注: Profile after Replay
可以考虑关掉加速shader编辑
Pass一览无余…可以说是相当养眼
一些观察
Present翻转
可以注意到管线中的图形是上下翻转的,这里和Metal的NDC空间有关系
Metal和Vulkan类似,仿射后的$Y$轴正方向朝下
修复而言在Vertex shader全部翻转仿射后的$Y$轴(比如直接对$PVM$矩阵之$P$变换)可行
不过Unity并没有这么做,而是在Present之前加了一层Flip pass…
…倒着UV重新blit了一遍;考虑否则用户需要手写修改的shader量貌似也无可厚非?
渲染模式
Game使用的仍是经典的前向渲染 (Forward Rendering),没用新鲜的TBDR;貌似URP支持后者?
但很显然这里用的其实是SRP
3. 浅看后处理
DoF
上图可见管线在处理完几何之后吐出了5个tex;一个图像,两个一对Depth-Stencil,还意外地留下了一个“Depth”和…Brightness?
这里Depth是个只使用了$R$通道的深度buffer;但不同于作z-test的buffer,这个buffer的取值范围并不对应NDC深度
参阅反编译易知这原来是做景深效果用的Buffer(注意_CoCParams
,CoC即Circle Of Confusion)
线性深度套用简化版(和上述链接非常相似的)公式后放到$[0,1]$区间存储
材质在后期被整合到_ColorCocTex
的Alpha通道
之后在简单Mip下采样以后快速产生模糊版图像并根据之前的CoC值叠加过去成景深后图像
(很好奇这里为什么会有个没用的Fg
…会被优化掉吗?)
Sampler全是Linear/Nearest Mip Filter,图略
…相当简单粗暴
Bloom
因为game没在做HDR渲染,Brightness tex在这里派上用场
做Box Blur后在后处理最后合成
饱和度?
此外,后处理部分还有LUT色阶处理与一些其他参数控制的效果
和一个同之前CoC下采样后的_SatTex
,不知道干什么的,不过…
Xcode中调试Metal shader相当容易:
一点即可即时获得编辑响应;来看看SatTex
干的活
在这里调节_SatAlpha
值,首先$0.5$时:
$1.0$时
$0.0$时
参阅代码也易知图像随这个值在模糊后与正式framebuffer见进行Lerp;值越小效果越’清晰‘
命名有点奇怪…同时正式buffer也有原来模糊过没有的后处理,过渡并不自然
具体实现什么目的暂时还猜不到orz
SMAA
后处理完毕做一遍SMAA就基本完毕了
最后来到上文提及的Flip - 呈现完毕
结语
第一次写逐帧分析,不得不说工作量比自己想象的大orz
未来希望在系列结束时能完成sssekai_blender_io
立下的几个flag,路漫漫其修远兮…
除了以下citation,这里还要特地感谢UnityPy及其群组和几位来自Q群/Discord不方便透露名字的朋友的帮助+指正+资源+…
SEE YOU SPACE COWBOY…
References
Real Time Rendering 4th Edition
https://mamoniem.com/behind-the-pretty-frames-detroit-become-human/
https://www.reedbeta.com/blog/circle-of-confusion-from-the-depth-buffer/
https://developer.apple.com/documentation/accelerate/fma
https://developer.apple.com/documentation/xcode/inspecting-shaders
https://www.saschawillems.de/blog/2019/03/29/flipping-the-vulkan-viewport/