Unity Shader 简单地挖一个洞 | 您所在的位置:网站首页 › 挖出一个小洞 › Unity Shader 简单地挖一个洞 |
11月就要过去了,2020年已经走到尾声。从月中开始就苦苦思考有什么值得写的东西,结果发现这个月没有写什么太值得深纠的东西,就一直拖到了现在。 效果描述其大致效果是在地上挖一个洞,然后有东西从洞里面升起来,具体参考如下:
那就真的在地上挖一个洞,即在地面的Shader 中添加一个额外的Clip或者功能,然后在释放技能的时候用代码传进来一个世界坐标,此时可以用世界坐标对地面进行裁剪或者透明处理。 我这里做了一个最简单Clip的方式的挖洞,可以延申成采图进行Clip 或者透明,以下是代码: Shader "MyShader/PalneWorld" { Properties { _MainTex ("Texture", 2D) = "white" {} _GetPos ("Start Pos(XYZ)",Vector)=(0,0,0,1) _Radius ("Radius", Float) = 0.5 [Toggle]_Factor ("Factor", Int) = 1 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; float3 worldPos:TEXCOORD1; }; sampler2D _MainTex; float4 _MainTex_ST; float3 _GetPos; float _Radius; int _Factor; v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); o.worldPos= mul(unity_ObjectToWorld,v.vertex).xyz; return o; } fixed4 frag(v2f i) : SV_Target { float dist=distance(i.worldPos,_GetPos); clip(dist-_Radius*_Factor); fixed4 col = tex2D(_MainTex, i.uv); return col; } ENDCG } } }效果:
在不抠洞的前提下,这里主要是想解决中间物体穿过地面时候的穿插问题,这个问题相当头疼,唯一的办法是让穿透的物体永远通过深度测试,但是又引发一系列问题,最后不得已引入模板测试,这是最复杂的方式了。 这里将会分成三个部分: 地板上的洞这一部分分只是个平面,只是为了遮住地板,如图:
接下来是要考虑中间穿过的物体,因为正常来说,当物体和平面会被遮挡掉,如图:
半球(遮罩物体,这里需要使用GrabPass)的Shader: Shader "MyShader/Occlusion" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags {"RenderType" = "Transparent" "Queue"="Transparent" "DisableBatching" = "True"} LOD 100 Cull Off Stencil { Ref 1 Comp Always Pass Replace } GrabPass{"_ScreenTex"} Pass { Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; float4 grabPos:TEXCOORD1; }; sampler2D _MainTex; sampler2D _ScreenTex; float4 _MainTex_ST; v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); o.grabPos=ComputeGrabScreenPos(o.vertex); return o; } fixed4 frag(v2f i) : SV_Target { // sample the texture fixed4 col = tex2Dproj(_ScreenTex,i.grabPos); //col.rgb=1-col.rgb; return col; } ENDCG } } }这里还需要注意的是遮罩的序列要要小于中间物体,好让遮罩先写入模板缓冲,比如:
这个法不是我自己想的,但是真的很妙,缺点就是不能使用透明,因为都是在Geometry里进行的——取决于地面所在的序列,想要透明也行那就是地面也要在透明序列里,这种情况还是少…实现的效果和第一个差不多,只是不用改动地面的Shader。
|
CopyRight 2018-2019 实验室设备网 版权所有 |