• Alpha预乘-混合与不混合[转]


    Alpha Blending几乎是每个3D应用程序的一小部分,但却很重要。从概念上讲,alpha混合用于传达表面的透明度。通常,消费者应用程序(游戏)倾向于使用RGB来传达下层表面的颜色,依赖于alpha通道来指示该颜色的“不透明度”。更具体地说,当在管道中启用alpha混合时,开发人员倾向于使用此表单进行混合:

    DestinationColor.rgb = (SourceColor.rgb * SourceColor.a) + (DestinationColor.rgb * (1 - SourceColor.a));

    在旧的,固定的功能中,这将被称为“SourceAlpha,InvSourceAlpha”; 也被称为“后倍增α”。然而,这种形式的alpha混合存在一个严重的缺陷:在许多情况下它会导致错误的颜色!最简单的这些情况可以通过一个简单的双像素图像来说明:

    一个红色像素,红色= 1,alpha为1,绿色像素为绿色= 1,alpha为0.10

    考虑上面的图像,其分辨率为2x1像素。艺术家想要传达的是,在绿色像素旁边有一个红色的不透明像素,它只会给它背后的物体带来最轻微的绿色。但是,当我们生成下一个mipmap级别1x1级别时会发生一些有趣的事情。结果可能令人惊讶; 生成的mipmapped纹素是这样的:

    RGBA =(0.5,0.5,0,0.55)

    当我们接近这个mipmap级别时,我们将获得与使用2x1级别时非常不同的结果 - 完全是因为我们决定使用postmultiplied级别。您可以在以下图片中看到这一点:

     
    规范图像测试“mandrill”的三个版本。第一个,原始的mandrill。第二个包含与我们的2x1图像混合时的mandrill,最后一个与2x1纹理的1x1 mipmap混合。

    输入预乘的alpha

    使用预乘的alpha,我们在存储之前首先将纹理组件乘以alpha组件。我们还修改了混合函数,将SourceColor.a更改为One:

    DestinationColor.rgb = (SourceColor.rgb * One) + (DestinationColor.rgb * (1 - SourceColor.a));

    使用预乘的alpha,我们的原始纹理看起来像这样:

    我们的2x1纹理,准备好预乘alpha。R =(1,0,0,1),G =(0,0.1,0,0.1)

    此纹理的1x1 mipmap级别如下所示:

    我们预乘的alpha纹理的1x1 mipmap。RGBA =(0.5,0.05,0,0.55)

    这是很多更合理。我们仍然丢失了一些信息(请注意,如果绿色组件足够小,或者如果我们的精度太低,绿色将完全消失),但我们保留了更高分辨率的mipmap的意图。为了比较,这里再次是图像,增加了我们的预乘混合器:

    规范的山雀脸。 

       
    所有版本的mandrill。从上到下的顺序,原始的mandrill,原始的mandrill由我们的预乘α2x1覆盖,后乘α2x1,预乘1x1,最后是后乘1x1。

    从我们的后乘世界过渡

    方便地,从后乘的α管道到利用预乘的α的管道的转换是微不足道的。在纹理保存时间或资产烘焙时间,甚至加载时间,将每个非alpha通道乘以alpha。那是:

    OutputTexture.rgb = InputTexture.rgb * InputTexture.a; OutputTexture.a = InputTexture.a;

    并且不要忘记修改“alpha混合启用”以使用One作为Source Alpha值。如果我们将预乘的alpha插入到原始混合方程中,很容易看到切换到预乘的alpha会给出完全相同的结果:

    DestinationColor.rgb = ((SourceColor.rgb * SourceColor.a) * One) + (DestinationColor.rgb * (1 - SourceColor.a));

    所以你可能会问:如果结果相同,为什么还要加倍预乘?原因是纹理过滤。从纹理中获取样本时,除非已禁用纹理过滤,否则硬件会将相邻纹理像素混合在一起并返回加权平均值作为结果。使用传统的后乘法alpha,此结果将不正确。

    原文地址:https://developer.nvidia.com/content/alpha-blending-pre-or-not-pre

  • 相关阅读:
    家庭内网向导帮助文档
    Nginx 容器连接 php rc-fpm 容器编译 php
    samba 容器实现共享
    编程思想(POP,OOP,SOA,AOP)
    OOP(面向对象编程)
    MySql5.6 Window超详细安装教程
    JAVA设计模式:状态模式
    Mysql设置创建时间字段和更新时间字段自动获取时间,填充时间
    eclipse里新建work set,将项目分组放在不同文件夹
    错误记录
  • 原文地址:https://www.cnblogs.com/xiaonanxia/p/9448383.html
Copyright © 2020-2023  润新知