使用Unity3D实现选中物体消融特效的方法详解

  Shader "MyShader/DissolveEffect" {

  Properties {

  _MainTex("Main Tex", 2D) = "white" {} // 主纹理

  _Color("Color", Color) = (1, 1, 1, 1) // 模型颜色

  _NoiseTex("Noise Tex", 2D) = "white"{} // 噪声纹理

  _BurnAmount("Burn Amount", Range(0, 1)) = 0 // 燃烧量, 值越大模型镂空的越多

  _LineWidth("Burn Line Width", Range(0, 0.2)) = 0.1 // 燃烧的线条宽度

  _BurnOuterColor("Burn Outer Color", Color) = (1, 0, 0, 1) // 燃烧线条的外侧颜色

  _BurnInnerColor("Burn Inner Color", Color) = (1, 0, 0, 1) // 燃烧线条的内侧颜色

  }

  SubShader {

  Tags { "RenderType"="Opaque" "Queue"="Geometry"}

  Pass {

  Tags { "LightMode"="ForwardBase" }

  Cull Off // 关闭剔除, 正反面都渲染, 因为消融会裸漏模型内部结构

  CGPROGRAM

  #include "Lighting.cginc"

  #pragma vertex vert

  #pragma fragment frag

  sampler2D _MainTex; // 主纹理

  fixed4 _Color; // 模型颜色

  sampler2D _NoiseTex; // 噪声纹理

  fixed _BurnAmount; // 燃烧量, 值越大模型镂空的越多

  fixed _LineWidth; // 燃烧的线条宽度

  fixed4 _BurnOuterColor; // 燃烧线条的外侧颜色

  fixed4 _BurnInnerColor; // 燃烧线条的内侧颜色

  float4 _MainTex_ST; // _MainTex的缩放和偏移

  float4 _NoiseTex_ST; // _NoiseTex的缩放和偏移

  struct a2v {

  float4 vertex : POSITION; // 模型空间顶点坐标

  float3 normal : NORMAL; // 模型空间顶点法线向量

  float4 texcoord : TEXCOORD0; // 顶点纹理坐标

  };

  struct v2f {

  float4 pos : SV_POSITION; // 裁剪空间顶点坐标

  float3 normal : Normal; // 世界空间顶点法线向量

  half2 uvMainTex : TEXCOORD0; // 主纹理的纹理坐标

  half2 uvNoiseTex : TEXCOORD1; // 噪声纹理的纹理坐标

  float3 worldPos : TEXCOORD2; // 世界空间顶点坐标

  };

  v2f vert(a2v v) {

  v2f o;

  o.pos = UnityObjectToClipPos(v.vertex); // 模型空间顶点坐标变换到裁剪空间, 等价于: mul(UNITY_MATRIX_MVP, v.vertex)

  o.normal = UnityObjectToWorldNormal(v.normal); // 将模型空间法线向量变换到世界空间(已归一化)

  o.uvMainTex = TRANSFORM_TEX(v.texcoord, _MainTex); // 主纹理坐标缩放和偏移

  o.uvNoiseTex = TRANSFORM_TEX(v.texcoord, _NoiseTex); // 噪声纹理坐标缩放和偏移

  o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; // 将模型空间顶点坐标变换到世界空间

  return o;

  }

  fixed4 frag(v2f i) : SV_Target {

  fixed noise = tex2D(_NoiseTex, i.uvNoiseTex).r; // 噪声采样

  float factor = noise - _BurnAmount;

  clip(factor); // 剔除factor小于0的片元, 即: if(factor < 0) discard;

  fixed3 lightDir = normalize(UnityWorldSpaceLightDir(i.worldPos)); // 世界空间灯光向量

  fixed4 albedo = tex2D(_MainTex, i.uvMainTex) * _Color; // 模型颜色

  fixed4 ambient = UNITY_LIGHTMODEL_AMBIENT * albedo; // 环境光颜色

  fixed4 diffuse = _LightColor0 * albedo * max(0, dot(i.normal, lightDir)); // 漫反射光颜色

  fixed t = smoothstep(0, _LineWidth, factor);

  fixed4 burnColor = lerp(_BurnOuterColor, _BurnInnerColor, t);

  fixed4 finalColor = lerp(burnColor, ambient + diffuse, t);

  return fixed4(finalColor.xyz, 1);

  }

  ENDCG

  }

  }

  FallBack "Diffuse"

  }