我正在渲染绿色文字,其中一些是模糊的,带有一个坚实的蓝色背景。透明度功能按预期工作,但我得到了一个黑暗的光环"在文本的模糊区域。我花了几天时间阅读文章并尝试不同的解决方案,但无济于事。
前景图像用纯绿色(0,0,1)填充,alpha通道用于定义文本和透明度。
访问网站http://www.andersriggelsen.dk/glblendfunc.php并输入以下两个图片网址
,可以轻松证明我的问题前景:http://troikatronix.com/files/text320x240.png
背景:http://troikatronix.com/files/solid-blue.png
此图显示了设置和带有暗晕的结果图像。
为了试图深入研究,我编写了一个调试函数,用于在渲染每个图层后回读后缓冲区。在数字上,数学都是正确的。
例如,如果我以10%的比例渲染预乘的源图像的实体部分(例如,在使用10%的预乘之前,源是rgba [0,0,255,255])并使用glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA)它就像这样
bkg = rgba[0, 0, 255, 255]
src = rgba[0, 25, 0, 25]
result = rgba[0, 25, 230, 255]
但是当你看到它时,你基本上会看到一个黑色的蓝色,看不到绿色,正如这个图像所示
那么我做错了什么?或者这是某种伽玛/色彩匹配问题,其中绿色的增加不像蓝色的减少那么明显?
答案 0 :(得分:3)
这是一个简单的感知问题,它与伽玛有关。
从此裁剪输出开始:
如果你拆分频道,你会得到(红色,绿色,蓝色):
监视器,包括您几乎肯定会看到的sRGB LCD监视器,对像素值进行伽玛缩放 note 1 。
以下是sRGB伽马函数 注2 的近似图:
当我们查看蓝色背景(值0,0,255
=> 0,0,1
)时,我们会得到0,0,1
的输出。同样地,当我们看到字母内部的完全绿色时,我们得到明显的亮度0,1,0
注3 。
现在想想边缘点上会发生什么。假设它基本上位于中间0,127,128
〜=> 0.0,0.5,0.5
。使用图表,我们得到了0.00,0.218,0.218
的输出表观强度。我们对像素亮度的感知在各个通道上是相加的,因此我们得到的整体亮度为0.436
。
这明显比字母的内部或外部更暗 - 你觉得它是一个黑暗的乐队!
注1 为什么?它具有从例如改变它的效果。 200
至201
实际亮度大于5
。 6
到2.4
。我们这样做是因为人类对比度感知基本上是百分比差异的函数。 为了保持明显均匀的对比度,亮度必须是非线性的。
note 2 现实情况有点不同,但这基本上是正确的。具体来说,指数实际上是0.0
,并且由于数值原因它变为线性接近{{1}}。有时会有进一步的修正使C1连续。
note 3 不同的颜色通道也会缩放,以提供相似的视在亮度。