如何使用端游工具分析外部Android手游渲染
发表于2016-04-13
一、写在前面
我只有6年的端游开发经验,除了业余时间捣鼓一下手游开发,没有在工作中实际的参与手游开发。所以,下面的分析过程,更多的是从端游的角度去分析手游的渲染流程。Nsight和GPA的用法就不详细介绍了,可能会跳过许多的操作步骤。
二、摘要
最终结果使用NSight截取了一帧Android游戏,存储,回放都没有问题,所有的渲染资源,包括模型,贴图,Shader,调用序列都能正确还原。下面的截图,是"乱斗西游" 初始关卡的场景。
GPA也可用于分析,但是会有一部分的渲染资源无法还原。下面的截图,也是乱斗西游" 初始关卡的场景。
三、过程
1、软件准备
Intel GPA, NVIDIA Nsight, BlueStacks
没有去仔细试过每一个软件的版本兼容性,我这里的环境是,Intel GPA 2014 R2,NSight 3.2,BlueStacks 0.98.
2、截取BlueStacks的渲染帧
NSight
a、无法直接使用VS的启用External Program附件NSight上去, 而是需要使用NSight Hud附加。
b、启动后,已经可以看到Nsight附加,此时已经可以看到绘制信息
c、Ctrl+Z, Space, Save Capture
Save Capture的目的有两个,1.是为了在VS中打开,拥有更详细的渲染信息,例如Shader信息,模型信息; 2. 是为了能够以后直接起动截帧就好,无需再次启动游戏.
如果满足与查看一下贴图和渲染序列,那么此时已经可以达到要求,此时可以像PerfHud一样,拖动时间轴,浏览Draw Call
d、找到Save的帧(Nsight Save的帧其实是一个D3D工程),一般的路径在¥Documents¥NVIDIA Nsight¥Captures, 在VS里添加工程
e、此时工程可以编译通过,但是无法运行,一旦运行就会退出,可能会有各种原因,但是问题目前已经回到了一个基础的D3D程序范畴。
针对我这个版本的截帧,需要手动修改一下CPP文件,因为生成的CPP多创建了一个Windows窗口,注释掉他
f、重新编译工程,再运行,就是一个Native的D3D程序了:
g、此时已经可以想调试D3D Native程序一样调试它了。
h、简单分析一下主地表的绘制吧
贴图和模型就不细说了,主要看看Pixel Shader,主要是比较简单,实例足够了:
//
// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20499
//
// Parameters:
//
// sampler2D _SamplerDiffuse0;
// sampler2D _SamplerLightmap1;
// float _blendValue;
//
//
// Registers:
//
// Name Reg Size
// ----------------- ----- ----
// _blendValue c3 1
// _SamplerDiffuse0 s0 1
// _SamplerLightmap1 s1 1
//
ps_3_0
dcl_texcoord v0.xy
dcl_texcoord1 v1.xy
dcl_2d s0
dcl_2d s1
texld r0, v1, s1
texld r1, v0, s0
mul r0.xyz, r0, r1
mul oC0.w, r1.w, c3.x
add oC0.xyz, r0, r0
// approximately 5 instruction slots used (2 texture, 3 arithmetic)
我们可以看到,BlueStacks已经把GLSL的Shader ASM转成了HLSL的Shader ASM了,变量名之类的都保留了。
Shader ASM的阅读肯定会比直接的Shader效率会低,HLSL 的 Shader ASM可以参考下面的文章:
https://msdn.microsoft.com/en-us/library/windows/desktop/bb219840(v=vs.85).aspx
我们看到他的Pixel Shader, 使用了一个BlendValue,c3. 为 1,通过参数表可查:
DiffuseMap的W分量都为1
所以OutputColor.w = DiffuseMap.W x 1 = 1
而RGB Color的输出却比较奇怪,输出的颜色是两倍DiffuseColor X LightMap:
OutputColor.RGB = Diffuse X LightMap + Diffuse X LightMap.
仔细查看了一下光图的数值,发现这样相加并不会溢色,因为即使光图中最亮的部分,他的值都小于<0.6.
只是觉得,直接把光图的亮度提高一倍就可以解决这个问题,不知道为什么Shader里多加了一次。
关于上面的乘以2的问题,在unity的论坛有关于它的讨论,大概的原因是为了兼容unity以前的版本所以才这样做的,后面的unity5里已经去掉了。
四、GPA截取
1、GPA的截取比较快捷,直接勾上Auto-Detect选项,然后双击运行游戏
2、截取帧并分析,Ctrl+Shift+C后,截取一帧,并打开:
3、我们看到丢失了一部分Draw的信息,例如后半段UI的绘制过程,他直接变成了一个DrawCall
实际的绘制其实不是这样的,NSight的截取的帧里的UI绘制信息是正确的,如下图,并不是一个全屏的DrawCall:
五、总结
所以,通过端游方法分析PC上运行的Android游戏,方法上是可行的,所有的渲染信息几乎都保留了下来,可以方便的参考原型,制作美术规范等工作。