Sharder学习 4
第8章 透明效果
实现透明效果的方法:1.透明度测试alpha test, 2.透明度混合alpha blending.
8.3透明度测试
void clip(float4 x); …… void clip(float x);
如果给定参数任何一个分量是负数,就会舍弃当前像素的输出颜色
Shader "my Alpha test" {
Properties {
_Color ("Main Tint", Color) = (1,1,1,1)
_MainTex("Main Tex", 2D) = "white" {}
_Cutoff ("Alpha Cutoff", Range(0, 1)) = 0.5
}
SubShader {
Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
Pass {
Tags {"LightMode"="ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#incude "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;
float3 worldPos : TEXCOORD1;
float2 uv : TEXCOORD2;
};
v2f vert(a2v v) {
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(_Object2World, v.vertex).xyz;
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
fixed4 frag(v2f i): SV_Target {
fixed3 worldNormal = normalize(i.worldNormal);
fiexd3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed4 texColor = tex2D(_MainTex, i.uv);
//Alpha test
clip(texColor.a - _Cutoff);
//equal to
//if ((texColor.a - _Cutoff) < 0.0) {
// discard;
//}
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, 1.0);
}
ENDCG
}
}
}
8.4透明度混合
Blend命令
- Blend Off 关闭混合
- Blend SrcFactor DstFactor 开启混合,并设置混合因子。源颜色乘以SrcFactor,而目标颜色(已经存在颜色缓存的颜色)会乘以DstFactor。然后把两者相加后再存入颜色缓冲中
- Blend SrcFactor DstFactor, SrcFactorA DstFactorA 和上面几乎一样
- BlendOp BlendOperation 使用BlendOperation 对它们进行其它操作
...
Properties {
_Color ("Main Tint", Color) = (1,1,1,1)
_MainTex ("Maint Tex", 2D) = "white" {}
_AlphaScale ("Alpha Scale", Range(0,1)) = 1
}
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
fixed _AlphaScale;
SubShader {
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
Pass {
Tags {"LightMode"="ForwardBase"}
ZWrite Off
Blend ScrAlpha OneMinusSrcAlpha
fixed4 frag(v2f i) :SV_Target {
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnitWorldSpaceLightDir(i.worldPos));
fixed4 texColor = tex2D(_MainTex, i.uv);
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, texColor.a * _AlphaScale);
}
}
}
Fallback "Transparent/VertexLit"
...
8.5开启深度写入的半透明效果
使用两个pass来渲染模型:第一个pass开启深度写入,但不输出颜色,它的目的仅仅是为了把该模型的深度值写入深度缓冲中;第二个pass进行正常的透明混合。
Shader "Alpha Blending ZWrite" {
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"}
//Extra pass that renders to depth buffer only
Pass {
ZWrite On
ColorMask 0 //颜色通道写掩码(write mask), 参数可以是RGB | A | 0 | RGBA的各种组合
}
Pass {
//和8.4节同样的代码
}
}
FallBack "Diffuse"
}
8.6 shaderLab的混合命令
- Blend SrcFactor DstFactor
- Blend SrcFactor DstFactor SrcFactorA DstFactorA
混合公式(颜色和透明度):
Orgb = SrcFactor * Srgb + DstFactor * Drgb
Oa = SrcFactorA * Sa + DstFactorA * Da
ShaderLab中的混合因子
- One
- Zero
- SrcColor
- SrcAlpha
- DstColor
- DstAlpha
- OneMinusSrcColor
- OneMinusSrcAlpha
- OneMinusDstColor
- OneMinusDstAlpha
混合操作(源颜色和目标颜色的混合操作):
- Add
- Sub
- RevSub
- Min
- Max
8.7 双面渲染的透明效果
可以使用Cull指令来控制需要剔除哪个面的渲染图元。
Cull Back | Front | Off
- Back 背对着摄像机的渲染图元就不会被渲染,这是默认剔除状态。
- Front 面向摄像机的渲染图元不会被渲染。
- Off 关闭剔除功能。
透明度测试的双面渲染
CullOff
透明度混合的双面渲染
使用两个pass。一个pass只渲染背面,另一个只渲染正面。
...
Pass {
...
Cull Front
...
}
Pass {
...
Cull Back
...
}
...