当前位置:   article > 正文

透明度测试(AlphaTest)和混合(Blend)的基础知识_alpha test

alpha test

本文分享透明度测试(AlphaTest)和混合(Blend)的基础知识

透明度测试和透明度混合都是用来处理半透明效果的手段.

在裁剪测试之后, 如果有一些半透片元需要抛弃(比如png纹理的多余空白), 可以通过透明度测试达到目的.

在深度测试通过之后, 渲染管线进入混合阶段, 在混合阶段处理不透明物体或者半透物体的颜色混合.

为什么透明效果需要处理

我们先说明不透明物体的处理过程.

深度测试通过之后, 相互遮挡的不透明物体开始进行颜色混合, 所谓颜色混合就是如何处理源颜色(待渲染的片元颜色)目标颜色(颜色缓存中已经存储的片元颜色).

默认情况下的操作就是使用源颜色覆盖目标颜色. 当然我们可以通过给混合函数传递不同的参数来改写操作.

接下来说说有透明效果的物体的处理过程.

有透明效果说明我们想要的是透过该物体可以看到起后面的物体, 但是如果采用默认的混合操作, 会使用透明物体的颜色更新颜色目标颜色, 我们就无法看到后面的物体了, 所以对于透明物体需要单独处理. 当然, 如果是不透明物体遮挡透明物体, 则采用默认的行为即可.

半透明物体的基本处理

现在常用的手段有两种, 一个是透明度测试, 一个是透明度混合.

透明度测试很简单, 就是在处理片元时, 给定一个阈值, 如果片元的透明度低于该值, 则抛弃该片元. 一般通过api提供的Clip函数完成. 如下:

// 模拟实现
void clip(value)
{
    if (value < 0)
        discard;
}

// Unity的片元着色器
fixed4 frag(v2f i) : SV_Target {
    fixed3 worldNormal = normalize(i.worldNormal);
    fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));

    fixed4 texColor = tex2D(_MainTex, i.uv);

    // Alpha test 若texColor.a小于_Cutoff,则物体完全透明
    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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

透明度测试一般用来过滤一些不受关注的透明片元, 并不是主流的透明物体处理方案, 因为它的结果是非此即彼, 就是说要么完全看得到, 要么完全看不到.

半透物体的处理主要还是使用透明度混合, 原理也十分简单, 就是在混合阶段使用片元的透明度来处理颜色混合, 具体实现是通过给混合函数传递透明度相关的参数.

Unity中的各种颜色混合

Unity中使用Blend函数和BlendOp函数来处理混合操作.

混合的原理是分别对源颜色和目标颜色做颜色和透明度的处理:

  • 使用颜色混合因子分别混合源颜色和目标颜色: O ( s ) r g b = F a c t o r s r c ∗ R G B s r c ; O ( d ) r g b = F a c t o r d s t ∗ R G B d s t O(s)_{rgb}=Factor_{src} * {RGB}_{src}; O(d)_{rgb}=Factor_{dst} * RGB_{dst} O(s)rgb=FactorsrcRGBsrc;O(d)rgb=FactordstRGBdst
  • 使用透明度混合因子分别混合源透明和目标透明度: O ( s ) a l p h a = F a c t o r A s r c ∗ A l p h a s r c ; O ( d ) a l p h a = F a c t o r A d s t ∗ A l p h a d s t O(s)_{alpha}=FactorA_{src} * Alpha_{src}; O(d)_{alpha}=FactorA_{dst} * Alpha_{dst} O(s)alpha=FactorAsrcAlphasrc;O(d)alpha=FactorAdstAlphadst
  • 将源颜色混合结果与目标颜色混合结果按照设定的逻辑处理(比如加, 减等): O r g b = O ( s ) r g b + O ( d ) r g b O{rgb}=O(s)_{rgb}+O(d)_{rgb} Orgb=O(s)rgb+O(d)rgb
  • 将源透明度混合结果与目标透明度混合结果按照设定的逻辑处理(比如加, 减等) O a l p h a = O ( s ) a l p h a + O ( d ) a l p h a O{alpha}=O(s)_{alpha}+O(d)_{alpha} Oalpha=O(s)alpha+O(d)alpha

Blend 用于开关混合功能, 可能的参数有:

  • Blend Off: 关闭混合, 直接覆盖目标颜色
  • Blend srcFactor destFactor: 使用相同的混合因子混合颜色和透明度
  • Blend srcFactor destFactor, srcFactorA destFactorA : 使用不同的混合因子混合颜色和透明度

混合因子可能的取值有:

  • One: 1
  • Zero: 0
  • SrcColor: 使用源颜色作为混合因子, 源颜色的rgb作为颜色混合因子, alpha作为透明度混合因子
  • DstColor: 使用目标颜色作为混合因子, 目标颜色的rgb作为颜色混合因子, alpha作为透明度混合因子
  • SrcAlpha: 使用源颜色的alpha作为rgb和alpha的混合因子
  • DstAlpha: 使用目标颜色的alpha作为rgb和alpha的混合因子
  • OneMinusSrcColor: 与SrcColor类似, 只不过是将各个分量被1减之后得到的颜色作为混合因子
  • OneMinusDstColor: 与DstColor类似, 只不过是将各个分量被1减之后得到的颜色作为混合因子
  • OneMinusSrcAlpha: 与OneMinusSrcColor类似, 只不过是将alpha被1减之后得到的alpha作为混合因子
  • OneMinusDstAlpha: 与OneMinusDstColor类似, 只不过是将alpha被1减之后得到的alpha作为混合因子

Unity默认参数是Blend One Zero, 使用源颜色覆盖目标颜色.

一般渲染半透明物体时使用Blend SrcAlpha OneMinusSrcAlpha.

BlendOp用于定义源颜色和目标颜色分别混合后进行的操作, 默认是BlendOp Add:

  • Add: 加
  • Sub: 减
  • RevSub: 目标-源
  • Min: 目标和源各个分量分别进行取较小值(是混合之前的颜色, 此参数下混合因子不生效)
  • Max: 目标和源各个分量分别进行取较大值(是混合之前的颜色, 此参数下混合因子不生效)

表面剔除和双面渲染

默认情况下, Unity会做表面剔除(通过Cull Front/Back来剔除正面或者背面), 也就是说会将物体内外某个方向的面去掉以提高渲染效率.

在渲染半透明物体时, 有时我们希望透过半透明部分看到物体内部, 比如通过窗户来看到屋子里的内容, 就可以关闭剔除效果Cull Off来达到目的.

有些半透明物体内部互相交叉会导致渲染错乱, 如下:

在这里插入图片描述

可以通过双面渲染解决, 双面渲染就是使用两个Pass来分两次分别渲染物体的正面和背面:

Pass{
    // 剔除正面
    Cull Front
	ZWrite Off
	Blend SrcAlpha OneMinusSrcAlpha
    // ... 着色
}

Pass{
    // 剔除背面
    Cull Back
	ZWrite Off
	Blend SrcAlpha OneMinusSrcAlpha
    // ... 着色
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

总结

今天主要对透明度测试和颜色混合还有半透明物体的渲染做了基本的介绍.

半透明物体的渲染在业界一直是一个比较复杂的问题, 今天的内容只是能够解决大部分情况, 还有一些特殊情况需要特殊处理.

希望对大家有所帮助.

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/107732
推荐阅读
相关标签
  

闽ICP备14008679号