PSJK Blender卡通渲染管线重现【1】- 预备工作

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 上一搜即得...

January 14, 2025 · 1 min · 207 words · mos9527

PSJK Blender卡通渲染管线重现【2】- 角色及舞台 Shader

Preface Shader部分其实已经有不少现成工作,比如 https://github.com/KH40-khoast40/Shadekai https://github.com/festivities/SekaiToon 至于为什么要自己重新造轮子…有时间。还要什么理由?除此之外(敲黑板)最后实现是要进 Blender 的嘛… PV:愛して愛して愛して 在Xcode调试Metal甚至有Render Graph方式呈现的资源依赖…库克太谢谢你了🥲 上一篇并没有往SRP后处理前的工作去看;这里直击SRPBatcherPass 很巧的是恰好这个Pass处理的正包含角色部分,下面逐步分析 注: 后文向量都将以图示方向表示 1. Eye-Highlight 简明概要的效果 - 即给角色眼睛表现添加卡通风格高光 这部分由额外Mesh表达(注意缩写ehl),在Pass中作为第一个Mesh出现 回到 Metal 调试,观察反编译可知几个效果上的细节 高光‘闪烁’效果 u_xlat0.x = FGlobals._SekaiGlobalEyeTime * UnityPerMaterial._DistortionFPS; u_xlat0.x = floor(u_xlat0.x); u_xlat0.x = u_xlat0.x / UnityPerMaterial._DistortionFPS; u_xlat1.x = u_xlat0.x * UnityPerMaterial._DistortionScrollX; u_xlat1.y = u_xlat0.x * UnityPerMaterial._DistortionScrollY; u_xlat0.xy = fma((-u_xlat1.xy), float2(UnityPerMaterial._DistortionScrollSpeed), input.TEXCOORD5.xy); u_xlat16_0.xy = _DistortionTex.sample(sampler_DistortionTex, u_xlat0.xy).xy; u_xlat16_2.xy = fma(u_xlat16_0.xy, half2(2.0, 2.0), half2(-1.0, -1.0)); u_xlat0.xy = float2(u_xlat16_2.xy) + float2(UnityPerMaterial._DistortionOffsetX, UnityPerMaterial._DistortionOffsetY); u_xlat1.x = UnityPerMaterial....

January 14, 2025 · 11 min · 2187 words · mos9527

PSJK Blender卡通渲染管线重现【3】- SDF 面部渲染实现

Preface 在v2面部模型更新后游戏终于引入了SDF面部阴影;实现上和市面上已有的大部分方案大同小异 本文分享自己在Blender中正确实现该效果的一种思路 注意: 由于个人水平有限错误难免,强烈推荐阅读以下文本作为预备知识: 二次元角色卡通渲染—面部篇 by MIZI 卡通渲染——360度脸部SDF光照方案 by Yu-ki016 Signed Distance Field by 欧克欧克 1. SDF 概述 SDF面部阴影在解决朴素法线/N dot L阈值阴影在极端光照角度表现上的不足以外提供了表现上相当大的自由 具体实现上也相当简洁,以下是HIFI Rush中的应用例 图源:Tango Gameworksのチャレンジが詰まったカートゥーン調リズムアクションゲーム『Hi-Fi RUSH(ハイファイラッシュ)』(1)キャラクター・モー*ション・エフェクト編 美术在(凭不同光照角度于原几何上的)渲染输出为蓝本,手绘出基于角度的阈值图后经某种合成算法后生成一张以亮度映射到光照角度的SDF图像 着色上,SDF可以将点/Fragment渲染的问题转换为物体/Object整体渲染的问题 ​ 最后的着色与且仅与光照角度有关(敲黑板),某种程度上来说等效于对法线一致的平面作阴影 合成上,有 Valve 在 SIGGRAPH 2007 上做的技术分享 和相当多教程会介绍的8-points Signed Sequential Euclidean Distance Transform/8SSEDT 在之后的文章中将会对这两者进行更深入的实现和剖析 当然,本篇还是以复现游戏效果为主 2. 游戏内实现 抽出游戏所用的SDF贴图如下 在 Photoshop 中查看阈值,很显然是上文所介绍过的类似模型 回忆我们所需的阈值对应光照角度;接下来马上就会用到(再次敲黑板) 3. Blender 实现 光照角度 从角度出发,考虑单个光向量$l$ —— 如图(来自 RTR4 …当然这里和BRDF并没有直接联系 由于对称性很显然只凭$ \mathbf{\hat{n}} \cdot \mathbf{\hat{l}}$ 我们只能获得 $\theta \in [0,90\degree]$的光照角($<0$ 部分背光故省去)...

January 14, 2025 · 3 min · 552 words · mos9527

Project SEKAI 逆向 - 笔记归档

Preface Cutoff: 24/01/05 Revision: 24/09/26 其实分析工作主要是在此后才真正起步…不过实在找不到时间写帖子orz 对最新知识有兴趣或也想参与研究的话,还请参阅以下Repo及其Wiki: https://github.com/mos9527/sssekai https://github.com/mos9527/sssekai_blender_io Project SEKAI 逆向(1): 文件解密及API初步静态分析 分析variant:ColorfulStage 2.4.1 (Google Play 美服) 1. 解密 metadata 利用 Il2CppDumper 对apk中提取出来的global-metadata.data和il2cpp.so直接分析,可见至少metadata有混淆 IDA静态分析libunity.so, 定位到export的il2cpp_init;没有发现有关混淆的处理 考虑直接分析il2cpp.so,定位到global-metadata.dat有关流程 从这里的xref可以很轻松的摸到Il2Cpp的metadata加载流程 (注:部分变量已更名) _BYTE *__fastcall MetadataLoader::LoadMetadataFile(char *a1) { unsigned __int64 v2; // x8 char *v3; // x9 __int64 v4; // x0 _BYTE *v5; // x8 unsigned __int64 v6; // x9 const char *v7; // x0 int v8; // w21 int v9; // w20 _BYTE *mapped_metadata; // x19 __int64 v11; // x8 __int64 v13; // [xsp+0h] [xbp-E0h] BYREF unsigned __int64 v14; // [xsp+8h] [xbp-D8h] char *v15; // [xsp+10h] [xbp-D0h] size_t len[2]; // [xsp+30h] [xbp-B0h] __int64 v17[2]; // [xsp+80h] [xbp-60h] BYREF char *v18; // [xsp+90h] [xbp-50h] char *v19; // [xsp+98h] [xbp-48h] BYREF __int64 v20; // [xsp+A0h] [xbp-40h] unsigned __int8 v21; // [xsp+A8h] [xbp-38h] _BYTE v22[15]; // [xsp+A9h] [xbp-37h] BYREF _BYTE *v23; // [xsp+B8h] [xbp-28h] sub_17A953C(); v19 = "Metadata"; v20 = 8LL; v2 = (unsigned __int64)(unsigned __int8)v13 >> 1; if ( (v13 & 1) !...

January 13, 2025 · 10 min · 1925 words · mos9527