原神中当相机距离角色很近的时候会表现出如下虚化的效果:
经过笔者仔细观察,发现其实就是做了个镂空效果,所以开始动手实现,代码如下:
Shader "Unlit/VirtualShader" { Properties { _MainTex ("Texture", 2D) = "white" {} _TilingTex("TileMap",2D) = "white"{} _TilingValue("TilingValue",float) = 20 } SubShader { Tags { "RenderType"="Transparent"} 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; float3 normal:NORMAL; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; float4 screenPos : TEXCOORD1; float3 worldNormal:TEXCOORD2; }; sampler2D _MainTex; sampler2D _TilingTex; float4 _MainTex_ST; float _TilingValue; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); o.screenPos = ComputeScreenPos(o.vertex); o.worldNormal = UnityObjectToWorldNormal(v.normal); return o; } fixed4 frag (v2f i) : SV_Target { float2 uv = i.screenPos.xy/i.screenPos.w; half clipValue = tex2D(_TilingTex,uv*_TilingValue).r-0.5; half3 lightDir = normalize(_WorldSpaceLightPos0.xyz); half3 worldNormal = normalize(i.worldNormal); clip(clipValue); fixed4 col = tex2D(_MainTex, i.uv)*saturate(dot(lightDir,worldNormal)); return col; } ENDCG } } }
主要思路就是从屏幕空间采样一张tiling的mask,根据mask去做alphatest。效果如下:
需要扩展自行添加,shader本身也没有什么难度,就不做赘述了。有问题可以评论区见~或者加qq群:104794354