9

我无法完全理解伽玛校正的必要性。我希望你们能帮助我。

假设我们要显示 256 个相邻像素。这些像素应该是从黑色到白色的平滑渐变。为了表示它们的颜色,我们使用线性灰度值,0..255.由于人眼的非线性,显示器不能仅仅将这些值转换为线性亮度值。如果相邻像素具有亮度值(1/256)*I_max, (2/256)*I_max, et cetera,我们会在较暗的区域感觉到两个像素之间的亮度差异过大(渐变将不平滑)。

幸运的是,监视器对人眼具有互为非线性。这意味着,如果我们将线性灰度值0..255放入帧缓冲区,那么监视器会将它们转换为非线性亮度值 x^gamma。然而,由于我们的眼睛反过来是非线性的,我们会感知到平滑的线性渐变。显示器的非线性和我们的一只眼睛相互抵消。

那么,为什么我们需要伽玛校正呢?我在书中读到我们总是希望显示器产生线性亮度值。根据他们的说法,在将灰度值写入帧缓冲区之前,必须补偿监视器的非线性。这是通过伽马校正完成的。然而,我的问题是——据我所知——当显示器产生线性亮度值时,我们不会感知到线性亮度值(即我们不会感知到平滑、稳定的渐变)。

在我看来,如果我们将线性灰度值放入帧缓冲区,那将是完美的。监视器将这些值转换为非线性亮度值,我们的眼睛再次感知线性亮度值,因为眼睛是互易非线性的。无需对帧缓冲区中的灰度值进行伽玛校正,也无需强制监视器产生线性亮度值。

我看待这些事情的方式有什么问题?谢谢

4

3 回答 3

6

Allow me to ‘resurrect’ this question since I am struggling with similar questions right now and I think I have found the answer -it may be useful for someone else. Or I might be wrong and someone could tell me :)

I think there is nothing wrong with your way of thinking. Thing is, you don‘t need to gamma-correct all the time, if you know what you are doing. It depends on what you want to achieve. Let‘s see two different cases.

A) Light simulation (AKA rendering). You have a diffuse surface with a light pointing towards it. Then, the light's intensity is doubled.

Well. Let’s see what happens in the real world in such situation. Assuming a purely diffuse surface, the intensity of the light reflected is going to be the surface's albedo multiplied by the incoming light intensity and the cosine of the incoming light angle and the normal. Whatever. Thing is, when the incoming light intensity is doubled, the reflected light intensity will be doubled too. This is why light transport is said to be a linear process. Funny enough, you will not perceive the surface as twice as bright, because our perception is nonlinear (This is modelled by the so-called Steven's power law). Put again: in the real world the reflected light is doubled, but you do not perceive it twice as bright.

Now, how would we simulate this? Well, if we have a sRGB texture with the surface's albedo, we would need to linearlize it (by de-correcting it, which means applying the 2.2 gamma). Now that it is linear, and we have the light intensity, we can use the formula I said before to compute the reflected light intensity. Since we are in a linear space, by doubling the intensity we will double the output, like in the real world. Now we gamma-correct our results. Because of this, when the screen displays the rendered image, it will apply the gamma and so it will have a linear response, meaning that the intensity of the light emited by the screen will be twice as much when we simulate the twice-as-poweful light than when we simulate the first one. So the light that arrive at your eyes from your screen will have double the intensity. Exactly as it would happen if you were looking at the real surface with real lights affecting it. You will not perceive the second render twice as bright, of course but, again, and as we said earlier, this is exactly what it would happen in the real situation. Same behavior in the real world and in the simulation means that the simulation (the render) was correct :)

B) A different case is precisely if you want a gradient that you want to 'look' (AKA being perceived) as linear.

Since you want the nonlinear response of the screen to cancel out our nonlinear visual perception, you can skip gamma correction altogether (as you suggest). Or, more accurately, keep operating in linear space and gamma-correcting, but creating your gradient not with consecutive values for the pixels(1,2,3...255) that would be perceived nonlinearly (because of Steven's), but values transformed by the inverse of our perceptual brightness response (that is, applying an exponent of 1/0.5=2 to the normalized values. This is applying the reciprocal of Steven's exponent for brightness).

As a matter of fact, if you see gamma-corrected linear gradient such as the one in http://scanline.ca/gradients/ you do not perceive it as linear at all: you see far more variation in the lower intensities than in the higher ones (as expected).

Well, at least this is my current understanding of the topic. I hope it helps anyone. And again, please, please, if it is wrong I would be really grateful if someone could point it out...

于 2013-09-26T02:22:22.237 回答
3

问题实际上是在进行颜色计算时。例如,如果要混合两种颜色,则需要使用线性强度进行计算。为了实际显示正确的结果,您必须将线性强度转换回伽马校正强度。

您的眼睛如何感知强度无关紧要。要正确进行颜色计算,必须根据光学的物理原理来完成,这依赖于线性亮度值。一旦您计算了颜色,您希望显示器输出这些亮度值,而不管它是如何被感知的,因此您必须补偿显示器不直接产生您想要的颜色的事实。

于 2012-10-19T14:02:02.997 回答
0

要真正回答你看待这个问题的方式有问题的问题——这并没有什么问题。拥有一个线性帧缓冲区会很棒,但正如您所说,拥有一个 8 位线性帧缓冲区肯定不是很好。

8 位是如此容易处理的事实几乎是伽玛压缩帧缓冲区和颜色符号的唯一理由(想想 HTML 的 #888 - 将 #333 用于中间灰色而不是 #888 会不会很酷)。

关于显示器 - 您希望能够预测它对您的输入的响应,并且您可以从 sRGB 中知道它应该是什么。通常这就是您需要知道的全部内容。如果监视器产生“线性”输出,如果您补偿监视器的伽马可以模拟,有些人认为这是“正确的”或其他东西。我建议避开这样的设置,它会破坏所有(正确且合理地)假设标准 gamma 的应用程序,而支持不间断的、考虑不周的线性假设应用程序。不要那样做。相反,修复应用程序或转储它们。

于 2012-10-22T16:17:00.347 回答