文章目录
- 渲染队列
- 透明度测试(Alpha Test)
- 效果
- Shader
- 透明度混合(Alpha Blending)
- 效果
- Shader
- 参考
渲染队列
由”Queue“ 标签决定,索引号越小越早被渲染:
名称 | 队列索引号 |
---|---|
Background | 1000 |
Geometry | 2000 |
AlphaTest | 2450 |
Transparent | 3000 |
Overlay | 4000 |
透明度测试(Alpha Test)
某一片元的透明度小于某个阈值,即被舍弃,反之,按非透明物体处理,进行正常的深度测试和深度写入【不需要关闭深度写入】。
效果
Shader
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'Shader "Example/AlphaTest"
{Properties{_Color ("Main Tint", Color) = (1, 1, 1, 1 )_MainTex ("Main Tex", 2D) = "white" {} _Cutoff ("Alpha Cutoff", Range(0, 1)) = 0.5}SubShader{//TransparentCutout: 指明使用了透明度测试//不受投影标签的影响Tags {"Queue" = "AlphaTest" "IgnoreProjector" = "True" "RenderType" = "TransparentCutout"}Pass{Tags{"LightMode" = "ForwardBase"}CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"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;};fixed4 _Color;sampler2D _MainTex;float4 _MainTex_ST;fixed _Cutoff;float4 _LightColor0;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);//透明度测试, 输入值小于0则丢弃该片元clip(texColor.a - _Cutoff);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}}Fallback "Transparent/Cutout/VertexLit"
}
UnityObjectToClipPos
将顶点从模型空间转到剪裁空间
UnityObjectToWorldNormal
将法线方向从模型空间变换到世界空间
unity_ObjectToWorld
当前模型矩阵
TRANSFORM_TEX
UnityCG.cginc内置宏,变换贴图的平移和缩放的属性到UV:
#define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)
UnityWorldSpaceLightDir
光照模式在ForwardBase下,根据给定在模型空间下的顶点位置,计算朝向光源的世界空间方向。
tex2D
从纹理中获取像素的颜色信息,传入一个纹理和一个二维坐标(通常是纹理坐标),以获取该坐标处的像素颜色。
透明度混合(Alpha Blending)
可以得到真正的半透明效果,使用当前片元的透明度作为混合因子,与已经存储在颜色缓冲中的颜色值进行混合,得到新的颜色。需要关闭深度写入,但没有关闭深度测试。
效果
Shader
Shader "Example/AlphaBlend"
{Properties{_Color ("Main Tint", Color) = (1, 1, 1, 1)_MainTex ("Texture", 2D) = "white" {}_AlphaScale ("Alpha Scale", Range(0, 1)) = 1}SubShader{Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}// Pass的先后顺序有影响//开启深度写入,不输出颜色Pass{ZWrite OnColorMask 0}//透明度混合Pass{Tags{"LightMode" = "ForwardBase"}// 关闭深度写入ZWrite Off// 设置Pass的混合模式,SrcAlpha: 片元着色器产生的颜色的混合因子// OneMinusSrcAlpha 已经存在于颜色缓冲中的颜色的混合因子Blend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"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;};fixed4 _Color;sampler2D _MainTex;float4 _MainTex_ST;fixed _AlphaScale;float4 _LightColor0;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 = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));return fixed4(ambient + diffuse, texColor.a * _AlphaScale);}ENDCG}}Fallback "Transparent/VertexLit"
}
使用两个Pass来渲染模型:第一个Pass开启深度写入,但不输出颜色,第二个Pass进行正常的透明度混合。注意写Pass有先后顺序。
使用两个Pass原因是,由于关闭了深度写入,当模型本身有复杂的遮挡关系或是包含了复杂的非凹凸网络,就会因为排序问题产生错误的透明效果。
ColorMask
设置颜色通道的写掩码,ColorMask RGB | A | 0 | 其他任何RGBA的组合,当设置为0时,Pass不写入任何的颜色通道,不会输出颜色。
参考
《Unity Shader入门精要》冯乐乐
内置着色器变量
内置着色器函数