透明度混合
半透明必须关闭深度写入
把自身颜色和已经存在于颜色缓存区中的颜色值进行混合
先渲染背景,然后把半透明物体从后往前渲染,这里关闭了深度写入,颜色缓存区是写入的背景颜色,再将前面的颜色按混合因子和缓存区的颜色混合。
Shader "Custom/6"
{
//透明度混合
//半透明必须关闭深度写入
//把自身颜色和已经存在于颜色缓存区中的颜色值进行混合
Properties
{
_Color("Main Tint", Color) = (1,1,1,1)
_MainTex("Main Tex",2D) = "white"{}
_AlphaScale("Alpha Scale", Range(0,1)) = 1
}
SubShader
{
Tags{"Queue" = "Transparent" " IgnoreProjector" = "true" "RenderType" = "Transparent"}
把模型的深度信息写入深度缓冲中,从而剔除模型中被自身遮挡的片元
Pass {
ZWrite On
ColorMask 0
}
Pass
{
Tags{"LightMode" = "ForwardBase"}
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
//将该片元着色器中产生的颜色的混合因子设为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;
float2 uv : TEXCOORD0;
float3 worldNormal : TEXCOORD1;
float3 worldPos : TEXCOORD2;
};
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);
fixed3 albedo = texColor.rgb * _Color.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
fixed3 diffuse = albedo * _LightColor0.rgb * max(0,dot(worldNormal,worldLightDir));
return fixed4(ambient + diffuse ,texColor.a * _AlphaScale);
//fixed4 中的四个元素是rgba,第四个是a透明度
}
ENDCG
}
}
FallBack "Transparent/VertexLit"
}
ZWrite Off 取消深度写入
Blend SrcAlpha OneMinusSrcAlpha
将该片元着色器中产生的颜色的混合因子设为SrcAlpha
把已存在颜色缓存中的混合因子设为OneMinusSrcAlpha
Orgba = SrcFactor * Srgba + DstFactor * Drgba
Unity中,使用Blend命令,设置混合状态同时开启了混合。
使用BlendOP BlendOperation 混合操作命令
通过混合操作和混合因子命令的组合,可以得到以下的几种效果:
Question:正方体背后的透明颜色为什么不加入计算?
默认情况下渲染引擎剔除了物体背面的渲染图元,而只渲染了物体的正面。如果想要获得双面渲染的效果,可以使用Cull指令来控制需要剔除哪个面的渲染图元。
Cull off
Shader "Custom/6"
{
//透明度混合
//半透明必须关闭深度写入
//把自身颜色和已经存在于颜色缓存区中的颜色值进行混合
Properties
{
_Color("Main Tint", Color) = (1,1,1,1)
_MainTex("Main Tex",2D) = "white"{}
_AlphaScale("Alpha Scale", Range(0,1)) = 1
}
SubShader
{
Tags{"Queue" = "Transparent" " IgnoreProjector" = "true" "RenderType" = "Transparent"}
//第一个Pass只渲染背面
Pass
{
Tags{"LightMode" = "ForwardBase"}
Cull Front
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
//将该片元着色器中产生的颜色的混合因子设为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;
float2 uv : TEXCOORD0;
float3 worldNormal : TEXCOORD1;
float3 worldPos : TEXCOORD2;
};
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);
fixed3 albedo = texColor.rgb * _Color.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
fixed3 diffuse = albedo * _LightColor0.rgb * max(0,dot(worldNormal,worldLightDir));
return fixed4(ambient + diffuse ,texColor.a * _AlphaScale);
//fixed4 中的四个元素是rgba,第四个是a透明度
}
ENDCG
}
//第二个Pass只渲染正面
Pass
{
Tags{"LightMode" = "ForwardBase"}
Cull Back
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
//将该片元着色器中产生的颜色的混合因子设为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;
float2 uv : TEXCOORD0;
float3 worldNormal : TEXCOORD1;
float3 worldPos : TEXCOORD2;
};
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);
fixed3 albedo = texColor.rgb * _Color.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
fixed3 diffuse = albedo * _LightColor0.rgb * max(0,dot(worldNormal,worldLightDir));
return fixed4(ambient + diffuse ,texColor.a * _AlphaScale);
//fixed4 中的四个元素是rgba,第四个是a透明度
}
ENDCG
}
}
FallBack "Transparent/VertexLit"
}
复制粘贴pass。两个pass中,一个Cull Front只渲染背面,一个Cull Back只渲染正面,按顺序执行pass