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


效果如下:

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

文章插图
的混合命令
混合就是通过混合等式(blend )将源颜色( color)和目标颜色( color)进行相应计算产生输出颜色( color) 。
混合等式和混合因子
Unity使用渲染命令 Blend 来设置混合等式的混合因子:
支持的常用混合因子如下:
更详细信息见Unity 官方手册
混合操作
我们可以使用渲染命令 来设置混合操作类型,默认的操作类型为加法,支持的常见混合操作如下:
更详细信息见Unity 官方手册
常见的混合类型
下面列出了常见的几种混合类型:
// 正常(Normal),即透明度混合Blend SrcAlpha OneMinusSrcAlpha// 柔和相加(Soft Additive)Blend OneMinusDstColor One// 正片叠底(Multiply),即相乘Blend DstColor Zero// 两倍相乘(2x Multiply)Blend DstColor SrcColor// 变暗(Darken)BlendOp MinBlend One One// 变亮(Lighten)BlendOp MaxBlend One One// 滤色(Screen)Blend OneMinusDstColor One// 等同于Blend One OneMinusSrcColor// 线性减淡(Linear Dodge)Blend One One
对应的混合效果如下图:
双面渲染的透明效果
在现实生活中,如果一个物体是透明的,意味着我们不仅可以透过它看到其他物体的样子,也可以看到它内部的结构 。但在前面实现的透明效果中,无论是透明度测试还是透明度混合,我们都无法观察到正方体内部及其背面的形状,导致物体看起来就好像只有半个一样 。这是因为,**默认情况下渲染引擎剔除了物体背面(相对于摄像机的方向)的渲染图元,而只渲染了物体的正面 。**如果我们想要得到双面渲染的效果,可以使用 Cull 指令来控制需要剔除哪个面的渲染图元 。
Cull Back | Front | Off
透明度测试的双面渲染
在 Pass 中关闭剔除即可:
Shader "Chaptor 8/SHA_AlphaTest"{Properties{_Color ("Color Tint", Color) = (1, 1, 1, 1)_MainTex ("Main Tex", 2D) = "white" {}_CutOff ("Alpha CutOff", Range(0, 1.0)) = 0.5}SubShader{Tags {"Queue"="AlphaTest" "IgnoreProjector"="true" "RenderType"="TransparentCutout"}Pass{Tags {"LightMode" = "ForwardBase"}// 关闭剔除Cull offCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"#include "Lighting.cginc"fixed4 _Color;sampler2D _MainTex;float4 _MainTex_ST;fixed _CutOff;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);clip(texColor.a - _CutOff);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, 1.0);}ENDCG}}Fallback "Specular"}
效果如下:
透明度混合的双面渲染
和透明度测试相比,想要让透明度混合实现双面渲染会更复杂一些,这是因为透明度混合需要关闭深度写入,所以我们需要保证渲染顺序的正确性 。我们想要保证图元是从后往前渲染的 。为此,我们选择把双面渲染的工作分成两个Pass,第一个Pass只渲染背面,第二个Pass只渲染正面,由于Unity会顺序执行中的各个Pass,因此我们可以保证背面总是在正面被渲染之前渲染,从而可以保证正确半透明效果: