预乘Alpha的作用
转载自: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的作用相关推荐
- VS2017中预编译头的作用(删除pch.h报错的原因)
刚使用VS2017的时候新建的项目的pch.h文件搞得一头雾水,点进去看了这个文件,发现里面什么内容都没有,但是把他删除之后就会报错说没有添加pch.h文件.百度了一下,发现这个是VS2017新加的一 ...
- iOS之深入解析预乘透明度Premultiplied Alpha
一.前言 Premultiplied Alpha 的概念,做过游戏开发的应该都知道,Xcode 的工程选项里有一项 Compress PNG Files,会对 PNG 进行 Premultiplied ...
- Alpha预乘-混合与不混合[转]
作者:John McDonald,于2013年1月31日上午07:57发布 标签: GameWorks专家开发人员 Alpha Blending几乎是每个3D应用程序的一小部分,但却很重要.从概念上 ...
- 【渲染】解决三维出图黑白边缘溢出问题:直通(STRAIGHT)与预乘(PREMULT)ALPHA剖析
昨天我录了一期视频讲解决模型高亮边缘锯齿问题的.今天在群里跟朋友们讨论,结果有人丢出一个文档说是讲的内容有类似.我打开一看,我去,这文档内容写的确实赞,内容深刻,讲解深入浅出,鞭辟入里:而且有一种莫名 ...
- 大模型系统和应用——Transformer预训练语言模型
引言 最近在公众号中了解到了刘知远团队退出的视频课程<大模型交叉研讨课>,看了目录觉得不错,因此拜读一下. 观看地址: https://www.bilibili.com/video/BV1 ...
- 啥是预乘?——Nuke中的Premult(预乘)和Unpremult(预除)
本文不定期更新,最新内容请访问:https://www.shuaiqi.me/2019/04/03/shashiyuchengnukezhongdepremultyuchengheunpremultf ...
- 预、自训练之争:谷歌说预训练虽火,但在标注数据上自训练更有效
公众号关注 "视学算法" 设为 "星标",重磅干货,第一时间送达! 来源 | 机器之心 预训练是当前计算机视觉领域的主要范式,但何恺明等人先前的研究发现,预训练 ...
- linux下程序执行的步骤及其作用
程序执行的步骤及其作用 在linux下使用gcc编程时,从表面上看是简单的命令的执行,但实际上,程序的执行分为四个步骤:预编译,编译,汇编,链接. 预编译 在linux系统下,一个.c文件经过预编译生 ...
- 【深度学习】keras框架使用预训练模型进行Finetune的应用
文章目录 1 概述 2 Keras 3 VGG16 (VGG16) 4 MobileNetV2 (MobileNetV2) 5 盗版ResNetV2 (InceptionResNetV2) 6 盗梦空 ...
最新文章
- ajax ie7没有权限,jquery ajax 在ie7不能正常使用
- xshell xftp使用
- 在正确的方向坚持下去,一直坚持下去,直到有成果
- boost::geometry::index:containst用法的测试程序
- 【Boost】boost库中thread多线程详解8——call_once仅运行一次
- 串口服务器常见异常情况排除方法介绍
- PHP操作数据库,不推荐使用mysql函数,而推荐使用mysqli和PDO函数
- Typescript 学习笔记一:介绍、安装、编译
- 不要轻易碰我,不然我就知道你有多软了 | Science Robotics
- java dom_Java DOM 解析 XML详解
- java获取网页的内容_java获取网页内容
- 封装mysql数据库操作系统_封装MySQL的单例,连接数据库并对数据进行增删改查操作...
- postman的基础使用
- ue编辑器漏洞_UEditor编辑器任意文件上传漏洞分析
- 视频教程-轻松搞定Spring全家桶(初识篇)-Java
- python列表平均值的算法_python计算一个序列的平均值的方法
- 计算机比赛小组名称和口号,小组名称口号大全(精选150个)
- three.js纹理贴图不显示
- 华为云服务-申请基础云服务2
- 广电电视信号如何生成RTMP流进入流媒体系统网络分发实现手机APP播放