《Unity 入门精要》第8章 透明效果( 三 )


下面是一个透明度混合的例子,其中采用Blend语义,并设置为 , 为 ,这样讲采用如下的混合算法:
更多混合语义的说明可查看官方文档 。下面是代码:
Shader "Chaptor 8/SHA_AlphaBlend"{Properties{_Color ("Color Tint", Color) = (1, 1, 1, 1)_MainTex ("Main Tex", 2D) = "white" {}// 用于控制整体的透明度_AlphaScale ("Alpha Scale", Range(0, 1.0)) = 1}SubShader{// 通过标签 Queue 指定渲染队列为 TransparentTags {"Queue"="Transparent" "IgnoreProjector"="true" "RenderType"="Transparent"}Pass{Tags {"LightMode" = "ForwardBase"}// 深度写入设置为关闭状态ZWrite off// 开启混合,并设置相应混合因子Blend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"#include "Lighting.cginc"fixed4 _Color;sampler2D _MainTex;float4 _MainTex_ST;fixed _AlphaScale;struct appdata{float4 vertex : POSITION;float3 normal : NORMAL;float2 uv : TEXCOORD0;};struct v2f{float4 vertex : SV_POSITION;float3 worldNormal : TEXCOORD0;float3 worldPos : TEXCOORD1;float2 uv : TEXCOORD2;};v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.worldNormal = UnityObjectToWorldNormal(v.normal);o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;o.uv = TRANSFORM_TEX(v.uv, _MainTex);return o;}fixed4 frag (v2f i) : SV_Target{float3 worldNormal = normalize(i.worldNormal);float3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));fixed4 texColor = tex2D(_MainTex, i.uv);fixed3 albedo = texColor * _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 "Specular"}
效果如下,左侧为透明度测试效果,右侧为透明度混合效果:
8.5 开启深度写入的半透明效果
由于在进行透明度混合时关闭了深度写入,所以当模型中有互相交叉的结构时,往往会得到错误的半透明效果:
为了解决这个问题,我们可以使用两个 Pass 来渲染,第一个 Pass 开启深度写入,但不输出颜色,它的目的仅仅是把模型的深度值写入深度缓冲中;第二个 Pass 进行正常的透明度混合,由于上一个 Pass 已经得到逐像素的正确的深度信息,该 Pass 就可以按照像素级别的深度排序结果进行透明渲染 。但这种的方法的缺点在于多使用了一个 Pass,会对性能造成一定影响 。
实现的如下:
Shader "Chaptor 8/SHA_AlphaBlendZWrite"{Properties{_Color ("Color Tint", Color) = (1, 1, 1, 1)_MainTex ("Main Tex", 2D) = "white" {}// 用于控制整体的透明度_AlphaScale ("Alpha Scale", Range(0, 1.0)) = 1}SubShader{// 通过标签 Queue 指定渲染队列为 TransparentTags {"Queue"="Transparent" "IgnoreProjector"="true" "RenderType"="Transparent"}Pass {// 第一个 Pass 开启深度写入ZWrite on// ColorMask 为渲染命令,用于设置颜色通道的写掩码// ColorMask 0 表示该 Pass 不写入任何颜色通道,即不会输出任何颜色ColorMask 0}Pass{Tags {"LightMode" = "ForwardBase"}// 深度写入设置为关闭状态ZWrite off// 开启混合,并设置相应混合因子Blend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"#include "Lighting.cginc"fixed4 _Color;sampler2D _MainTex;float4 _MainTex_ST;fixed _AlphaScale;struct appdata{float4 vertex : POSITION;float3 normal : NORMAL;float2 uv : TEXCOORD0;};struct v2f{float4 vertex : SV_POSITION;float3 worldNormal : TEXCOORD0;float3 worldPos : TEXCOORD1;float2 uv : TEXCOORD2;};v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.worldNormal = UnityObjectToWorldNormal(v.normal);o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;o.uv = TRANSFORM_TEX(v.uv, _MainTex);return o;}fixed4 frag (v2f i) : SV_Target{float3 worldNormal = normalize(i.worldNormal);float3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));fixed4 texColor = tex2D(_MainTex, i.uv);fixed3 albedo = texColor * _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 "Specular"}