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ą:
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:
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;
}
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
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