申明:本文内容仅供个人学习,请勿转载。
NPR——卡通渲染
本文的目标是在“NPR——开通渲染(一)”的基础之上尝试“靠近”《崩坏3》的角色渲染表现。
1.1《崩坏3》
1.1.1 游戏抓帧
(游戏截图)
本文主要学习研究的对象同样是《崩坏3》的角色卡通渲染技术,使用工具对《崩坏3》抓帧,基本内容如引文 [1] 和 [2] 所介绍的一样:
(身体部分绘制)
身体部分的 DrawCall 使用了两个纹理,如下图:
(Application Input)
上图看到有两个纹理,一个主纹理(漫反射纹理),一个 LightMap——如引文 [1] 和 [2] 所述,一个特殊的纹理,三个通道分别存储了不同的信息,比如高光 Mask、高光颜色以及阴影 Mask。
1.1.2 Shader 翻译
没有使用 Adreno Profile,不知道 [1] 和 [2] 作者是否人肉翻译出来的 Shader,本文获得的部分 Vertex\Pixel DXBC 如下:
// Vertex Shader DirectX Bytecode
// Generated by Microsoft (R) HLSL Shader Compiler 10.1
//
//
// Buffer Definitions:
//
// cbuffer $Globals
// {
//
// float4 __BloomMaskTex_ST; // Offset: 0 Size: 16
// float __DitherAlpha; // Offset: 16 Size: 4
// float4 __ProjectionParams; // Offset: 32 Size: 16
// float __UsingBloomMask; // Offset: 48 Size: 4
// float __UsingDitherAlpha; // Offset: 64 Size: 4
// float4 __WorldSpaceLightPos0; // Offset: 80 Size: 16
// float4x4 _unity_MatrixVP; // Offset: 96 Size: 64
// float4x4 _unity_ObjectToWorld; // Offset: 160 Size: 64
// float4x4 _unity_WorldToObject; // Offset: 224 Size: 64
//
// }
//
//
// Resource Bindings:
//
// Name Type Format Dim HLSL Bind Count
// ------------------------------ ---------- ------- ----------- -------------- ------
// $Globals cbuffer NA NA cb0 1
//
//
//
// Input signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// TEXCOORD 0 xyzw 0 NONE float xyzw
// TEXCOORD 1 xyzw 1 NONE float xyzw
// TEXCOORD 2 xyz 2 NONE float xyz
// TEXCOORD 3 xyzw 3 NONE float xy
//
//
// Output signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_Position 0 xyzw 0 POS float xyzw
// TEXCOORD 7 xyzw 1 NONE float xyzw
// TEXCOORD 0 xyzw 2 NONE float xyzw
// TEXCOORD 1 xyzw 3 NONE float xyzw
// TEXCOORD 2 xyz 4 NONE float xyz
// TEXCOORD 6 w 4 NONE float w
// TEXCOORD 3 xyz 5 NONE float xyz
// TEXCOORD 4 xy 6 NONE float xy
// TEXCOORD 5 zw 6 NONE float zw
//
vs_5_0
dcl_globalFlags refactoringAllowed
dcl_constantbuffer CB0[17], immediateIndexed
dcl_input v0.xyzw
dcl_input v1.xyzw
dcl_input v2.xyz
dcl_input v3.xy
dcl_output_siv o0.xyzw, position
dcl_output o1.xyzw
dcl_output o2.xyzw
dcl_output o3.xyzw
dcl_output o4.xyz
dcl_output o4.w
dcl_output o5.xyz
dcl_output o6.xy
dcl_output o6.zw
dcl_temps 3
...
...
...
// Pixle Shader DirectX Bytecode
// Generated by Microsoft (R) HLSL Shader Compiler 10.1
//
//
// Buffer Definitions:
//
// cbuffer $Globals
// {
//
// float __BloomFactor; // Offset: 0 Size: 4
// float4 __Color; // Offset: 16 Size: 16
// float4x4 __DITHERMATRIX; // Offset: 32 Size: 64
// float __Emission; // Offset: 96 Size: 4
// float __EmissionBloomFactor; // Offset: 112 Size: 4
// float4 __EmissionColor; // Offset: 128 Size: 16
// float3 __FirstShadowMultColor; // Offset: 144 Size: 12
// float __LightArea; // Offset: 160 Size: 4
// float3 __LightSpecColor; // Offset: 176 Size: 12
// float4 __ScreenParams; // Offset: 192 Size: 16
// float __SecondShadow; // Offset: 208 Size: 4
// float3 __SecondShadowMultColor; // Offset: 224 Size: 12
// float __Shininess; // Offset: 240 Size: 4
// float __SpecMulti; // Offset: 256 Size: 4
// float __UsingBloomMask; // Offset: 272 Size: 4
// float __UsingDitherAlpha; // Offset: 288 Size: 4
// float3 __WorldSpaceCameraPos; // Offset: 304 Size: 12
// float4 __WorldSpaceLightPos0; // Offset: 320 Size: 16
//
// }
//
//
// Resource Bindings:
//
// Name Type Format Dim HLSL Bind Count
// ------------------------------ ---------- ------- ----------- -------------- ------
// samplers2D[0] sampler NA NA s0 1
// samplers2D[1] sampler NA NA s1 1
// samplers2D[2] sampler NA NA s2 1
// textures2D[0] texture float4 2d t0 1
// textures2D[1] texture float4 2d t1 1
// textures2D[2] texture float4 2d t2 1
// $Globals cbuffer NA NA cb0 1
//
//
//
// Input signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_Position 0 xyzw 0 POS float
// TEXCOORD 7 xyzw 1 NONE float
// TEXCOORD 0 xyzw 2 NONE float x
// TEXCOORD 1 xyzw 3 NONE float xyzw
// TEXCOORD 2 xyz 4 NONE float xyz
// TEXCOORD 6 w 4 NONE float w
// TEXCOORD 3 xyz 5 NONE float xyz
// TEXCOORD 4 xy 6 NONE float xy
// TEXCOORD 5 zw 6 NONE float zw
//
//
// Output signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_TARGET 0 xyzw 0 TARGET float xyzw
//
ps_5_0
dcl_globalFlags refactoringAllowed
dcl_immediateConstantBuffer { { 1.000000, 0, 0, 0},
{ 0, 1.000000, 0, 0},
{ 0, 0, 1.000000, 0},
{ 0, 0, 0, 1.000000} }
dcl_constantbuffer CB0[21], immediateIndexed
dcl_sampler s0, mode_default
dcl_sampler s1, mode_default
dcl_sampler s2, mode_default
dcl_resource_texture2d (float,float,float,float) t0
dcl_resource_texture2d (float,float,float,float) t1
dcl_resource_texture2d (float,float,float,float) t2
dcl_input_ps linear v2.x
dcl_input_ps linear v3.xyzw
dcl_input_ps linear v4.xyz
dcl_input_ps linear v4.w
dcl_input_ps linear v5.xyz
dcl_input_ps linear v6.xy
dcl_input_ps linear v6.zw
dcl_output o0.xyzw
dcl_temps 5
...
...
...
从第二段代码 Pixle Shader DirectX Bytecode 来看确实如 [1] 和 [2] 所展示的逆向分析结果一样,《崩坏3》的着色大致是 FirstShadow + Second Shadow + Spcular + Bloom。
Vertex DXBC
接下来尝试转译成方便阅读的伪代码,先看 Vertex DXBC,dcl_input v0 到 v3 四个寄存器输入信息应该分别是 position,color,normal 和 uv,dcl_output 输出寄存器中最起码也包含了这四项,剩下的三个输出寄存器中我们来看代码:
mov r0.xyz, v0.xyzx
mov r0.w, l(1.000000)
dp4 r1.x, cb0[10