透明测试实现
SubShader
{
Tags{"Queue" = "AlphaTest"/模型渲染队列/ "IngnoreProjector" = "True" "RanderType" = "Transparent"}//Pass块参数标签
Pass
{
Tags {"Lighting" = "ForwardBase"} //定义LightMode,获取UNITY内部光照变量
fixed4 texColor = tex2D(_MainTex, f.uv.xy) * _Color;//获取纹理坐标下贴图像素点的颜色*与外部属性控制的贴图颜色混合
clip(texColor.a-_Cutoff);
通过透明贴图实现显示与透明(非半透明)。
开启深度写入的半透明效果,通过两个pass块实现,第一个测试深度:ColorMask 0//设置颜色通道写掩码,0-不输出颜色,只测试深度。
混合模式:
透明混合实现
Shader "Custom/Alpha"
{
Properties//属性
{
_MainTex("Main Tex",2D) = "white"{}//贴图代替漫反射颜色
_Color("Tex Color",Color) = (1,1,1,1)//贴图颜色:与贴图uv坐标下的像素点颜色混合
_NormalMap("Normal Map",2D) = "bump"{}//未添法线贴图时为默认法线
_NormalST("Normal ST",Float) = 1//法线贴图强度参数
_AlphaScale("_AlphaScale",Float) = 1
}
SubShader
{
Tags{"Queue" = "Transparent"/设置模型渲染队列为透明度混合/ "IngnoreProjector" = "True" "RanderType" = "Transparent"}//Pass块参数标签
Pass
{
Tags {"Lighting" = "ForwardBase"} //定义LightMode,获取UNITY内部光照变量
ZWrite Off//深度写入关闭
Blend SrcAlpha OneMinusSrcAlpha//混合模式:透明区域与透明物体后颜色混合
* CGPROGRAM
* //在CG声明属性
sampler2D _MainTex;//ShaderCG中的关键字
float4 _MainTex_ST; //主贴图的缩放与偏移“属性名称固定”_MainTex_ST.xy缩放属性;_MainTex_ST.zw偏移属性
fixed4 _Color;//与贴图叠混合颜色
sampler2D _NormalMap;
float4 _NormalMap_ST;
float _NormalST;
float _AlphaScale;
#include "Lighting.cginc"//引入UNITY内置文件,获取光照变量 _LightColor0.rgb;光源颜色
#pragma vertex vert//声明顶点函数
#pragma fragment frag//声明片原函数
struct a2v//应用向顶点函数传递参数
{
float4 vertex:POSITION;//模型空间顶点坐标
//切线空间的确定是通过(存储到模型里的/模型空间)法线 与 (存储到模型里的/模型空间)切线确定的
float3 normal:NORMAL;//模型空间法线方向
float4 tangent:TANGENT;//模型空间下的切线方向:tangent.w:是用来确定切线空间中坐标轴的方向(切线空间下的Z轴方向默认为顶点的法线方向:通过控制缩放xy可改变法线强度)
float4 texcoord :TEXCOORD0;//获取纹理坐标
};
struct v2f//顶点函数向片原函数传递参数
{
float4 svPos:SV_POSITION;//顶点函数返回值:剪裁空间中的顶点坐标-系统直接使用
//float3 worldNormal : TEXCOORD0;//顶点函数向片原函数传递世界坐标下的法线方向(使用法线贴图后不需要)
float3 lightDir:TEXCOORD0;//切线空间下的平行光方向
//float4 worldView:TEXCOORD1;//顶点函数向片原函数传递世界坐标下的顶点坐标
float4 uv:TEXCOORD2;//xy用来存储_MainTex的纹理坐标,zw用来存储_NormalMap的纹理坐标
};
v2f vert(a2v v)//顶点函数将顶点从模型空间转到世界空间,返回值在世界坐标系下的顶点坐标
{
v2f f;//声明传参结构体,并对其中的值赋值
f.svPos = UnityObjectToClipPos(v.vertex);
//f.worldNormal = UnityObjectToWorldNormal(v.normal);
//f.worldView = (UnityObjectToWorldNormal(v.vertex), 0);
f.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;//将纹理坐标传递到片原函数 * 乘上主贴图缩放属性 + 加上主贴图的偏移属性
f.uv.zw = v.texcoord.xy * _NormalMap_ST.xy + _NormalMap_ST.zw;//将法线纹理坐标与其属性结合存储到uv.zw中
TANGENT_SPACE_ROTATION;//调用这个宏后(保证a2v "v"中存在"normal""tangent"宏自动调用),会得到一个矩阵"rotation"这个矩阵用来把模型空间下的法线转换到切线空间下
//ObjSpaceLightDir(v.vertex);//模型空间下的平行光方向
f.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex));//将切线就下的平行光方向传到片原函数
return f;//返回结构体
}
//把与法线有关相关计算放到切线空间下(从法线贴图取到的方向坐标为切线空间下的)
fixed4 frag(v2f f) :SV_Target//片原函数,返回值为输出到像素颜色值的缓存
{
//计算漫反射
//fixed3 normalDir = normalize(f.worldNormal);//法线方向
fixed4 normalColor = tex2D(_NormalMap,f.uv.zw);//法线贴图在纹理坐标下的颜色值(只使用其中RGB值)
//此方法法线读取不正确//fixed3 tangentNormal = normalize(normalColor.xyz * 2 - 1);//切线空间下的法线方向
fixed3 tangentNormal = normalize(UnpackNormal(normalColor));//在UNITY中将法线贴图类型设置为法线贴图时可用此方法获得切线空间下的法线方向
//切线空间下的Z轴方向默认为顶点的法线方向:通过控制缩放xy可改变法线强度,则如下
tangentNormal.xy = tangentNormal.xy * _NormalST;//强度为0时使用的即是模型顶点默认的法线方向
fixed3 lightDir = normalize(f.lightDir);//单位化切线空间下的光源方向
fixed4 texColor = tex2D(_MainTex, f.uv.xy) * _Color;//获取纹理坐标下贴图像素点的颜色*与外部属性控制的贴图颜色混合
fixed3 diffuse = _LightColor0.rgb * texColor.rgb * max((dot(tangentNormal,lightDir) * 0.5 + 0.5), 0);//fixed3 harfLambert =dot(f.wordNormalDir, lightDir)*0.5+0.5;//半兰伯特光照模型:直射光颜色 * (cos夹角(光与法线)*0.5+0.5):使背光面不完全为黑色
//计算高光反射
//fixed3 reflectDir = normalize(reflect(-lightDir, normalDir));
//fixed3 viewDir = normalize(WorldSpaceViewDir(f.worldView));//实视线方向
//fixed3 harfDir = normalize(viewDir + lightDir);//视角与平行光的平分方向
//fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(dot(normalDir, harfDir),0), _Gloss);//BP模型://Blinn-Phong光照模型Specular = 直射光*pow(max(cos夹角,0)*高光参数) ,夹角:法线与x方向夹角,x:平行光与视野方向的平分项。
fixed3 tempColor = diffuse + UNITY_LIGHTMODEL_AMBIENT.rgb * texColor;//漫反射+高光+环境光*纹理,相加混合(环境光与纹理混合:使强光下的纹理仍保持清晰)
return fixed4(tempColor,_AlphaScale*texColor.a);//外部属性与纹理贴图Alpha值混合控制
//开启Blend混合后片元的透明通道才有影响
}
ENDCG
}
}
FallBack "Diffuse"
}
双面透明渲染:通过Cull Back/Front/Off来剔除面/关闭剔除
透明测试双面渲染
Pass
{
Tags{LightMode ="ForwardBase"}
Cull Off
}
透明度混合的上面渲染
通过两个Pass块实现,第一个Pass只渲染背面-Cull Front,第二个Pass只渲染正面-Cull-Back