当我们想要在一个立方体上加入其它模型,但由于重面会发生闪烁的效果。这时候我们就需要设置重合位置的透明度为0。代码如下:
Shader "Custom/MyShader" {
Properties{
_Color("Color", Color) = (1,1,1,1)
_MainTex("Albedo (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Transparent" "LightMode" = "ForwardBase" }
ZWrite Off
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct v2f {
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float2 uv : TEXCOORD2;
};
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Color;
uniform float4 _Points[10];
uniform float _Points_Num;
v2f vert(a2v v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
fixed4 frag(v2f i) : SV_Target{
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed4 texColor = tex2D(_MainTex, i.uv);
float alpha = 1;
for (int j = 0; j < _Points_Num; j++)
{
// step(a, x) 如果 a>x,返回 0;否则,返回 1。
alpha = alpha* step(step(_Points[j].x, i.worldPos.x) + step(_Points[j].y, i.worldPos.y) + step(i.worldPos.x, _Points[j].z) + step(i.worldPos.y, _Points[j].w), 3);
}
clip(alpha-0.9);
fixed3 albedo = texColor.rgb * _Color.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));
return fixed4(ambient + diffuse, alpha);
}
ENDCG
}
}
FallBack "Diffuse"
}
以上代码原理就是我们通过比较给定区域和我们shader的顶点世界坐标,如果顶点的世界坐标在这个指定区域内,我们就设置alpha值为0,否则返回1.最后在alpha为0时舍弃当前像素。
step(a, x) 如果 a>x,返回 0;否则,返回 1。
clip(a-x) 如果a-x<0 舍弃当前像素片原
我们传入的数组是一个Vector4类型的数组。Vector4里表示的是区域最小值和最大值。即new Vector4(min.x,min.y,max.x,max.y)。
我们可以传入多组数据去使一个立方体上有多个透明度为0的区域。
unity 这里给shader传入数据代码如下:
var points=new List<Vector4>();
points.Add(new Vector4(-4f,-0.5f,-3,0.5f));
points.Add(new Vector4(1f, -0.5f, 2, 0.5f));
Material material = Cuve.GetComponent<MeshRenderer>().sharedMaterial;
material.SetInt("_Points_Num",2);
material.SetVectorArray("_Points", points);
最后效果图如下: