Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Opengl 如何使用GLSL更改纹理的色调?_Opengl_Filter_Glsl_Hsv_Hue - Fatal编程技术网

Opengl 如何使用GLSL更改纹理的色调?

Opengl 如何使用GLSL更改纹理的色调?,opengl,filter,glsl,hsv,hue,Opengl,Filter,Glsl,Hsv,Hue,有没有一种方法可以使用GLSL(片段着色器)有效地更改2D OpenGL纹理的色调 有人有代码吗 更新:这是用户1118321建议产生的代码: uniform sampler2DRect texture; const mat3 rgb2yiq = mat3(0.299, 0.587, 0.114, 0.595716, -0.274453, -0.321263, 0.211456, -0.522591, 0.311135); const mat3 yiq2rgb = mat3(1.0, 0.956

有没有一种方法可以使用GLSL(片段着色器)有效地更改2D OpenGL纹理的色调

有人有代码吗

更新:这是用户1118321建议产生的代码:

uniform sampler2DRect texture;
const mat3 rgb2yiq = mat3(0.299, 0.587, 0.114, 0.595716, -0.274453, -0.321263, 0.211456, -0.522591, 0.311135);
const mat3 yiq2rgb = mat3(1.0, 0.9563, 0.6210, 1.0, -0.2721, -0.6474, 1.0, -1.1070, 1.7046);
uniform float hue;

void main() {

vec3 yColor = rgb2yiq * texture2DRect(texture, gl_TexCoord[0].st).rgb; 

float originalHue = atan(yColor.b, yColor.g);
float finalHue = originalHue + hue;

float chroma = sqrt(yColor.b*yColor.b+yColor.g*yColor.g);

vec3 yFinalColor = vec3(yColor.r, chroma * cos(finalHue), chroma * sin(finalHue));
gl_FragColor    = vec4(yiq2rgb*yFinalColor, 1.0);
}
这是与参考文献比较的结果:

我曾尝试在atan内用Q切换I,但结果是错误的,即使在0°左右

你有什么提示吗

如果需要进行比较,这是原始的未修改图像:
虽然@awoodland所说的是正确的,但我相信这种方法可能会导致亮度变化的问题

HSV和HLS颜色系统有很多问题。我最近和一位色彩学家谈过这个问题,他的建议是转换到YIQ或YCbCr空间,并相应地调整色度通道(I&Q或Cb&Cr)。(您可以学习如何做到这一点和。)

一旦进入其中一个空间,通过执行
hue=atan(cr/cb)
(注意cb==0),就可以从色度通道形成的角度获得色调。这将为您提供弧度值。只需通过添加色调旋转量来旋转它。完成后,可以使用
chroma=sqrt(cr*cr+cb*cb)
计算色度的大小。要返回RGB,请使用
Cr=chroma*sin(色调)
Cb=chroma*cos(色调)
计算新的Cb和Cr(或I&Q)。然后按照上述网页上的说明转换回RGB

编辑:这是一个我已经测试过的解决方案,它似乎给了我与您的参考相同的结果。您可能会将一些点积折叠为矩阵乘法:

uniform sampler2DRect inputTexture;
uniform float   hueAdjust;
void main ()
{
    const vec4  kRGBToYPrime = vec4 (0.299, 0.587, 0.114, 0.0);
    const vec4  kRGBToI     = vec4 (0.596, -0.275, -0.321, 0.0);
    const vec4  kRGBToQ     = vec4 (0.212, -0.523, 0.311, 0.0);

    const vec4  kYIQToR   = vec4 (1.0, 0.956, 0.621, 0.0);
    const vec4  kYIQToG   = vec4 (1.0, -0.272, -0.647, 0.0);
    const vec4  kYIQToB   = vec4 (1.0, -1.107, 1.704, 0.0);

    // Sample the input pixel
    vec4    color   = texture2DRect (inputTexture, gl_TexCoord [ 0 ].xy);

    // Convert to YIQ
    float   YPrime  = dot (color, kRGBToYPrime);
    float   I      = dot (color, kRGBToI);
    float   Q      = dot (color, kRGBToQ);

    // Calculate the hue and chroma
    float   hue     = atan (Q, I);
    float   chroma  = sqrt (I * I + Q * Q);

    // Make the user's adjustments
    hue += hueAdjust;

    // Convert back to YIQ
    Q = chroma * sin (hue);
    I = chroma * cos (hue);

    // Convert back to RGB
    vec4    yIQ   = vec4 (YPrime, I, Q, 0.0);
    color.r = dot (yIQ, kYIQToR);
    color.g = dot (yIQ, kYIQToG);
    color.b = dot (yIQ, kYIQToB);

    // Save the result
    gl_FragColor    = color;
}

Andrea3000,在比较YIQ在网上的例子时,我看到了你的帖子,但我认为你的代码的“更新”版本有问题。。。。我确信您的“mat3”定义在列/行顺序上是颠倒的。。。(也许这就是你仍然有麻烦的原因)

仅供参考:OpenGL矩阵排序:“有关更多值,矩阵按列主顺序填充。即,第一个X值为第一列,第二个X值为下一列,依此类推。”请参阅:


这是RGB三元组围绕(1,1,1)向量的旋转-你可以表示为着色器中的矩阵乘法如果你的色调偏移是恒定的,那么你可以跳过atan、sqrt、sin和cos。你要做的是把它们转换成极坐标,增加角度,然后再转换回来。可以使用2x2旋转矩阵进行此计算。如果不需要在yiq空间中进行任何其他数学运算,则可以预先计算整个变换。将rgb2yiq与2d旋转(填充为3x3)相乘,然后与yiq2rgb相乘,得到一个完成整个过程的大3x3矩阵。就像@Flexo所说的,这只是围绕(1,1,1)向量的旋转。谢谢,我刚刚实现了它,但它似乎不能正常工作。。它实际上会改变色调,但与Photoshop的色调调整(例如)完全不同。我决定将其转换为YIQ,因为有了YCbCr,我的成绩甚至最差。因此,我计算了
hue=atan2(Q,I)
chroma=sqrt(I*I+Q*Q)
,然后
I=chroma*sin(hue)
Q=chorma*cos(hue)
。对吗?我遗漏了什么吗?我觉得这是对的。你得到了什么结果?(是色调不对,还是亮度和饱和度也被弄乱了?)如果在
atan2()
调用中反转I和Q,结果是否更像您所期望的?也许如果你发布了一些代码,我们可以为你再次检查。谢谢你的关注,我已经用代码和结果快照更新了问题。在我看来,也许你需要反转你传递的色调角度作为开始。那至少会让你更亲近。因为某种原因,你的饱和度似乎在增加。此外,您可能无法获得与Photoshop完全相同的结果,因为它们可能在与您不同的颜色空间中工作。@user1118321我尝试将纯R(1,0,0)、G(0,1,0)、B(0,0,1)转换为YCrCb,然后计算饱和度。然而,在这两种情况下,饱和度都不是1,事实上,每种原色的饱和度完全不同。我错过了什么?
mat2(
float, float,   //first column
float, float);  //second column