Jak zmienić odcień tekstury za pomocą GLSL?

Czy istnieje sposób na efektywną zmianę odcienia tekstury OpenGL 2D przy użyciu GLSL (fragment shader)?

Czy ktoś ma jakiś kod do tego?

UPDATE: jest to kod wynikający z sugestii user1118321:

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);
}

I jest to wynik porównywany z referencją:

Tutaj wpisz opis obrazka

Próbowałem przełączyć I z Q wewnątrz Atana ale wynik jest błędny nawet w okolicach 0°

Masz jakąś wskazówkę?

Jeśli jest to konieczne dla porównania, jest to oryginalny niezmodyfikowany obraz: Tutaj wpisz opis obrazka

Author: Andrea3000, 2012-02-11

2 answers

Chociaż to, co mówi @ awoodland, jest poprawne, ta metoda może powodować problemy ze zmianami luminancji, jak sądzę.

Systemy kolorów HSV i HLS są problematyczne z wielu powodów. Niedawno rozmawiałem o tym z kolorowym naukowcem i jego rekomendacją była konwersja do przestrzeni YIQ lub YCBCR i odpowiednie dostosowanie kanałów chroma (i&Q, lub CB&Cr). (Możesz dowiedzieć się, jak to zrobić tutaj i tutaj .)

Raz w jednym z tych miejsc, można uzyskać odcień z kąta utworzonego przez kanały chroma, wykonując hue = atan(cr/cb) (obserwując dla cb = = 0). Daje to wartość w radianach. Po prostu obróć go, dodając ilość obrotu odcienia. Gdy już to zrobisz, możesz obliczyć wielkość chroma za pomocą chroma = sqrt(cr*cr+cb*cb). Aby wrócić do RGB, Oblicz nowe Cb I Cr (lub I & Q) za pomocą Cr = chroma * sin (hue), Cb = chroma * cos (hue). Następnie Konwertuj z powrotem do RGB zgodnie z opisem na powyższych stronach internetowych.

EDIT: oto rozwiązanie, które przetestowałem i wydaje mi się, że daje mi te same wyniki, co twój Referencja. Prawdopodobnie można zwinąć niektóre z produktów dot w mnożenie macierzy:

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;
}
 26
Author: user1118321,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-13 02:07:44

Andrea3000, porównując przykłady YIQ w sieci, natknąłem się na twój post, ale myślę, że jest problem z "zaktualizowaną" wersją Twojego kodu.... jestem pewien, że Twoje definicje "mat3" są odwracane/wyrzucane w kolejności kolumn / wierszy... (może dlatego nadal miałeś problemy)...

FYI: OpenGL matrix ordering: "aby uzyskać więcej wartości, macierze są wypełniane w kolejności kolumn-głównych. Oznacza to, że pierwsze wartości X są pierwszą kolumną, drugie wartości X są następną kolumną, a więc naprzód."Zobacz: http://www.opengl.org/wiki/GLSL_Types

mat2(
float, float,   //first column
float, float);  //second column
 3
Author: Joe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-06 16:27:22