OpenGL GLSL:如何使用片段着色器在 photoshop 中实现渐变贴图的概念?

OpenGL GLSL: How to implement the concept of gradient map in photoshop using fragment shader?

这可能不是 Whosebug 的完美问题,但我已经在 stackexchange 的图形设计网络中问过这个问题,但没有得到任何答案,因此将其张贴在这里。 我正在尝试使用 glsl 片段着色器以编程方式实现 Photoshop 的渐变贴图。考虑下面显示的渐变图,其中所有白色组件都被绿色替换,黑色被蓝色替换。对于其他颜色分量,Photoshop 会根据蓝色和绿色之间的线性渐变进行计算。我知道这个计算背后有一个数学。有谁知道为特定输入颜色值查找输出颜色的公式吗?

根据图像和描述,它看起来像是将图像的原始灰度值映射到蓝绿色渐变。

有多种方法可以将颜色转换为灰度,具体取决于所使用的颜色系统。许多简单的只是RGB分量的加权和。例如,一个广泛使用的将 RGB 转换为亮度 (Y) 的公式是:

Y = 0.299 * R + 0.587 * G + 0.114 * B

有关该主题和所有不同选项的更多背景信息,请参阅 Grayscale wikipedia page

然后可以用灰度值作为参数,对蓝色和绿色进行线性插值。无论如何,这方面的数学很容易,但 GLSL 甚至有一个用于此目的的内置 mix() 函数。

GLSL 的一些可能代码片段,基于使用纹理坐标 TexCoord:

从纹理 Tex 读取原始颜色
uniform sampler2D Tex;
in vec2 TexCoord;
out vec4 FragColor;
...
    vec4 origColor = texture(Tex, TexCoord);
    float grayscaleValue = dot(origColor.rgb, vec3(0.299, 0.587, 0.114));
    FragColor = mix(vec4(0.0, 0.0, 1.0, 1.0), vec4(0.0, 1.0, 0.0, 1.0), grayscaleValue);

在此代码中,vec3(0.299, 0.587, 0.114) 包含上述 RGB 到灰度(亮度)公式的系数。 mix()函数的前两个参数是渐变的开始和结束颜色:

  • 蓝色:vec4(0.0, 0.0, 1.0, 1.0)
  • 绿色:vec4(0.0, 1.0, 0.0, 1.0)

请注意,RGB space 中两种颜色之间的简单线性插值并不理想,尤其是当颜色差异很大时。您可以通过使用不同的颜色 space(例如 HLS)来使它更精细,并可能获得更好的质量。

另一个可能改善视觉外观的选项是使用两种以上的颜色来指定渐变。例如,您可以将蓝色指定为亮度 0.0,将青色指定为亮度 0.5,将绿色指定为亮度 1.0。它比上面的 GLSL 代码需要更多的逻辑,但它只是相同原理的扩展。

我在 Photoshop 中尝试了不同的渐变贴图,我的设置接缝与 OP 中的不同。在我的例子中,将渐变图滤镜应用于从黑到白的渐变图像表明黑色仍然是黑色,而白色仍然是白色。中间的每个灰色阴影都被绿色和蓝色之间的某种颜色所取代。如果将灰色阴影直接映射到线性渐变,黑色和白色将消失。 Photoshop 渐变贴图接缝保留原始颜色的发光。

这是我为我的设置匹配 Photoshop 渐变贴图的公式。

给定 (Rg1,Gg1,Bg1)(Rg2,Gg2,Bg2) 渐变值,(Ro,Go,Bo) 原始颜色值和 (Rr,Gr,Br) 生成的颜色。

  1. 获取HSL中要转换的颜色space:

(Ho, So, Lo) = rgb2hsl(Ro, Go, Bo)

  1. 计算 Lo 值的梯度(RGB)的线性插值:

(Rt,Gt,Bt) = (Rg1+[Rg2-Rg1]*Lo, Gg1+[Gg2-Gg1]*Lo), Bg1+[Bg2-Bg1]*Lo)

  1. 在 HSL 中获取此值 space :

(Ht,St,Lt) = rgb2hsl(Rt, Gt, Bt)

  1. 保留原始颜色的L值

(Rr,Gr,Br) = hsl2rgb(Ht,St,Lo)

rgb2hsl 和 hsl2rgb 代码示例可在此处找到:HSL to RGB color conversion