UnityShader_两层Fresnel表现外发光
  • 以前工作中的一个案例,使用两个Pass , 都使用Fresnel,来表现外发光效果

  • 然后最后的效果:


/*
UnityShader - 5.3

星球Shader
两个Pass
   1 做星球表面 Diff/Norm/Spec/Rim
   2 做星球外发光环, Rim + Transparent
*/

Shader "TAShaders/TEST/Planet"
{
   Properties
   {
       _Color      ("Color", Color) = (1, 1, 1, 1)
       _MainTex    ("Main Tex", 2D) = "grey" {}
       
       // Specular
       _Specular ("Specular", Color) = (1, 1, 1, 1)
       _Gloss ("Gloss", Range(0.1, 256)) = 20

       // Normal
       _BumpMap ("Normal Map", 2D) = "bump" {}
       //_BumpScale ("Bump Scale", Float) = 1.0

       // Rim
       _RimColor       ("RimColor", Color) = (1, 1, 1, 1)
       _RimPower       ("RimPower", Range(0, 15)) = 10
       _RimMulitpiler  ("RimMultipiler", Range(0, 15)) = 10

       // Extrusion
       _Extrusion ("Extrusion", Range(0, 10)) = 1

       // Panner
       _PannerXSpeed ("PanX Speed", Float) = 0

   }

   SubShader
   {
       // 第1个Pass,做基本的Diff/Norm/Spec/ + Rim
       Pass
       {
           Cull Back
           Tags { "RenderType"="Opaque" "LightMode"="ForwardBase" }
           CGPROGRAM
           #pragma multi_compile_fwdbase  
           #pragma vertex vert
           #pragma fragment frag
           #include "UnityCG.cginc"
           #include "Lighting.cginc"
           //#include "AutoLight.cginc"

           // Fog
           //#pragma multi_compile_fog
           fixed4 _Color;
           sampler2D   _MainTex;
           float4      _MainTex_ST;
           
           // Specular
           fixed4      _Specular;
           float       _Gloss;
           
           // Normal
           sampler2D   _BumpMap;
           
           // Rim
           fixed4 _RimColor;
           fixed _RimPower;
           fixed _RimMulitpiler;
           
           // Extrusion
           float _Extrusion;
           
           // UVAnimSpeed
           float _PannerXSpeed;
           
           struct appdata
           {
               float4 vertex   : POSITION;
               float3 normal   : NORMAL;
               float4 tangent  : TANGENT;
               float4 texcoord : TEXCOORD0;
           };
           
           struct v2f
           {
               float4 pos  : SV_POSITION;
               float2 uv   : TEXCOORD0;
               
               // FogCoord
               UNITY_FOG_COORDS(3)
               
               // Normal
               float3 lightDir: TEXCOORD1;
               float3 viewDir : TEXCOORD2;
           };

           v2f vert(appdata v)
           {
               v2f o;
               
               // 做UV动画?,也许另写脚本旋转球体比较理智,UV动画会像是一张皮在球体上滑动
               v.texcoord.x +=  _Time * _PannerXSpeed;
               
               // 投射空间的顶点位置
               o.pos           = mul(UNITY_MATRIX_MVP, v.vertex);
               o.uv            = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
               
               // Fog
               //UNITY_TRANSFER_FOG(o,o.pos);

               TANGENT_SPACE_ROTATION;
               
               // 视图向量与灯光向量转到 切线空间
               o.lightDir  = mul(rotation, ObjSpaceLightDir(v.vertex)).xyz;
               o.viewDir   = mul(rotation, ObjSpaceViewDir(v.vertex)).xyz;
               
               return o;
           }

           fixed4 frag(v2f i) : SV_Target
           {
               // 在切线空间计算法线
               fixed3 tangentLightDir  = normalize(i.lightDir);
               fixed3 tangentViewDir   = normalize(i.viewDir);
               fixed4 packedNormal     = tex2D(_BumpMap, i.uv);
               fixed3 tangentNormal;
               tangentNormal       = UnpackNormal(packedNormal);
               tangentNormal.z     = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));                // Diffuse贴图采样
               fixed3 diff = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
               
               // Lambert
               fixed LM_Lambert =  saturate(dot(tangentNormal, tangentLightDir));
               
               // Ambient颜色
               fixed3 ambient  = UNITY_LIGHTMODEL_AMBIENT.xyz;
               
               // Rim
               fixed rim       = saturate(dot(tangentNormal, tangentViewDir));
               fixed rimPow    = (15 - _RimPower);
               
               // 取了RimPower最大值反向
               fixed rimMulti  = _RimMulitpiler * 0.2;
               
               //
               fixed3 rimColor = pow((1- rim),rimPow) * _RimColor * rimMulti;
               
               // Specular
               fixed3 halfDir = normalize(tangentLightDir + tangentViewDir);
               fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(tangentNormal, halfDir)), _Gloss);
               
               // Final颜色混合
               fixed3 final = (_LightColor0.rgb * diff * LM_Lambert) + (diff * ambient) + specular + rimColor;        
               fixed4 finalColor = fixed4(final,1.0);
               
               // Fog
               //UNITY_APPLY_FOG(i.fogCoord, finalColor);
               return fixed4(finalColor);
           }          
           ENDCG
       }
       
       // 第2个Pass,用作外轮廓发光
       pass
       
       {
           // 使用Transparent排序,不使用ZWrite,
           Tags { "LightMode" = "Always" "Queue"="Transparent" "IgnoreProjector"="True"}

           ZWrite Off
           Lighting Off
           
           // 剔除前面的面
           Cull Front
           
           // 使用 Soft Additive混合
           Blend OneMinusDstColor One
           
           CGPROGRAM
           #pragma vertex vert
           #pragma fragment frag      
           #include "UnityCG.cginc"

           fixed   _Color;
           fixed4  _RimColor;
           fixed   _RimPower;
           fixed   _RimMulitpiler;
           fixed   _Extrusion;
           
           struct appdata
           {
               float4 vertex   : POSITION;  
               float3 normal   : NORMAL;    
               float4 texcoord : TEXCOORD0;
           };
           
           struct v2f
           {
               float4 pos          : SV_POSITION;
               float2 uvMatCap     : TEXCOORD0;    
               float3 worldNormal  : TEXCOORD1;
               float3 worldPos     : TEXCOORD2;
           };

           v2f vert (appdata v)
           {
               // 将顶点沿着法线方向向外推
               v.vertex.xyz += v.normal * (_RimPower * 0.01) * _Extrusion;
               
               v2f o;
               
               o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
               o.worldNormal = mul(v.normal, (float3x3)_World2Object);
               o.worldPos      = mul(_Object2World, v.vertex).xyz;
               return o;
           }

           float4 frag (v2f i) : COLOR
           {
               // N 世界空间法线
               fixed3 worldNormal = normalize(i.worldNormal);
               
               // V 视图向量
               fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
               
               // Rim
               fixed rimMulti = _RimMulitpiler * 0.001f;
               
               // 这里对Rim倍乘做了调整,否则Rim会显得非常亮
               fixed fresnel = 1 - dot(worldNormal, viewDir);
               fixed3 fresnelColor = pow(fresnel,_RimPower) * _RimColor.rgb * rimMulti;
               
               // Final
               fixed3 final = fresnelColor;        
               return fixed4(final,1.0);
           }
           ENDCG
       }
   }
   FallBack "Specular"
}

  • 当然这也能用来表现角色,只是由于角色的模型非球形那么规则,所以沿法线挤出后总会有折叠的部分,但是也能简单的表现一下外发光效果



作者:TAZORN

著作权归作者所有




【相关阅读】:


【上传发布插件】: