原神中當相機距離角色很近的時候會表現出如下虛化的效果:
經過筆者仔細觀察,發現其實就是做了個鏤空效果,所以開始動手實現,代碼如下:
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