转载自:https://www.cnblogs.com/xiaonanxia/p/9448444.html

Premultiplied Alpha 这个概念做游戏开发的人都不会不知道。Xcode 的工程选项里有一项 Compress PNG Files,会对 PNG 进行 Premultiplied Alpha,Texture Packer 中也有Premultiplied Alpha 的选项。那么问题来了,Premultiplied Alpha 是什么呢?我被这个问题困惑了很久,之前搜到过 Nvidia的这篇文章,其实说的很清楚,只是当时有很多相关概念没搞清楚,所以没看懂。直到前几天读《Real Time Rendering》时终于搞懂了。

Alpha Blending

要搞清楚这个问题,先得理解Alpha通道的工作原理,如果你已经了解可以直接跳过。

最常见的像素表示格式是RGBA8888即 (r, g, b, a),每个通道8位,0-255。例如红色60%透明度就是 (255, 0, 0, 153),为了表示方便alpha通道一般记成正规化后的0-1的浮点数,也就是 (255, 0, 0, 0.6)。而 Premultiplied Alpha 则是把RGB通道乘以透明度也就是 (r * a, g * a, b * a, a),50%透明红色就变成了(153, 0, 0, 0.6)。

透明通道在渲染的时候通过 Alpha Blending 产生作用,如果一个透明度为 as 的颜色 Cs 渲染到颜色 Cd上,混合后的颜色通过以下公式计算,

Co=αsCs+(1−αs)CdCo=αsCs+(1−αs)Cd

以60%透明的红色渲染到白色背景为例:

Co=(255,0,0)⋅0.6+(255,255,255)⋅(1−0.6)=(255,102,102)Co=(255,0,0)⋅0.6+(255,255,255)⋅(1−0.6)=(255,102,102)

也就是说,从视觉上,(255, 0, 0, 0.6)渲染到白色背景上 和 (255, 102, 102) 是同一个颜色。如果颜色以 Premultiplied Alpha 形式存储,也就是Cs已经乘以透明度了,所以混合公式变成了:

Co=Cs′+(1−αs)CdCo=Cs′+(1−αs)Cd

为什么要 Premultiplied Alpha 呢?

Premultiplied Alpha 后的像素格式变得不直观,因为在画图的时候都是先从调色板中选出一个RGB颜色,再单独设置透明度,如果RGB乘以透明度就搞不清楚原色是什么了。从前面的 Alpha Blending 公式可以看出,Premultiplied Alpha 之后,混合的时候可以少一次乘法,这可以提高一些效率,但这并不是最主要的原因。最主要的原因是:

没有 Premultiplied Alpha 的纹理无法进行 Texture Filtering(除非使用最近邻插值)。

以最常见的 filtering 方式线性插值为例,一个宽2px高1px的图片,左边的像素是红色,右边是绿色10%透明度,如果把这个图片缩放到1x1的大小,那么缩放后1像素的颜色就是左右两个像素线性插值的结果,也就是把两个像素各个通道加起来除以2。如果使用没有 Premultiplied Alpha 的颜色进行插值,那么结果就是:

((255,0,0,1)+(0,255,0,0.1))⋅0.5=(127,127,0,0.55)((255,0,0,1)+(0,255,0,0.1))⋅0.5=(127,127,0,0.55)

如果绿色 Premultiplied Alpha,也就是 (0, 255 * 0.1, 0, 0.1),和红色混合后:

((255,0,0,1)+(0,25,0,0.1))⋅0.5=(127,25,0,0.55)

从上面的图里第三个颜色是没有 Premultiplied Alpha 的混合结果,对比第四个 Premultiplied Alpha 后颜色的结果,显然第四个颜色更符合直觉,第三个颜色太绿了,因为绿色通道没有乘以透明度,所以在线性插值的时候占了过大的权重。

所以 Premultiplied Alpha 最重要的意义是使得带透明度图片纹理可以正常的进行线性插值。这样旋转、缩放或者非整数的纹理坐标才能正常显示,否则就会像上面的例子一样,在透明像素边缘附近产生奇怪的颜色。

纹理处理

我们使用的PNG图片纹理,一般是不会 Premultiplied Alpha 的。游戏引擎在载入PNG纹理后回手动处理,然后再glTexImage2D传给GPU,比如 Cocos2D-x 中的 CCImage::premultipliedAlpha:

void Image::premultipliedAlpha() {unsigned int* fourBytes = (unsigned int*)_data;for (int i = 0; i < _width * _height; i++) {unsigned char* p = _data + i * 4;fourBytes[i] = CC_RGB_PREMULTIPLY_ALPHA(p[0], p[1], p[2], p[3]);}  _hasPremultipliedAlpha = true;
}

 

而GPU专用的纹理格式,比如 PVR、ETC 一般在生成纹理都是默认 Premultiplied Alpha 的,这些格式一般是GPU硬解码,引擎用CPU处理会很慢。

总之 glTexImage2D 传给 GPU 的纹理数据最好都是 Multiplied Alpha 的,要么在生成纹理时由纹理工具 Pre-multiplied,要么载入纹理后由游戏引擎或UI框架 Post-multiplied。

预乘Alpha的作用相关推荐

  1. VS2017中预编译头的作用(删除pch.h报错的原因)

    刚使用VS2017的时候新建的项目的pch.h文件搞得一头雾水,点进去看了这个文件,发现里面什么内容都没有,但是把他删除之后就会报错说没有添加pch.h文件.百度了一下,发现这个是VS2017新加的一 ...

  2. iOS之深入解析预乘透明度Premultiplied Alpha

    一.前言 Premultiplied Alpha 的概念,做过游戏开发的应该都知道,Xcode 的工程选项里有一项 Compress PNG Files,会对 PNG 进行 Premultiplied ...

  3. Alpha预乘-混合与不混合[转]

    作者:John McDonald,于2013年1月31日上午07:57发布 标签:  GameWorks专家开发人员 Alpha Blending几乎是每个3D应用程序的一小部分,但却很重要.从概念上 ...

  4. 【渲染】解决三维出图黑白边缘溢出问题:直通(STRAIGHT)与预乘(PREMULT)ALPHA剖析

    昨天我录了一期视频讲解决模型高亮边缘锯齿问题的.今天在群里跟朋友们讨论,结果有人丢出一个文档说是讲的内容有类似.我打开一看,我去,这文档内容写的确实赞,内容深刻,讲解深入浅出,鞭辟入里:而且有一种莫名 ...

  5. 大模型系统和应用——Transformer预训练语言模型

    引言 最近在公众号中了解到了刘知远团队退出的视频课程<大模型交叉研讨课>,看了目录觉得不错,因此拜读一下. 观看地址: https://www.bilibili.com/video/BV1 ...

  6. 啥是预乘?——Nuke中的Premult(预乘)和Unpremult(预除)

    本文不定期更新,最新内容请访问:https://www.shuaiqi.me/2019/04/03/shashiyuchengnukezhongdepremultyuchengheunpremultf ...

  7. 预、自训练之争:谷歌说预训练虽火,但在标注数据上自训练更有效

    公众号关注 "视学算法" 设为 "星标",重磅干货,第一时间送达! 来源 | 机器之心 预训练是当前计算机视觉领域的主要范式,但何恺明等人先前的研究发现,预训练 ...

  8. linux下程序执行的步骤及其作用

    程序执行的步骤及其作用 在linux下使用gcc编程时,从表面上看是简单的命令的执行,但实际上,程序的执行分为四个步骤:预编译,编译,汇编,链接. 预编译 在linux系统下,一个.c文件经过预编译生 ...

  9. 【深度学习】keras框架使用预训练模型进行Finetune的应用

    文章目录 1 概述 2 Keras 3 VGG16 (VGG16) 4 MobileNetV2 (MobileNetV2) 5 盗版ResNetV2 (InceptionResNetV2) 6 盗梦空 ...

最新文章

  1. ajax ie7没有权限,jquery ajax 在ie7不能正常使用
  2. xshell xftp使用
  3. 在正确的方向坚持下去,一直坚持下去,直到有成果
  4. boost::geometry::index:containst用法的测试程序
  5. 【Boost】boost库中thread多线程详解8——call_once仅运行一次
  6. 串口服务器常见异常情况排除方法介绍
  7. PHP操作数据库,不推荐使用mysql函数,而推荐使用mysqli和PDO函数
  8. Typescript 学习笔记一:介绍、安装、编译
  9. 不要轻易碰我,不然我就知道你有多软了 | Science Robotics
  10. java dom_Java DOM 解析 XML详解
  11. java获取网页的内容_java获取网页内容
  12. 封装mysql数据库操作系统_封装MySQL的单例,连接数据库并对数据进行增删改查操作...
  13. postman的基础使用
  14. ue编辑器漏洞_UEditor编辑器任意文件上传漏洞分析
  15. 视频教程-轻松搞定Spring全家桶(初识篇)-Java
  16. python列表平均值的算法_python计算一个序列的平均值的方法
  17. 计算机比赛小组名称和口号,小组名称口号大全(精选150个)
  18. three.js纹理贴图不显示
  19. 华为云服务-申请基础云服务2
  20. 广电电视信号如何生成RTMP流进入流媒体系统网络分发实现手机APP播放

热门文章

  1. javaweb JAVA JSP停车场管理系统源码JSP停车收费系统JSP停车场管理 JSP停车场收费系统
  2. ubuntu下面kill掉卡巴斯基shell脚本
  3. 访问OSS图片,返回状态码 Code UserDisable?
  4. python读取文件夹下所有文件
  5. thinkpad x1 carbon电池充不进去电解决方案
  6. 当你亚马逊店铺注册出现问题了你要怎么解决?
  7. 【QT5】QListWidget列表框的使用
  8. 龙应台心灵的X光(转)
  9. HOOPS/QT集成指南
  10. 基金投资入门教程-----学会资产配置,更安慰地赚钱