参考 https://blog.csdn.net/xiaoge132/article/details/77801931
//全息效果 Shader "Custom/Silhouette" { Properties { _MainTex ("Texture", 2D) = "white" {} _Color("Color", Color) = (1,1,1,1) _DotProduct("Rim effect", Range(-1,1)) = 0.25 } SubShader { Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "LightMode" = "ForwardBase" } LOD 200 Cull Off Pass { Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; //模型空间法线 float3 normal : NORMAL; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; //世界空间法线 float3 worldNormal : TEXCOORD1; //世界空间坐标 float3 worldPosition : TEXCOORD2; }; sampler2D _MainTex; float4 _MainTex_ST; fixed4 _Color; fixed _DotProduct; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); o.worldNormal = UnityObjectToWorldNormal(v.normal); o.worldPosition = mul(unity_ObjectToWorld, v.vertex).xyz; return o; } fixed4 frag (v2f i) : SV_Target { fixed3 worldNormal = normalize(i.worldNormal); fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPosition)); //因为viewDir和worldNormal都是归一化矢量,点乘后的值为它们夹角的cos值。 //考虑到半透明物体需要双面渲染, 所以对点乘结果求绝对值abs。 float border = 1 - (abs(dot(viewDir, worldNormal))); //_DotProduct: 调整透明度 float alpha = (border * (1 - _DotProduct) + _DotProduct); float4 c = tex2D(_MainTex, i.uv) * _Color; c.a = alpha; return c; } ENDCG } } }