美文网首页
Unity Shader:白平衡

Unity Shader:白平衡

作者: Dragon_boy | 来源:发表于2020-09-23 10:38 被阅读0次

白平衡(white balance),字面意义上是白色的平衡,由于显示器的三元色红绿蓝混合后是白色,因此白平衡是描述其白色精确度的一个指标,通过它可以解决色彩还原和色调处理的一系列问题。

使用数码摄像机拍照时可能会出现一些问题,如日光灯的房间里拍摄的影像会显得发绿,在室内钨丝灯光下拍摄的影像会偏黄,日光灯阴影处拍摄到的照片则偏蓝,这些都是因为白平衡设置不当。

白平衡修正图像的方法是将白色物体还原为白色,对于偏色情况,加强对应的补色来补偿。

了解白平衡的话还需要了解色温。色温是用开尔文温度来表示色彩。假设一个黑体物质,能够将落在其上的所有热量吸收,没有损失,同时将热量生成的能量以光的形式释放出来,便会因受到热力的高低而变成不同的颜色。如黑体受到的热力相当于500-550℃,就会变成暗红色,达到1050-1150℃时,就会变成黄色,温度继续升高就会变成蓝色。任何光线的色温相当于黑体散发出同样颜色时所受到的温度。色温越高,光色越偏蓝,色温越低则偏红。某一种色光比其它的色光的色温高,说明该色光比其它色光偏蓝,反之偏红。同样,当一种色光比其它色光偏蓝时说明该色光的色温偏高。

由于人眼拥有适应性,所以有时不能发现色温变化,不过在光源改变时会感觉到一会儿,之后就会适应。白平衡就是针对不同的色温条件,抵消偏色,使其更接近人眼的视觉习惯,使白色物体仍是白色。

在Unity中,我们可以看一下shader graph 内置的白平衡节点的实现:

void Unity_WhiteBalance_float(float3 In, float Temperature, float Tint, out float3 Out)
{
    // Range ~[-1.67;1.67] works best
    float t1 = Temperature * 10 / 6;
    float t2 = Tint * 10 / 6;

    // Get the CIE xy chromaticity of the reference white point.
    // Note: 0.31271 = x value on the D65 white point
    float x = 0.31271 - t1 * (t1 < 0 ? 0.1 : 0.05);
    float standardIlluminantY = 2.87 * x - 3 * x * x - 0.27509507;
    float y = standardIlluminantY + t2 * 0.05;

    // Calculate the coefficients in the LMS space.
    float3 w1 = float3(0.949237, 1.03542, 1.08728); // D65 white point

    // CIExyToLMS
    float Y = 1;
    float X = Y * x / y;
    float Z = Y * (1 - x - y) / y;
    float L = 0.7328 * X + 0.4296 * Y - 0.1624 * Z;
    float M = -0.7036 * X + 1.6975 * Y + 0.0061 * Z;
    float S = 0.0030 * X + 0.0136 * Y + 0.9834 * Z;
    float3 w2 = float3(L, M, S);

    float3 balance = float3(w1.x / w2.x, w1.y / w2.y, w1.z / w2.z);

    float3x3 LIN_2_LMS_MAT = {
        3.90405e-1, 5.49941e-1, 8.92632e-3,
        7.08416e-2, 9.63172e-1, 1.35775e-3,
        2.31082e-2, 1.28021e-1, 9.36245e-1
    };

    float3x3 LMS_2_LIN_MAT = {
        2.85847e+0, -1.62879e+0, -2.48910e-2,
        -2.10182e-1,  1.15820e+0,  3.24281e-4,
        -4.18120e-2, -1.18169e-1,  1.06867e+0
    };

    float3 lms = mul(LIN_2_LMS_MAT, In);
    lms *= balance;
    Out = mul(LMS_2_LIN_MAT, lms);
}

函数通过一个色温和偏移值来改变颜色,并输出颜色。

函数第一二行,将色温和偏移映射到[-1.67,1.67],据说这样效果最好。

之后的三行,使获取CIE测量的白平衡点的色度(颜色的色调和饱和度)坐标,何为白点?维基百科上的解释如下:

白点是一系列三色值或色度坐标,它们定义了图像抓取、编码或重生成时的白色。一个发光体的特征是一个光谱功率分布(SPD)。一个发光体的白点是该发光体下白色物体的色度,可以通过色度坐标来表示,如CIE色度图表的xy坐标(使用相对SPD,而不是绝对SPD,因为白点只与颜色相关,与强度无关)。
发光体和白点是独立的概念,对于一个给定的发光体,它的白点是独一无二的,而白点并不对应于某一特定的发光体。从通常使用的CIE 1931色度图表可以得出,几乎所有的非光谱颜色,包括描述为白色的颜色,可以由无限多光谱颜色组合生成,因此会有无限多的不同的发光体光谱。尽管在发光体和白点间的并没有一对一的对应关系,在CIE D系列标准发光体的情况中,光谱功率分布可以从相对应白点的色度坐标来获得。

其中色度坐标的计算由CIE色度图标完成。

之后一行计算LMS空间的系数。LMS是由人眼的三种锥体的响应表示的颜色空间,以其在长波长,中波长和短波长处的响应度(灵敏度)峰命名。在执行色适应时估计样本在不同光源下的外观时,通常使用LMS色彩空间。

之后的7行是将CIE的xy坐标转换到LMS空间。

之后使用计算的因数来计算白平衡系数。

之后的两个矩阵是在线性颜色空间和LMS颜色空间之间的转换。

最后将线性空间颜色转换为LMS空间,然后乘以白平衡系数,之后转换回线性空间然后输出颜色。

相关文章

网友评论

      本文标题:Unity Shader:白平衡

      本文链接:https://www.haomeiwen.com/subject/hasnyktx.html