Ответ 1
Хотя то, что говорит @awoodland, верно, этот метод может вызвать проблемы с изменениями яркости, я считаю.
Системы цвета HSV и HLS являются проблематичными по ряду причин. Я недавно общался с цветным ученым, и его рекомендация заключалась в том, чтобы преобразовать в пространство YIQ или YCbCr и соответствующим образом настроить каналы цветности (I & Q, или Cb & Cr). (Вы можете узнать, как это сделать здесь и здесь. )
В одном из этих пространств вы можете получить оттенок от угла, образованного каналами цветности, выполнив hue = atan(cr/cb)
(наблюдая за cb == 0). Это дает вам ценность в радианах. Просто поверните его, добавив количество вращения оттенка. Как только вы это сделаете, вы можете рассчитать величину цветности с помощью chroma = sqrt(cr*cr+cb*cb)
. Чтобы вернуться в RGB, вычислите новые Cb и Cr (или я и Q) с помощью Cr = chroma * sin (hue)
, Cb = chroma * cos (hue)
. Затем конвертируйте обратно в RGB, как описано на приведенных выше веб-страницах.
EDIT: Здесь решение, которое я тестировал, и, похоже, дает мне те же результаты, что и ваша ссылка. Вероятно, вы можете свернуть некоторые из точечных продуктов на матрицу:
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 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;
}