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上,混合后的颜色通过以下公式计算,
以60%透明的红色渲染到白色背景为例:
也就是说,从视觉上,(255, 0, 0, 0.6)渲染到白色背景上 和 (255, 102, 102) 是同一个颜色。如果颜色以 Premultiplied Alpha 形式存储,也就是Cs已经乘以透明度了,所以混合公式变成了:
为什么要 Premultiplied Alpha 呢?
Premultiplied Alpha 后的像素格式变得不直观,因为在画图的时候都是先从调色板中选出一个RGB颜色,再单独设置透明度,如果RGB乘以透明度就搞不清楚原色是什么了。从前面的 Alpha Blending 公式可以看出,Premultiplied Alpha 之后,混合的时候可以少一次乘法,这可以提高一些效率,但这并不是最主要的原因。最主要的原因是:
没有 Premultiplied Alpha 的纹理无法进行 Texture Filtering(除非使用最近邻插值)。
以最常见的 filtering 方式线性插值为例,一个宽2px高1px的图片,左边的像素是红色,右边是绿色10%透明度,如果把这个图片缩放到1x1的大小,那么缩放后1像素的颜色就是左右两个像素线性插值的结果,也就是把两个像素各个通道加起来除以2。如果使用没有 Premultiplied Alpha 的颜色进行插值,那么结果就是:
如果绿色 Premultiplied Alpha,也就是 (0, 255 * 0.1, 0, 0.1),和红色混合后:
从上面的图里第三个颜色是没有 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。
相关推荐
"PRGBA"和"Alpha预乘(Premultiplied Alpha)"就是两个这样的关键术语,它们涉及到颜色混合和透明效果的实现。 首先,我们来理解PRGBA。这个术语是“Pre-Multiplied RGB with Alpha”的缩写,它是颜色通道的一种...
1. `D3DRS_ALPHATESTENABLE` 设置为 FALSE,因为我们要使用Alpha混合而不是Alpha测试。 2. `D3DRS_ALPHABLENDENABLE` 设置为 TRUE,开启Alpha混合功能。 3. `D3DRS_SRCBLEND` 设置为 D3DBLEND_SRCALPHA,定义源颜色...
除了这些基本步骤,还可以通过调整Alpha Blending的参数,实现更复杂的效果,比如预乘Alpha(premultiplied alpha)、颜色剪切(color clamping)和深度排序等。预乘Alpha处理了颜色和Alpha的关系,颜色剪切防止颜色...
常见的混合函数包括Additive(加法)、Multiply(乘法)、Subtractive(减法)以及Premultiplied Alpha(预乘Alpha)等。 在2D游戏中,Alpha混合常用于创建精灵(Sprite)的半透明效果,如烟雾、云朵或者角色的透明...
对于带有Alpha通道的图像,我们可以使用"Premultiplied Alpha Blending"(预乘Alpha混合)算法,它考虑了颜色值与Alpha值的关系。 6. **Premultiplied Alpha Blending**:这是一种常见的图像混合技术,其基本思想是...
" Straight to Premultiplied"选项涉及Alpha通道的处理,它将直通Alpha(Straight Alpha)转换为预乘Alpha(Premultiplied Alpha),以更精确地处理带有透明度的图像。红、绿、蓝和Alpha通道是图像的基础,而Hue、...
2. **颜色空间**:iOS系统倾向于使用Premultiplied Alpha(预乘Alpha)的颜色空间,这意味着像素的RGB值已经与Alpha通道的透明度相乘。非预乘Alpha的PNG图片在iOS上可能会出现色彩失真的问题,源码可能包含转换颜色...
最后,Premultiplied Alpha(Alpha预乘)是一种优化的技术,它将颜色分量与Alpha值相乘,使得在混合透明图像时能减少错误和边缘锯齿现象。这种技术在3D图形渲染、视频合成等领域广泛应用。 综上所述,理解这些图像...
这个效果可以帮助去除由于Alpha通道处理不当或者素材预乘Alpha(Premultiplied Alpha)导致的光晕,使得遮罩边缘更加平滑,减少与背景的冲突。 除了Remove Color Matting,还有其他几个相关的工具和概念值得了解: ...
优化策略包括:分组渲染(相同透明度的物体一起绘制)、使用alpha测试(只绘制alpha值超过某个阈值的像素)等。 6. **纹理格式和颜色空间**:选择正确的纹理格式和颜色空间也很关键。例如,使用RGBA格式可以存储...
QImage rotatedImage(originalImage.size(), QImage::Format_ARGB32_Premultiplied); rotatedImage.fill(Qt::transparent); // 使用QPainter在新的QImage上绘制旋转后的原始图像 painter.drawImage(QPoint(0, 0), ...
* Premultiplied(预乘):将A的蒙版值与B的蒙版值相乘,并且对B进行预乘处理。 * Unpremultiplied(非预乘):将A的蒙版值与B的蒙版值相加,并且对B进行非预乘处理。 5. 其他运算 除上述运算方式外,Nuke软件还...
return QImage::Format_ARGB4444_Premultiplied; } ``` 同时,还需要处理创建和初始化Framebuffer设备的部分。这通常包括打开Framebuffer设备节点,获取Framebuffer的信息(如宽度、高度、像素格式等),并根据...
这涉及到颜色的Alpha混合算法,如Alpha blending或Premultiplied Alpha blending。 三、源码解析 压缩包中的"易语言D2D透明块复制源码"提供了具体的实现细节。易语言是一种面向对象的中文编程语言,它提供了与D2D...
1. 创建一个QImage对象,指定其大小并设置ARGB32或ARGB32_Premultiplied格式,这两种格式都支持Alpha通道。 2. 使用QPainter的begin()方法开始绘制操作,并将其绑定到目标设备,如QLabel、QWidget或其他可绘对象。 3...
使用PixelFormer并按照以下步骤操作: 在PixelFormer中打开具有透明度的16x16 PNG文件单击File -> Export 选择BMP作为“保存类型” 单击Save ,然后在以下窗口中选择A8:R8:G8:B8 (32 bpp) 检查Premultiplied alpha ...
例如,可以使用预乘阿尔法(premultiplied alpha)优化混合效果,或者使用低多边形模型和简化纹理来降低资源消耗。 总的来说,"OpenGL ES 2.0 散射光Demo"是一个学习和实践移动设备图形编程的好案例,它涵盖了顶点...
- **Premultiplied Alpha**: 在WebGL中,预乘Alpha是一种处理透明度的技术,其中每个颜色通道都被Alpha值预先缩放。 - **Canvas APIs**: WebGL与HTML5 Canvas API紧密集成,可以利用Canvas API的功能来处理图像数据...
若勾选后显示正常,则应在导出 Atlas 文件时使用 premultiplied alpha 设置。 - **动画冲突**:当一个动画改变了某个骨架的状态时,这种改变会一直保留,直到被另一个动画或代码手动更改。为了避免这种情况,建议在...