How to change hue of a texture with GLSL?

后端 未结 2 835
梦毁少年i
梦毁少年i 2020-12-04 15:09

Is there a way to efficiently change hue of a 2D OpenGL texture using GLSL (fragment shader)?

Do someone have some code for it?

UPDATE: This

相关标签:
2条回答
  • 2020-12-04 15:24

    Andrea3000, in comparing YIQ examples on the net, i came across your posting, but i think there is an issue with the 'updated' version of your code.... i'm sure your 'mat3' definitions are flip/flopped on the column/row ordering... (maybe that's why you were still having troubles)...

    FYI: OpenGL matrix ordering: "For more values, matrices are filled in in column-major order. That is, the first X values are the first column, the second X values are the next column, and so forth." See: http://www.opengl.org/wiki/GLSL_Types

    mat2(
    float, float,   //first column
    float, float);  //second column
    
    0 讨论(0)
  • 2020-12-04 15:26

    While what @awoodland says is correct, that method may cause issues with changes in luminance, I believe.

    HSV and HLS color systems are problematic for a number of reasons. I talked with a color scientist about this recently, and his recommendation was to convert to YIQ or YCbCr space and adjust the the chroma channels (I&Q, or Cb&Cr) accordingly. (You can learn how to do that here and here.)

    Once in one of those spaces, you can get the hue from the angle formed by the chroma channels, by doing hue = atan(cr/cb) (watching for cb == 0). This gives you a value in radians. Simply rotate it by adding the hue rotation amount. Once you've done that, you can calculate the magnitude of the chroma with chroma = sqrt(cr*cr+cb*cb). To get back to RGB, calculate the new Cb and Cr (or I & Q) using Cr = chroma * sin (hue), Cb = chroma * cos (hue). Then convert back to RGB as described on the above web pages.

    EDIT: Here's a solution that I've tested and seems to give me the same results as your reference. You can probably collapse some of the dot products into matrix multiplies:

    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;
    }
    
    0 讨论(0)
提交回复
热议问题