Xcode 的工程选项里有一项 Compress PNG Files,会对 PNG 进行 Premultiplied Alpha。游戏开发中会更加关注这个格式,省一些运行时计算。

Premultiplied Alpha 是什么呢?

Alpha Blending: To Pre or Not To Pre 这篇文章其实说的很清楚。还有《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 = asCs + (1 − as)Cd

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

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 − as)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)

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

三、纹理处理

我们使用的 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。

四、iOS 中的 Premultiplied Alpha

Core Graphics 的 CGImage.h 对图像透明度信息有如下定义

typedef CF_ENUM(uint32_t, CGImageAlphaInfo){
// ...
/* For example, premultiplied RGBA */
kCGImageAlphaPremultipliedLast,
/* For example, premultiplied ARGB */
kCGImageAlphaPremultipliedFirst,
// ...
};

预乘透明度(Premultiplied Alpha图像简单地说,即每个颜色分量都乘以 alpha 通道值作为结果值:

color.rgb *= color.alpha

为什么关注预乘透明度图像?微信团队因 AR 抢红包场景的 OpenGL 混色结果出错引起注意。

Premultiplied alpha is better than conventional blending for several reasons:

It works properly when filtering alpha cutouts _(see below)_

It works properly when doing image composition _(stay tuned for my next post)_

It is a superset of both conventional and additive blending. If you set alpha to zero while RGB is non zero, you get an additive blend. This can be handy for particle systems that want to smoothly transition from additive glowing sparks to dark pieces of soot as the particles age.

It plays nice with DXT compression, which only supports transparent pixels with an RGB of zero.

摘自:Premultiplied alpha

Premultiplied Alpha的更多相关文章

  1. [转]图片Premultiplied Alpha到底是干嘛用的

    Premultiplied Alpha 这个概念做游戏开发的人都不会不知道.Xcode 的工程选项里有一项 Compress PNG Files,会对 PNG 进行 Premultiplied Alp ...

  2. 图像处理术语解释:什么是PRGBA和Alpha预乘(Premultiplied Alpha )

    ☞ ░ 前往老猿Python博文目录 ░ Alpha预乘(Premultiplied Alpha)和PRGBA 一般来说四通道图像数据保存的都是ARGB或RGBA,其R.G.B值还没有进行任何透明化处 ...

  3. 图像处理术语解释:灰度、色相、饱和度、亮度、明度、阿尔法通道、HSL、HSV、RGBA、ARGB和PRGBA以及Premultiplied Alpha(Alpha预乘)等基础概念详解

    ☞ ░ 前往老猿Python博文目录 ░ 一.引言 由于老猿以前没接触过图像处理,在阅读moviepy代码时,对类的有些处理方法代码看不懂是什么含义,为此花了4天时间查阅了大量资料,并加以自己的理解和 ...

  4. 图片Alpha预乘的作用[转]

    Premultiplied Alpha 这个概念做游戏开发的人都不会不知道.Xcode 的工程选项里有一项 Compress PNG Files,会对 PNG 进行 Premultiplied Alp ...

  5. From Alpha to Gamma (II)

    这篇文章被拖延得这么久是因为我没有找到合适的引言 -- XXX 这一篇接着讲Gamma.近几年基于物理的渲染(Physically Based Shading, 后文简称PBS)开始在游戏业界受到关注 ...

  6. From Alpha to Gamma (I)

    What we think of as conventional alpha-blending is basically wrong. --Tom Forsyth 前段时间在Amazon上淘的三本二手 ...

  7. Win2D 官方文章系列翻译 - 预乘 Alpha

    本文为个人博客备份文章,原文地址: http://validvoid.net/win2d-premultiplied-alpha/ 在计算机绘图中有两种表示颜色值不透明度的方法.Win2D 中两种方法 ...

  8. 【探索】利用 canvas 实现数据压缩

    前言 HTTP 支持 GZip 压缩,可节省不少传输资源.但遗憾的是,只有下载才有,上传并不支持.如果上传也能压缩,那就完美了.特别适合大量文本提交的场合,比如博客园,就是很好的例子. 虽然标准不支持 ...

  9. Gamma校正与线性空间

    基础知识部分 为了方便理解,首先会对(Luminance)的相关概念做一个简单介绍.如果已经了解就跳到后面吧. 我们用Radiant energy(辐射能量)来描述光照的能量,单位是焦耳(J),因为光 ...

随机推荐

  1. fsLayuiPlugin数据表格动态转义

    数据表格动态转义提供一种更简洁的方式,主要解决前端laytpl模板转义的问题,对于一些简单的,例如:状态展示,我们可以通过前端编写laytpl模板来处理:对于动态的数据,通过这种静态方式是没有办法处理 ...

  2. ZYNQ入门实例——定时器中断与程序固化

    一.前言 APU系统中CPU以串行执行代码的方式完成操作,软件方式很难做到精准计时,因此调用内部定时器硬件完成计时是更好的选择.本文以定时器中断方式控制LED周期性闪烁为例学习私有定时器的使用.同时学 ...

  3. 实验一 Linux系统与应用准备

    实验一 Linux系统与应用准备 项目 内容 作业归属 班级课程 作业要求 课程作业要求 学号-姓名 17041419-刘金林 作业学习目标 1.学习博客园软件开发者学习社区使用技巧和经验:2.学习M ...

  4. python-面向对象小结

    面向对象 小结 1:面向对象:就是一种编程思想 简称oop,指挥某某完成能完成的功能 2:面向对象与面向过程的优缺点 : 面向过程: 优点: 复杂问题简答化(一步一步解决), 流程化, 缺点:机械化 ...

  5. AlphaGo、人工智能、深度学习解读以及应用

    经过比拼,AlphaGo最终还是胜出,创造了人机大战历史上的一个新的里程碑.几乎所有的人都在谈论这件事情,这使得把“人工智能”.“深度学习”的热潮推向了新的一个高潮.AlphaGo就像科幻电影里具有人 ...

  6. xadmin theme

    我在user的adminx中设置了为True之后,我的主题还是加载不出来,具体没找到原因,网上也没有找到相应的资料,不过通过尝试,可以根据需要,添加自己需要的主题,操作如下: 1.找到xadmin文件 ...

  7. chrome安装扩展插件出现-crx_header_invalid问题

    1. 将*.crx文件重命名为*.rar 2.将rar文件解压 3. 在chrome浏览器添加扩展程序时选择“加载已解压的扩展程序” 4.添加成功

  8. 曹工说mini-dubbo(1)--为了实践动态代理,我写了个简单的rpc框架

    相关背景及资源: 之前本来一直在写spring源码解析这块,如下,aop部分刚好写完.以前零散看过一些文章,知道rpc调用基本就是使用动态代理,比如rmi,dubbo,feign调用等.自己也就想着试 ...

  9. Simulink仿真入门到精通(七) Simulink的回调函数

    7.1 什么是回调函数 Callback functions(回调函数)是因某种操作而除法对其调用的函数,如按下按钮或双击操作等. 常用的Simulink回调函数可应用在以下场合: 打开Simulin ...

  10. 用shell脚本实现定时备份数据库

    1.备份数据库的方法 可以使用命令查看 ls  /usr/local/mysql/bin 这个mysqldump就是系统内置的用来备份数据库的工具. 2.实现方法 ①先随便进入一个位置创建一个目录 ② ...