Unity-shader- game rendering effect reverse analysis


title: unity-shader-reverse analysis of game rendering effects
categories: Unity3d-Shader
tags: [unity, shader, glsl, reverse]
date: 2022-07-18 18:59:06
comments: false
mathjax: true
toc: true

Reverse analysis of game rendering effect


Prequel

It’s all for copying other people’s effects, using software such as snapdragon profiler to capture a certain frame rendered by other people’s games, and restore it to the shader code of the corresponding engine through glsl reverse engineering.

There must be a comparison when restoring, for example, to restore a game made by unity, you can first write some shaders, pack it and use snapdragon to see what kind of glsl the function of the unity shader finally renders when rendering, and then face the one that needs to be reversed The game pushes back to the shader of unity.


Reverse of various functions

normalize normalization

// normalize(_WorldSpaceLightPos0.xyz)

u_xlat0.x = dot(_WorldSpaceLightPos0.xyz, _WorldSpaceLightPos0.xyz);
u_xlat0.x = inversesqrt(u_xlat0.x);
u_xlat0.xyz = u_xlat0.xxx * _WorldSpaceLightPos0.xyz;

UnityObjectToWorldNormal

// UnityObjectToWorldNormal(v.normal)

u_xlat1.x = dot(in_NORMAL0.xyz, unity_Builtins0Array[u_xlati0 / 8].hlslcc_mtx4x4unity_WorldToObjectArray[0].xyz);
u_xlat1.y = dot(in_NORMAL0.xyz, unity_Builtins0Array[u_xlati0 / 8].hlslcc_mtx4x4unity_WorldToObjectArray[1].xyz);
u_xlat1.z = dot(in_NORMAL0.xyz, unity_Builtins0Array[u_xlati0 / 8].hlslcc_mtx4x4unity_WorldToObjectArray[2].xyz);
u_xlat0.x = dot(u_xlat1.xyz, u_xlat1.xyz);
u_xlat0.x = inversesqrt(u_xlat0.x);
u_xlat0.xyz = u_xlat0.xxx * u_xlat1.xyz;

UnityObjectToClipPos

// UnityObjectToClipPos(v.vertex);

u_xlat1 = in_POSITION0.yyyy * unity_Builtins0Array[u_xlati0 / 8].hlslcc_mtx4x4unity_ObjectToWorldArray[1];
u_xlat1 = unity_Builtins0Array[u_xlati0 / 8].hlslcc_mtx4x4unity_ObjectToWorldArray[0] * in_POSITION0.xxxx + u_xlat1;
u_xlat1 = unity_Builtins0Array[u_xlati0 / 8].hlslcc_mtx4x4unity_ObjectToWorldArray[2] * in_POSITION0.zzzz + u_xlat1;
u_xlat1 = u_xlat1 + unity_Builtins0Array[u_xlati0 / 8].hlslcc_mtx4x4unity_ObjectToWorldArray[3];
u_xlat2 = u_xlat1.yyyy * hlslcc_mtx4x4unity_MatrixVP[1];
u_xlat2 = hlslcc_mtx4x4unity_MatrixVP[0] * u_xlat1.xxxx + u_xlat2;
u_xlat2 = hlslcc_mtx4x4unity_MatrixVP[2] * u_xlat1.zzzz + u_xlat2;
u_xlat1 = hlslcc_mtx4x4unity_MatrixVP[3] * u_xlat1.wwww + u_xlat2;
gl_Position = u_xlat1;

saturate

// saturate
#ifdef UNITY_ADRENO_ES3
    u_xlat0.x = min(max(u_xlat0.x, 0.0), 1.0);
#else
    u_xlat0.x = clamp(u_xlat0.x, 0.0, 1.0);
#endif

size comparison

// bool a = b < c.x;
#ifdef UNITY_ADRENO_ES3
    u_xlatb1 = !!(u_xlat16_14<u_xlat16_0.x);
#else
    u_xlatb1 = u_xlat16_14<u_xlat16_0.x;
#endif

variable

intensive reading

uniform mediump float -> half (medium intensive)


input Output

in mediump vec4 in_POSITION0;
in mediump vec3 in_NORMAL0;
in mediump vec2 in_TEXCOORD0;

// 对应 unity
struct appdata_t {
    
    
    half4 vertex : POSITION;
    half3 normal : NORMAL;
    half2 texcoord : TEXCOORD0;
};

output

out mediump vec2 vs_TEXCOORD0;
out mediump vec3 vs_TEXCOORD1;

// 对应 unity
struct v2f {
    
    
    half4 vertex : SV_POSITION; // unity 必要的属性
    half2 texcoord : TEXCOORD0;
    half3 tex02 : TEXCOORD1;
};

uniform

uniform 	vec4 _WorldSpaceLightPos0; // unity 内置的世界空间下的 灯光位置

uniform 	mediump vec4 _Tint;
uniform 	mediump vec4 _ColorLight;
uniform 	mediump vec4 _ColorUnlight;
uniform 	mediump float _SplitThreshold;

// 对应 unity
_Tint("Tint", Color) = (1,1,1,1)
_ColorLight("ColorLight", Color) = (1,1,0,1)
_ColorUnlight("ColorUnlight", Color) = (0,0,0,1)
_SplitThreshold("SplitThreshold", float) = 1
            
half4 _Tint;
half4 _ColorLight;
half4 _ColorUnlight;
half _SplitThreshold;

Example 01 - Bird Soul

Room playing card diagram

image-20220721163816269

Test shader git address:[email protected]:yangxuan0261/tdmj_shader.git

The main thing to look at is the processing of the following parts

  1. To the light/backlight part
  2. stroke
  3. shadow

1. First find out the rendering of the card body

Directly modify the fs rgb value to a certain value, it is easy to find the rendering batch of the card body

asd

You can see that the rendering of the card body is separated from the stroke


2. Stroke

asd

Enlarge the body of the card, remove the front side when the shader processes it, and only render the back side. Due to the depth relationship, it is blocked by the normal card body, and the stroke effect comes out.

And all the enlarged models of the cards can also be processed in one batch.

image-20220721165110995


3. Shadow

sdf


Guess you like

Origin blog.csdn.net/yangxuan0261/article/details/125946318