美文网首页
Shader逆向经验总结

Shader逆向经验总结

作者: 离原春草 | 来源:发表于2023-07-25 15:32 被阅读0次

最近在做Shader的逆向还原,我们通过截帧工具(如RenderDoc)抓取到的Shader基本上是类似于汇编的指令,如果想要还原成含义比较明确的高级语言语法,需要费一番心思去琢磨,为了方便后续工作,特此将相关经验进行记录。

1. 根据贴图(顶点色)进行解析

1.1 输出贴图

通过Edit Shader功能,可以将贴图采样的结果(或者顶点属性)直接展示在RenderDoc截帧的效果上,据此可以推断每个贴图或者顶点色的含义

如将某个顶点属性输出可以判断这个属性中存储的是法线:

法线

如将某个贴图的某个通道输出,可以判断这个通道是用于标注衣服的:

1.2 输入贴图

由于RenderDoc截帧的DrawCall中包含了输入贴图,现有的渲染管线中,常见的渲染公式数目是有限的,可以通过对公式进行匹配来推测每张贴图的作用。

1.2.1 PBR

参考[1],PBR的贴图只包含材质的固有属性数据,不包含场景光照数据,比较好辨认,常用的计算方式有两种,分别是:

  1. 基于Metal+Roughness(金属度+粗糙度)的计算方式
  • 有的地方会用Smoothness来替代Roughness,两者是x与1-x的关系,本质上无区别
  • Metallic贴图,黑色表示电介质,白色表示纯金属
  • Roughness贴图,黑色表示光滑(对应区域会有小而亮的高光),白色表示粗糙(对应区域会有大而黯淡的高光)
  1. 基于Specular+Glossiness(光滑度)的计算方式
  • 这里的Glossiness贴图就跟上一种方式中的Smoothness贴图是对等的(完全相同)
  • Specular贴图中存储的是BRDF中的F0,是一张三通道的贴图。F0表示的是入射光垂直于物体表面入射时的镜面反射率(高光强度),对于非金属材质而言,这个数值对于RGB三个分量都是相同的,约等于4%,但是对于金属材质而言,这个数值就是RGB各不相同了,且一般远大于4%,通常会将金属的基色用作F0,其数值可以通过查表来求得
  • Glosiness贴图,黑色表示粗糙,白色表示光滑

PBR有如下的一些特征:

  • PBR默认金属没有漫反射,所以在Diffuse/BaseColor上,金属部位是纯黑的
  • 遵循能量守恒,金属度越高的地方,镜面反射越强,漫反射越弱,即Metal越大的地方,Diffuse颜色就越暗

上述两种流派中,金属度方案使用较广,原因是使用的Metalness只需要一个通道存储,而Specular则需要三个通道,此外,对于美术同学来说,这种方式也更为友好。

两种方案中的基色贴图分别命名为BaseColor跟Diffuse,表明这两者是存在区别的,简单来说,BaseColor是一种复合贴图,其存储的数据是去除光照后的材质基础属性,且会跟随部位的属性而变化:

  1. 对于非导体(金属)而言,其数值表示的是材质的漫反射颜色(Diffuse/Albedo,另外由于一般认为,光线打在金属表面上,进入到金属内部的光线是不会再折射出来,因此认为金属材质的漫反射为0)
  2. 对于导体而言,这里存储的就是F0(即光线与垂直与表面的方向入射到表面上,镜面反射的比例,一般非导体的F0固定为0.04)
    正因为这个贴图中的数据的解释方式随着材质会有所不同,因此需要配合金属度贴图来做解释:
    F0 = lerp(0.04, BaseColor, metalness)

更多请参考[1] & [2]

2. 根据已知变量进行解析

这个比较好理解,类似于拼图,基于已有的变量名来推断与之有关联的其他变量的含义。另外,Shader逆向的时候,如果对Constant Buffer参数的含义完全没有头绪,可以看看其他DrawCall的逆向结果,实际上,同一帧的多个draw call之间的constant buffer数据存在一定程度的复用,所以变量的含义有很大概率会是相同的

3. 根据参数进行解析

这个也相对好理解,根据变量的取值,我们可以大概推断出其作用:

  • 如果是单位向量,那么这个变量可能是用于表征方向的
  • 如果是多个向量(一般是3个或者4个)与某个向量相乘(mad)来得到另一个向量,那么这些参数向量可能是矩阵,用于构成某个变换。针对矩阵,这里推荐一个在线的矩阵计算工具,基于这个工具,可以对矩阵做一些快速的运算,来验证两个矩阵之间的关系(比如判断是否彼此是逆矩阵之类)

4. 根据公式进行解析

一些常用的公式,有对应的固定的汇编格式,下面将目前整理的一些公式做一下总结

lerp

31: add r5.xyz, cb2[16].xyzx, -cb2[17].xyzx
32: mad r5.xyz, r2.wwww, r5.xyzx, cb2[17].xyzx

r5.xyz = lerp(cb2[17].xyz, cb2[16].xyz, r2.w)

smoothstep

173: mad r1.x, r1.w, l(0.5000), l(-0.4000)
174: mul_sat r1.x, r1.x, l(5.0000)
175: mad r1.z, r1.x, l(-2.0000), l(3.0000)
176: mul r1.x, r1.x, r1.x
177: mul r1.w, r1.x, r1.z

r1.w = smoothstep(0.8, 1.2, r1.w)

Matrix Transform

 0: mul r0.xyz, v0.yyyy, cb1[1].xyzx
1: mad r0.xyz, cb1[0].xyzx, v0.xxxx, r0.xyzx
2: mad r0.xyz, cb1[2].xyzx, v0.zzzz, r0.xyzx
3: add r0.xyz, r0.xyzx, cb1[3].xyzx

Matrix = [cb1[0].xyz; cb1[1].xyz; cb1[2].xyz; cb1[3].xyz];
Pos = v0.xyz;
TransformedPos = Matrix * Pos

Cross Product

32: mul r5.xyz, r3.zxyz, r4.yzxy
33: mad r5.xyz, r3.yzxy, r4.zxyz, -r5.xyzx

r5.xyz = cross(r3.xyz, r4.xyz)

5. 对变量作图进行解析

当某个变量一时难以判断其作用,但是又知道其自变量的取值范围时,可以通过绘制x-y曲线图来推测其含义:

如上图是对ShadowMap采样的坐标进行变换后得到的某个变量跟随采样坐标变化的曲线,这个曲线在0.5(对应于Shadowmap各像素的中心位置)取最大值,其余位置均随着自变量的增加而衰减,那么可以推测这个数值有可能是用于消除自阴影而增加的shadow depth bias。

参考

[1]. PBR贴图基础知识
[2]. PBR基础(两大流程中的贴图标准)

相关文章

网友评论

      本文标题:Shader逆向经验总结

      本文链接:https://www.haomeiwen.com/subject/kqlwudtx.html