深度测试:
实现效果:
透明度测试
将纹理图片中的小于0.5的部分剔除掉,所以我们看到黑色的边缘不见了。
代码:
透明度测试的Tags设置为
Tags{“Queue”=“AlphaTest” “IgnoreProjector”=“True” “RenderType”=“TransparentCutout”}
分别表示渲染顺序为深度测试,忽略物体的阴影影响,渲染的模式是TransparentCutout
Shader "Custom/Chapter8-AlphaTest"
{
Properties{
_Color("Color Tint",color)=(1,1,1,1)
_MainTex("Main Tex",2D)="white"{}
//透明度测试范围
_Cutoff("Alpha Cutoff",Range(0,1))=0.5
}
SubShader{
//第一个是透明度测试队列,第二个是不受投射器的影响,第三个指定这个shader用了透明度测试
Tags{"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
Pass{
Tags{"LightMode"="ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
fixed _Cutoff;
struct a2v{
float4 vertex:POSITION;
float3 normal:NORMAL;
float4 texcoord:TEXCOORD0;
};
struct v2f{
float4 pos:SV_POSITION;
float3 worldNormal:TEXCOORD0;
float4 worldPos:TEXCOORD1;
float2 uv:TEXCOORD2;
};
v2f vert(a2v v){
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
o.worldNormal=UnityObjectToWorldNormal(v.normal);
o.worldPos=mul(unity_ObjectToWorld,v.vertex);
o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
return o;
}
fixed4 frag(v2f i):SV_Target{
fixed3 worldNormal =normalize(i.worldNormal);
fixed3 lightDir =normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed4 texColor =tex2D(_MainTex,i.uv);
//判断透明度
//如果小于_Cutoff则舍弃片元
//如果大于则当成不透明物体
clip(texColor-_Cutoff);
fixed3 albedo =texColor.rgb*_Color.rgb;
fixed3 ambient0 =UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
fixed3 diffuse0 =_LightColor0.rgb*albedo*saturate(dot(worldNormal,lightDir));
return fixed4(ambient0+diffuse0,1.0);
}
ENDCG
}
}
FallBack "Transparent/Cutout/VertexLit"
}
透明度混合
实现效果:
unity shader透明度混合
代码:
透明度混合的Tags设置
Tags{“Queue”=“Transparent” “IgnoreProjector”=“True” “RenderType”=“Transparent”}
Shader "Custom/Chapter8_8_4"
{
Properties{
_Color("Color Tint",color)=(1,1,1,1)
_MainTex("Main Tex",2D)="white"{}
//透明度
_AlphaScale("Alpha Scale",Range(0,1))=1
}
SubShader{
//第一个是透明度混合队列,第二个是不受投射器的影响,第三个指定这个shader用了透明度测试
Tags{"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
Pass{
Tags{"LightMode"="ForwardBase"}
//深度写入关闭
ZWrite Off
//混合因子
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
fixed _AlphaScale;
struct a2v{
float4 vertex:POSITION;
float3 normal:NORMAL;
float4 texcoord:TEXCOORD0;
};
struct v2f{
float4 pos:SV_POSITION;
float3 worldNormal:TEXCOORD0;
float4 worldPos:TEXCOORD1;
float2 uv:TEXCOORD2;
};
v2f vert(a2v v){
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
o.worldNormal=UnityObjectToWorldNormal(v.normal);
o.worldPos=mul(unity_ObjectToWorld,v.vertex);
o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
return o;
}
fixed4 frag(v2f i):SV_Target{
fixed3 worldNormal =normalize(i.worldNormal);
fixed3 lightDir =normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed4 texColor =tex2D(_MainTex,i.uv);
fixed3 albedo =texColor.rgb*_Color.rgb;
fixed3 ambient0 =UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
fixed3 diffuse0 =_LightColor0.rgb*albedo*saturate(dot(worldNormal,lightDir));
//透明度由纹理的透明度和透明度系数混合
return fixed4(ambient0+diffuse0,texColor.a*_AlphaScale);
}
ENDCG
}
}
FallBack "Transparent/VertexLit"
}
开启深度写入的透明度混合
没有深度写入的话,会产生一些排序错误而产生的错误的透明效果。
解决方法:
使用两个pass:
- 第一个Pass开启深度写入,但是不输出颜色,目的是为了把模型的深度信息写入深度缓冲中。
- 第二个Pass进行正常的透明度混合
实现效果:
代码:
Shader "Custom/NewSurfaceShader"
{
Properties{
_Color("Color Tint",color)=(1,1,1,1)
_MainTex("Main Tex",2D)="white"{}
//透明度
_AlphaScale("Alpha Scale",Range(0,1))=1
}
SubShader{
//第一个是透明度混合队列,第二个是不受投射器的影响,第三个指定这个shader用了透明度测试
Tags{"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
Pass{
ZWrite On
//ColorMask为0意味着不写入任何颜色通道
ColorMask 0
}
Pass{
Tags{"LightMode"="ForwardBase"}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
fixed _AlphaScale;
struct a2v{
float4 vertex:POSITION;
float3 normal:NORMAL;
float4 texcoord:TEXCOORD0;
};
struct v2f{
float4 pos:SV_POSITION;
float3 worldNormal:TEXCOORD0;
float4 worldPos:TEXCOORD1;
float2 uv:TEXCOORD2;
};
v2f vert(a2v v){
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
o.worldNormal=UnityObjectToWorldNormal(v.normal);
o.worldPos=mul(unity_ObjectToWorld,v.vertex);
o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
return o;
}
fixed4 frag(v2f i):SV_Target{
fixed3 worldNormal =normalize(i.worldNormal);
fixed3 lightDir =normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed4 texColor =tex2D(_MainTex,i.uv);
fixed3 albedo =texColor.rgb*_Color.rgb;
fixed3 ambient0 =UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
fixed3 diffuse0 =_LightColor0.rgb*albedo*saturate(dot(worldNormal,lightDir));
return fixed4(ambient0+diffuse0,texColor.a*_AlphaScale);
}
ENDCG
}
}
FallBack "Transparent/VertexLit"
}
双面渲染的透明效果
在之前的渲染中我们可以看到我们只能看到表面的效果,但是看不到cube的内部以及背面的效果,这是因为在默认的情况下,渲染是剔除了背面的,如果我们想要得到更加真实的效果,我们需要对背面也进行渲染。
实现方式:
使用两个Pass,一个Pass渲染前面,另外一个渲染背面。
实现效果:
双面渲染的透明度混合
代码:
Shader "Custom/Chapter8-AlphaBlendBothSided"
{
Properties{
_Color("Color Tint",color)=(1,1,1,1)
_MainTex("Main Tex",2D)="white"{}
//透明度
_AlphaScale("Alpha Scale",Range(0,1))=1
}
SubShader{
//第一个是透明度混合队列,第二个是不受投射器的影响,第三个指定这个shader用了透明度测试
Tags{"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
Pass{
Tags{"LightMode"="ForwardBase"}
ZWrite Off
//剔除前面的渲染,只渲染背对着摄像头的
Cull Front
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
fixed _AlphaScale;
struct a2v{
float4 vertex:POSITION;
float3 normal:NORMAL;
float4 texcoord:TEXCOORD0;
};
struct v2f{
float4 pos:SV_POSITION;
float3 worldNormal:TEXCOORD0;
float4 worldPos:TEXCOORD1;
float2 uv:TEXCOORD2;
};
v2f vert(a2v v){
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
o.worldNormal=UnityObjectToWorldNormal(v.normal);
o.worldPos=mul(unity_ObjectToWorld,v.vertex);
o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
return o;
}
fixed4 frag(v2f i):SV_Target{
fixed3 worldNormal =normalize(i.worldNormal);
fixed3 lightDir =normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed4 texColor =tex2D(_MainTex,i.uv);
fixed3 albedo =texColor.rgb*_Color.rgb;
fixed3 ambient0 =UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
fixed3 diffuse0 =_LightColor0.rgb*albedo*saturate(dot(worldNormal,lightDir));
return fixed4(ambient0+diffuse0,texColor.a*_AlphaScale);
}
ENDCG
}
Pass{
Tags{"LightMode"="ForwardBase"}
//剔除背对摄像头的,只渲染前面的
Cull Back
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
fixed _AlphaScale;
struct a2v{
float4 vertex:POSITION;
float3 normal:NORMAL;
float4 texcoord:TEXCOORD0;
};
struct v2f{
float4 pos:SV_POSITION;
float3 worldNormal:TEXCOORD0;
float4 worldPos:TEXCOORD1;
float2 uv:TEXCOORD2;
};
v2f vert(a2v v){
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
o.worldNormal=UnityObjectToWorldNormal(v.normal);
o.worldPos=mul(unity_ObjectToWorld,v.vertex);
o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
return o;
}
fixed4 frag(v2f i):SV_Target{
fixed3 worldNormal =normalize(i.worldNormal);
fixed3 lightDir =normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed4 texColor =tex2D(_MainTex,i.uv);
fixed3 albedo =texColor.rgb*_Color.rgb;
fixed3 ambient0 =UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
fixed3 diffuse0 =_LightColor0.rgb*albedo*saturate(dot(worldNormal,lightDir));
return fixed4(ambient0+diffuse0,texColor.a*_AlphaScale);
}
ENDCG
}
}
FallBack "Transparent/VertexLit"
}