前言:每日记录自己学习unity的心得和体会,小弟才疏学浅,如有错误的地方,欢迎大佬们指正,感谢~
使用的核心方法是clip,当传入正值时渲染,传入负值时不渲染。定义一个裁剪向量,使用裁剪向量和模型点点乘,如果模型点和裁剪向量是同一个方向,点乘为正,相反为负。
shader源码
Shader "SongShaderDemo/CutOffWorld"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
_CutValue("切割范围:",Float) = 0
_CutDirection("切割方向",Vector) = (0, 1, 0, 0)
_CutDistance("切割距离",Float) = 1000
_LightIntensity("灯光强度",Float) = 1
}
SubShader
{
Tags { "RenderType" = "Opaque" "LigthMode" = "ForwarBase"}
LOD 100
Pass
{
Cull Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc "
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal: NORMAL;//存储法线的盒子
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float3 worldPos : TEXCOORD1;
float3 wNormal:TEXCOORD6;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _CutValue;
float _CutDistance;
float4 _CutDirection;
float _LightIntensity;
v2f vert (appdata v)
{
v2f o;
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.wNormal = UnityObjectToWorldNormal(v.normal);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
//_WorldSpaceLightPos0 unity提供的灯光向量
float3 L = normalize(_WorldSpaceLightPos0);
float3 N = normalize(i.wNormal);
float halfLam = dot(L, N) * 0.5 + 0.75;
//_LightColor0.rgb unity提供的灯光强度
float3 diffLight = halfLam * _LightColor0.rgb*_LightIntensity;
fixed4 diffColor = fixed4(diffLight.rgb, 1);
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
float3 cutDirection = normalize(_CutDirection.xyz);//切割向量
float3 curCenter = (cutDirection * (_CutValue - 0.5) * _CutDistance);//切割的原点,在切割的向量上移动
float3 targetVer = i.worldPos - curCenter;//切割原点到模型点上的向量
float angel =- dot(cutDirection,normalize(targetVer));//切割向量和targetVer点乘,正则同方向,父则反方向
clip(angel);//反方向剔除
return col* diffColor;
}
ENDCG
}
}
}
使用Shader Graphs
补充(自身模型空间的裁剪)
Shader "SongShaderDemo/CutOffObject"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
_CutValue("切割范围:",Float) = 0
_CutDirection("切割方向",Vector) = (0, 0, 0, 0)
_CutDistance("切割距离",Float) = 1
_LightIntensity("灯光强度",Float) = 1
}
SubShader
{
Tags { "RenderType" = "Opaque" "LigthMode" = "ForwarBase"}
LOD 100
// Blend SrcAlpha OneMinusSrcAlpha
ZWrite On
Pass
{
Cull Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc "
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal: NORMAL;//存储法线的盒子
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float3 worldPos : TEXCOORD1;
float3 center:TEXCOORD2;
float3 wNormal:TEXCOORD6;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _CutValue;
float _CutDistance;
float _LightIntensity;
float4 _CutDirection;
v2f vert(appdata v)
{
v2f o;
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
//得到中心点
o.center = float3(unity_ObjectToWorld[0].w, unity_ObjectToWorld[1].w, unity_ObjectToWorld[2].w);
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.wNormal = UnityObjectToWorldNormal(v.normal);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
//_WorldSpaceLightPos0 unity提供的灯光向量
float3 L = normalize(_WorldSpaceLightPos0);
float3 N = normalize(i.wNormal);
float halfLam = dot(L, N)*0.5 + 0.75;
//_LightColor0.rgb unity提供的灯光强度
float3 diffLight = halfLam * _LightColor0.rgb*_LightIntensity;
fixed4 diffColor = fixed4(diffLight.rgb, 1);
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
float3 cutDirection = normalize(_CutDirection.xyz);//切割向量
float3 curCenter = i.center + (cutDirection*(_CutValue - 0.5)*_CutDistance);//切割的原点,在切割的向量上移动
float3 targetVer = i.worldPos - curCenter;//切割原点到模型点上的向量
float angel = dot(normalize(targetVer), cutDirection);//切割向量和targetVer点乘,正则同方向,父则反方向
clip(angel);//反方向剔除
return col * diffColor;
}
ENDCG
}
}
Fallback "Transparent/VertexLit"
}