`
陈浩k啦你
  • 浏览: 7351 次
  • 性别: Icon_minigender_1
  • 来自: 广州
最近访客 更多访客>>
社区版块
存档分类
最新评论

【转】Premultiplied Alpha 到底是干嘛用的

阅读更多

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)Cd

 

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

Co=(255,0,0)0.6+(255,255,255)(10.6)=(255,102,102)


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

Co=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)

 

如果绿色 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。

 

原文地址:http://boundary.cc/2015/07/why-premultiplied-alpha/

分享到:
评论

相关推荐

    音视频资料-图像处理术语解释:什么是PRGBA和Alpha预乘(Premultiplied Alpha ).rar

    "PRGBA"和"Alpha预乘(Premultiplied Alpha)"就是两个这样的关键术语,它们涉及到颜色混合和透明效果的实现。 首先,我们来理解PRGBA。这个术语是“Pre-Multiplied RGB with Alpha”的缩写,它是颜色通道的一种...

    VS2008下的win32Alpha混合的例子

    1. `D3DRS_ALPHATESTENABLE` 设置为 FALSE,因为我们要使用Alpha混合而不是Alpha测试。 2. `D3DRS_ALPHABLENDENABLE` 设置为 TRUE,开启Alpha混合功能。 3. `D3DRS_SRCBLEND` 设置为 D3DBLEND_SRCALPHA,定义源颜色...

    dx9_alpha_blending_material.rar_Alpha

    除了这些基本步骤,还可以通过调整Alpha Blending的参数,实现更复杂的效果,比如预乘Alpha(premultiplied alpha)、颜色剪切(color clamping)和深度排序等。预乘Alpha处理了颜色和Alpha的关系,颜色剪切防止颜色...

    D3D-study.rar_Alpha_d3d_d3d 2d

    常见的混合函数包括Additive(加法)、Multiply(乘法)、Subtractive(减法)以及Premultiplied Alpha(预乘Alpha)等。 在2D游戏中,Alpha混合常用于创建精灵(Sprite)的半透明效果,如烟雾、云朵或者角色的透明...

    VC 实现两张图片透明化并合成新图像.rar

    对于带有Alpha通道的图像,我们可以使用"Premultiplied Alpha Blending"(预乘Alpha混合)算法,它考虑了颜色值与Alpha值的关系。 6. **Premultiplied Alpha Blending**:这是一种常见的图像混合技术,其基本思想是...

    AE层的通道合成器.pdf

    " Straight to Premultiplied"选项涉及Alpha通道的处理,它将直通Alpha(Straight Alpha)转换为预乘Alpha(Premultiplied Alpha),以更精确地处理带有透明度的图像。红、绿、蓝和Alpha通道是图像的基础,而Hue、...

    IOS应用源码之转换iPhonePNG图片为标准格式src.zip

    2. **颜色空间**:iOS系统倾向于使用Premultiplied Alpha(预乘Alpha)的颜色空间,这意味着像素的RGB值已经与Alpha通道的透明度相乘。非预乘Alpha的PNG图片在iOS上可能会出现色彩失真的问题,源码可能包含转换颜色...

    音视频资料-图像处理术语解释:灰度、色相、饱和度、亮度、明度、阿尔法通道、

    最后,Premultiplied Alpha(Alpha预乘)是一种优化的技术,它将颜色分量与Alpha值相乘,使得在混合透明图像时能减少错误和边缘锯齿现象。这种技术在3D图形渲染、视频合成等领域广泛应用。 综上所述,理解这些图像...

    AE层的遮罩颜色消除.pdf

    这个效果可以帮助去除由于Alpha通道处理不当或者素材预乘Alpha(Premultiplied Alpha)导致的光晕,使得遮罩边缘更加平滑,减少与背景的冲突。 除了Remove Color Matting,还有其他几个相关的工具和概念值得了解: ...

    游戏中用到的透明效果

    优化策略包括:分组渲染(相同透明度的物体一起绘制)、使用alpha测试(只绘制alpha值超过某个阈值的像素)等。 6. **纹理格式和颜色空间**:选择正确的纹理格式和颜色空间也很关键。例如,使用RGBA格式可以存储...

    QT图像旋转功能的实现

    QImage rotatedImage(originalImage.size(), QImage::Format_ARGB32_Premultiplied); rotatedImage.fill(Qt::transparent); // 使用QPainter在新的QImage上绘制旋转后的原始图像 painter.drawImage(QPoint(0, 0), ...

    Nuke软件各种运算方法.pdf

    * Premultiplied(预乘):将A的蒙版值与B的蒙版值相乘,并且对B进行预乘处理。 * Unpremultiplied(非预乘):将A的蒙版值与B的蒙版值相加,并且对B进行非预乘处理。 5. 其他运算 除上述运算方式外,Nuke软件还...

    QT使用 Linux framebuffer时候 支持QT本身不支持的其他格式(例如支持argb4444)的一种取巧方法

    return QImage::Format_ARGB4444_Premultiplied; } ``` 同时,还需要处理创建和初始化Framebuffer设备的部分。这通常包括打开Framebuffer设备节点,获取Framebuffer的信息(如宽度、高度、像素格式等),并根据...

    D2D透明块复制.rar

    这涉及到颜色的Alpha混合算法,如Alpha blending或Premultiplied Alpha blending。 三、源码解析 压缩包中的"易语言D2D透明块复制源码"提供了具体的实现细节。易语言是一种面向对象的中文编程语言,它提供了与D2D...

    argb.rar_argb_argb显示效果

    1. 创建一个QImage对象,指定其大小并设置ARGB32或ARGB32_Premultiplied格式,这两种格式都支持Alpha通道。 2. 使用QPainter的begin()方法开始绘制操作,并将其绑定到目标设备,如QLabel、QWidget或其他可绘对象。 3...

    EditableContextMenu:WIP-Windows的可编辑上下文菜单外壳扩展

    使用PixelFormer并按照以下步骤操作: 在PixelFormer中打开具有透明度的16x16 PNG文件单击File -> Export 选择BMP作为“保存类型” 单击Save ,然后在以下窗口中选择A8:R8:G8:B8 (32 bpp) 检查Premultiplied alpha ...

    OpenGL ES 2.0 散射光demo

    例如,可以使用预乘阿尔法(premultiplied alpha)优化混合效果,或者使用低多边形模型和简化纹理来降低资源消耗。 总的来说,"OpenGL ES 2.0 散射光Demo"是一个学习和实践移动设备图形编程的好案例,它涵盖了顶点...

    WebGL说明书(英文)

    - **Premultiplied Alpha**: 在WebGL中,预乘Alpha是一种处理透明度的技术,其中每个颜色通道都被Alpha值预先缩放。 - **Canvas APIs**: WebGL与HTML5 Canvas API紧密集成,可以利用Canvas API的功能来处理图像数据...

    Spine 骨骼动画查看器Skeleton Viewer_官方文档中文版

    若勾选后显示正常,则应在导出 Atlas 文件时使用 premultiplied alpha 设置。 - **动画冲突**:当一个动画改变了某个骨架的状态时,这种改变会一直保留,直到被另一个动画或代码手动更改。为了避免这种情况,建议在...

Global site tag (gtag.js) - Google Analytics