RenderDoc[03] 还原粒子特效shader
对于未加密的ab,可以用对应版本的unity load出来。
模型可以正常显示,但是粒子特效使用的是自制shader,所以显示为红色。
这次的目标是还原粒子特效shader。
最终还原效果如下图:本文转自https://huutu.blog.csdn.net/article/details/112307325
1.查找对应shader代码
选中粒子特效后,在属性面板可以看到shader名字。
例如上图粒子特效,使用shader名为 Basic Additive。
在RenderDoc中找到shader资源。本文转自https://huutu.blog.csdn.net/article/details/112307325
来看动图本文转自https://huutu.blog.csdn.net/article/details/112307325
2.创建shader
在unity中新建Unlit shader。
根据属性面板,添加对应Property。
Properties{ [HDR] _TintColor("Tint Color", Color) = (1,1,1,1) _MainTex ("Particle Texture", 2D) = "white" {} _UVScroll("UV Scroll", Vector) = (0,0,0,0)}
并添加透明处理
SubShader { //透明处理 Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane" } Blend SrcAlpha One LOD 100
然后在Pass中引入新添加的Property。
Pass{ ...... sampler2D _MainTex; float4 _MainTex_ST; //引入新添加的Property float4 _UVScroll; float4 _TintColor;
3.还原顶点shader
乍一看,代码多又乱,但是之前已经解释过了,这里的代码都是经过展开的,还原回Unity就是几行代码。
整理一下
#version 300 esuniform vec4 _Time;uniform vec4 hlslcc_mtx4x4unity_ObjectToWorld[4];uniform vec4 hlslcc_mtx4x4unity_MatrixVP[4];uniform mediump vec4 _MainTex_ST;uniform mediump vec2 _UVScroll;in mediump vec4 in_POSITION0;in mediump vec4 in_COLOR0;in mediump vec2 in_TEXCOORD0;out mediump vec4 vs_COLOR0;out mediump vec2 vs_TEXCOORD0;vec4 u_xlat0;vec4 u_xlat1;mediump vec2 u_xlat16_2;void main(){ u_xlat0 = in_POSITION0.yyyy * hlslcc_mtx4x4unity_ObjectToWorld[1]; u_xlat0 = hlslcc_mtx4x4unity_ObjectToWorld[0] * in_POSITION0.xxxx u_xlat0; u_xlat0 = hlslcc_mtx4x4unity_ObjectToWorld[2] * in_POSITION0.zzzz u_xlat0; u_xlat0 = u_xlat0 hlslcc_mtx4x4unity_ObjectToWorld[3]; u_xlat1 = u_xlat0.yyyy * hlslcc_mtx4x4unity_MatrixVP[1]; u_xlat1 = hlslcc_mtx4x4unity_MatrixVP[0] * u_xlat0.xxxx u_xlat1; u_xlat1 = hlslcc_mtx4x4unity_MatrixVP[2] * u_xlat0.zzzz u_xlat1; u_xlat0 = hlslcc_mtx4x4unity_MatrixVP[3] * u_xlat0.wwww u_xlat1;//上面这几行代码就是做了顶点变换,相当于//o.vertex = UnityObjectToClipPos(v.vertex); gl_Position = u_xlat0; vs_COLOR0 = in_COLOR0;//传递顶点色到片段shader u_xlat16_2.xy = in_TEXCOORD0.xy * _MainTex_ST.xy _MainTex_ST.zw;//相当于 o.uv = TRANSFORM_TEX(v.uv, _MainTex); u_xlat0.xy = _Time.xx * _UVScroll.xy u_xlat16_2.xy;//uv滚动 vs_TEXCOORD0.xy = u_xlat0.xy; return;}
其实需要处理的的代码就两行。
vs_COLOR0 = in_COLOR0;//传递顶点色到片段shader
u_xlat0.xy = _Time.xx * _UVScroll.xy u_xlat16_2.xy;//uv滚动
在新创建的shader中,加上这两行的逻辑。
v2f vert (appdata v){ v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); UNITY_TRANSFER_FOG(o,o.vertex); o.vertexcolor = v.vertexcolor;//传递顶点色到片段shader o.uv.xy = _Time.xx * _UVScroll.xy o.uv.xy;//uv滚动 return o;}
4.还原片段shader
代码不多,但是变量名很乱,比较难看,进行梳理。
#version 300 esprecision highp float;precision highp int;uniform mediump vec4 _TintColor;uniform mediump sampler2D _MainTex;in mediump vec4 vs_COLOR0;in mediump vec2 vs_TEXCOORD0;layout(location = 0) out mediump vec4 SV_Target0;mediump vec4 u_xlat16_0;mediump vec4 u_xlat16_1;void main(){ u_xlat16_0 = vs_COLOR0 vs_COLOR0;//顶点色叠加 u_xlat16_1 = texture(_MainTex, vs_TEXCOORD0.xy);//采样 u_xlat16_0 = u_xlat16_0 * u_xlat16_1;//采样颜色 和 叠加的顶点色 混合 u_xlat16_0 = u_xlat16_0 * _TintColor;//再和 _TintColor 混合 SV_Target0 = u_xlat16_0; return;}
在自己创建的shader里面实现
fixed4 frag(v2f i) : SV_Target{ //对顶点色叠加一次 fixed4 vertexcolor = i.vertexcolor i.vertexcolor;//顶点色叠加 // sample the texture fixed4 col = tex2D(_MainTex, i.uv);//采样 vertexcolor = vertexcolor * col;//采样颜色 和 叠加的顶点色 混合 vertexcolor = vertexcolor * _TintColor;//再和 _TintColor 混合 col = vertexcolor; // apply fog UNITY_APPLY_FOG(i.fogCoord, col); return col;}
这样就还原了shader。
完整的shader如下:
Shader "Effect/Basic Additive"{ Properties { [HDR] _TintColor("Tint Color", Color) = (1,1,1,1) _MainTex ("Particle Texture", 2D) = "white" {} _UVScroll("UV Scroll", Vector) = (0,0,0,0) } SubShader { //透明处理 Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane" } Blend SrcAlpha One LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; float4 vertexcolor : COLOR0; }; struct v2f { float2 uv : TEXCOORD0; UNITY_FOG_COORDS(1) float4 vertex : SV_POSITION; float4 vertexcolor : COLOR0; }; sampler2D _MainTex; float4 _MainTex_ST; //引入新添加的Property float4 _UVScroll; float4 _TintColor; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); UNITY_TRANSFER_FOG(o,o.vertex); o.vertexcolor = v.vertexcolor;//传递顶点色到片段shader o.uv.xy = _Time.xx * _UVScroll.xy o.uv.xy;//uv滚动 return o; } fixed4 frag(v2f i) : SV_Target { //对顶点色叠加一次 fixed4 vertexcolor = i.vertexcolor i.vertexcolor;//顶点色叠加 // sample the texture fixed4 col = tex2D(_MainTex, i.uv);//采样 vertexcolor = vertexcolor * col;//采样颜色 和 叠加的顶点色 混合 vertexcolor = vertexcolor * _TintColor;//再和 _TintColor 混合 col = vertexcolor; // apply fog UNITY_APPLY_FOG(i.fogCoord, col); return col; } ENDCG } }}
5.更加复杂的shader
还原的过程中遇到更复杂的shader,逻辑代码量有个20多行,看起来有点头大。
如果只是为了还原个七七八八,可以尝试只还原而不是弄懂。
本文转自https://huutu.blog.csdn.net/article/details/112307325
直接拷贝逻辑代码,然后将glsl标记替换为cg标记。
这里先提供几个我遇到的。
#define vec4 fixed4#define vec3 fixed3#define vec2 fixed2#define mix lerp#define texture tex2D
放在 CGPROGRAM
后面就可以。
6.发现问题
1.RenderDoc资源列表有多份同名的shader,会对应不同的shader代码。暂不清楚原因,后续跟进。
2.粗糙还原出来shader的效果和原来游戏并不一致。
7.参考博文
修改 UV 坐标实现纹理贴图的滚动 模拟水流效果
https://huutu.blog.csdn.net/article/details/50953900
Unity Shader 结构函数内置变量
https://zhuanlan.zhihu.com/p/132607912
GLSL转换HLSL
https://blog.csdn.net/u010778229/article/details/107488048
opengl shader函数
https://www.shaderific.com/glsl-functions/