【Unity Shader入门精要 第8章】透明效果(三)

1. 透明度混合

透明度混合用来模拟真正的半透效果。

1.1 基本原理

为了方便后续描述,我们先提前对一些表示符号进行介绍

符号称呼意义
src用于表示当前正在处理的片元的相关信息
dst目标用于表示颜色缓冲区中与当前正处理的片元对应位置上已经存储的相关信息
O输出用于表示最终输出的颜色信息

透明度混合的基本原理是,在片元着色器输出时,将该片元的颜色信息(源)和目标缓冲区中已经存在的颜色信息(目标)按照某种方式进行计算,并用最终的计算结果更新目标颜色缓冲区。

O = f( src, dst )

1.2 混合因子

在实际混合时,源和目标都会分配一个系数,称为混合因子(Factor),因此,实际的混合公式更类似与如下表示:

O = f( srcFactor * srcColor, dstFactor * dstColor )

其中 srcColor 和 dstColor 都是包含了RGBA四个通道的颜色值,我们可以给四个通道分配同样的混合因子,也可以为RGB通道分配一个混合因子,而给A通道分配另一个混合因子。具体分配混合因子时是通过在 SubShader 中设置混合指令 Blend 来进行的,因此Blend指令包含如下两种格式:

格式说明对应公式
Blend SrcFactor DstFactor为源颜色的四个通道都分配混合因子SrcFactor,同时为目标颜色的四个通道都分配混合因子DstFactorO = f( srcFactor * srcColor, dstFactor * dstColor )
Blend SrcFactor DstFactor, SrcFactorA DstFactorA为源颜色的RGB通道分配混合因子SrcFactor,A通道分配混合因子SrcFactorA,同时为目标颜色的RGB通道分配混合因子DstFactor,A通道分配混合因子DstFactorAORGB = f( srcFactor * srcRGB, dstFactor * dstRGB ),OA = f( srcFactorA * srcA, dstFactorA * dstA )

当通过以上两种格式设置了混合指令后,Unity会自动为我们开启透明度混合,除此以外,我们还可以通过 Blend Off 的方式指定关闭透明度混合。

注意:Blend指令是通知Unity开启透明度混合的开关,如果没有设置Blend指令,即使片元着色器中输出颜色的Alpha值小于1也不会有混合的效果。

SrcFactor和DstFactor并不是我们可以随意指定的,而是由Unity定义好的,Unity支持的混合因子如下:

参数描述
One1
Zero0
SrcAlpha源颜色的 Alpha 值
SrcColor源颜色的颜色值。当混合RGB时,用源颜色的RGB分量,当混合A通道时,用源颜色的A分量
DstAlpha目标颜色的 Alpha 值
DstColor目标颜色的颜色值。当混合RGB时,用目标颜色的RGB分量,当混合A通道时,用目标颜色的A分量
OneMinusSrcAlpha1减源颜色的 Alpha 值
OneMinusSrcColor1减源颜色的颜色值
OneMinusDstAlpha1减目标颜色的 Alpha 值
OneMinusDstColor1减目标颜色的颜色值

1.3 混合操作

除了可以通过 Blend 指令分配混合因子外,还可以通过 BlendOp 指令指定混合的操作方法,即 f() 的部分。Unity支持的混合操作如下:

操作描述
Add相加,O = SrcFactor * SrcColor + DstFactor * DstColor
Sub相减,O = SrcFactor * SrcColor - DstFactor * DstColor
RevSub反向相减,O = DstFactor * DstColor - SrcFactor * SrcColor
Min各分量取最小值,O = (min(SR, DR), min(SG, DG), min(SB, DB), min(SA, DA))
Max各分量取最大值,O = (max(SR, DR), max(SG, DG), max(SB, DB), max(SA, DA))

当不指定BlendOp时,默认为 Add

1.4 常见的混合效果

通过对混合因子和混合操作进行组合,可以得到一些类似于PhotoShop混合模式中的混合效果:

效果组合
正常Blend SrcAlpha OneMinusSrcAlpha
柔和相加Blend OneMinusDstColor One
正片叠底Blend DstColor Zero
两倍相乘Blend DstColor SrcColor
变暗BlendOp Min / Blend One One
变亮BlendOp Max / Blend One One
滤色Blend OneMinusDstColor One 或者 Blend One OneMinusSrcColor
线性减淡Blend One One

2. 示例

  • 创建 Chapter_8_AlphaBlend_Mat 作为测试材质
  • 创建 Chapter_8_AlphaBlend_Shader 作为测试shader,并赋给 Chapter_8_AlphaBlend_Mat 材质
  • 场景中创建一个用于测试的立方体,将 Chapter_8_AlphaBlend_Mat 材质赋给立方体
  • 场景中添加一盏平行光,并调整平行光角度
  • 为了便于观察效果,在立方体下方创建一个Plane

在SubShader中设置标签

Tags { "Queue" = "Transparent" "RenderType" = "Transparent" "IgnoreProjector" = "True"}

在Pass中设置混合因子

Blend SrcAlpha OneMinusSrcAlpha

为了避免半透物体挡住其后物体的问题,需要在Pass中关闭深度写入

ZWrite Off

最后,在片元着色器的输出颜色中,Alpha值不能再像之前一样直接输出1,而是要根据实际情况输出(这里我没有设置Alpha值的缩放系数,直接用采样得到的Alpha输出)

最终Shader如下:

Shader "MyShader/Chapter_8/Chapter_8_AlphaBlend_Shader"
{
    Properties
    {
        _MainTex("MainTex", 2D) = "white"{}
    }
    
    SubShader
    {
        Tags { "Queue" = "Transparent" "RenderType" = "Transparent" "IgnoreProjector" = "True"}
    
        Pass
        {
            Tags {"LightMode" = "ForwardBase"}
            
            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha
        
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            
            struct a2v
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float2 uv : TEXCOORD0;
            };
            
            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
                float3 worldNormal : TEXCOORD1;
            };
            
            sampler2D _MainTex;
            float4 _MainTex_ST;
            
            v2f vert(a2v i)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(i.vertex);
                o.worldNormal = mul(i.normal, (float3x3)unity_WorldToObject);
                o.uv = TRANSFORM_TEX(i.uv, _MainTex);
                return o;
            }
            
            fixed4 frag(v2f i) : SV_Target
            {
                fixed3 _ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;
                float3 _worldNormal = normalize(i.worldNormal);
                float3 _worldLight = normalize(_WorldSpaceLightPos0.xyz);
                float4 _mainColor = tex2D(_MainTex, i.uv);
                fixed3 _diffuse = _LightColor0.rgb * _mainColor.xyz * (0.5 * dot(_worldLight, _worldNormal) + 0.5);
                return fixed4(_ambient + _diffuse, _mainColor.w);
            }
            
            ENDCG
        }
    
    }

}

效果如下:
在这里插入图片描述

  • 33
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值