Градиент с HSV, а не RGB в OpenGL - PullRequest
2 голосов
/ 05 марта 2012

OpenGL может раскрасить прямоугольник с градиентом цветов от одной стороны к другой.Я использую следующий код для этого в C ++

glBegin(GL_QUADS);
{
    glColor3d(simulationSettings->hotColour.redF(), simulationSettings->hotColour.greenF(), simulationSettings->hotColour.blueF());
    glVertex2d(keyPosX - keyWidth/2, keyPosY + keyHight/2);
    glColor3d(simulationSettings->coldColour.redF(), simulationSettings->coldColour.greenF(), simulationSettings->coldColour.blueF());
    glVertex2d(keyPosX - keyWidth/2, keyPosY - keyHight/2);
    glColor3d(simulationSettings->coldColour.redF(), simulationSettings->coldColour.greenF(), simulationSettings->coldColour.blueF());
    glVertex2d(keyPosX + keyWidth/2, keyPosY - keyHight/2);
    glColor3d(simulationSettings->hotColour.redF(), simulationSettings->hotColour.greenF(), simulationSettings->hotColour.blueF());
    glVertex2d(keyPosX + keyWidth/2, keyPosY + keyHight/2);
}

Я использую некоторые библиотеки Qt для преобразования между HSV и RGB.Как видно из кода, я рисую прямоугольник с цветовым градиентом от того, что я называю hotColour к coldColour.

Почему я это делаю?Созданная мной программа рисует трехмерные векторы в пространстве и указывает их длину по цвету.Пользователю предлагается выбрать горячий (высокое значение) и холодный (низкое значение) цвета, и программа автоматически выполнит градиент, используя масштабирование HSV.

Почему масштабирование HSV?потому что HSV однозначен по всей используемой мной цветовой карте, и линейное создание градиентов с ним - очень простая задача.Чтобы пользователь мог выбрать цвета, я предлагаю ему цветовую карту QColourDialog

http://qt -project.org / doc / qt-4.8 / qcolordialog.html

На этой цветовой карте вы можете видеть, что красный доступен с правой и левой стороны, что делает невозможным линейный масштаб для этой цветовой карты с RGB.Но с HSV, линейная шкала очень легко достижима, где я просто должен использовать линейную шкалу между 0 и 360 для значений оттенка.

С этой парадигмой мы видим, что горячие и холодные цвета определяют направлениедля градиента, например, если я выберу оттенок 0 для холодного и 359 для горячего, HSV даст мне градиент от 0 до 359 и включит весь спектр цветов в градиент;в то время как в OpenGL он будет в основном переходить с красного на красный, что не является градиентом !!!!!!

Как я могу заставить OpenGL использовать градиент HSV, а не RGB?Единственная идея, которая приходит мне в голову, - это нарезать прямоугольник, который я хочу раскрасить, и сделать много градиентов по меньшим прямоугольникам, но я думаю, что это не самый эффективный способ сделать это.

Есть идеи?

Ответы [ 2 ]

7 голосов
/ 05 марта 2012

Как я могу заставить OpenGL использовать градиент HSV, а не RGB?

Я бы не назвал это "принуждением", но "обучением".Способ OpenGL по умолчанию для интерполяции векторов атрибутов вершин заключается в барицентрической интерполяции отдельных векторных элементов на основе координат NDC фрагмента.

Вы должны указать OpenGL, как преобразовать эти барицентрические интерполированные значения HSV в RGB.1007 *

Для этого мы вводим фрагментный шейдер, который принимает атрибут цветовой вершины не RGB, а HSV.

#version 120
varying vec3 vertex_hsv; /* set this in appropriate vertex shader to the vertex attribute data*/

vec3 hsv2rgb(vec3 hsv)
{
    float h = hsv.x * 6.; /* H in 0°=0 ... 1=360° */
    float s = hsv.y;
    float v = hsv.z;
    float c = v * s;

    vec2 cx = vec2(v*s, c * ( 1 - abs(mod(h, 2.)-1.) ));

    vec3 rgb = vec3(0., 0., 0.);
    if( h < 1. ) {
        rgb.rg = cx;
    } else if( h < 2. ) {
        rgb.gr = cx;
    } else if( h < 3. ) {
        rgb.gb = cx;
    } else if( h < 4. ) {
        rgb.bg = cx;
    } else if( h < 5. ) {
        rgb.br = cx;
    } else {
        rgb.rb = cx;
    }
    return rgb + vec3(v-cx.y);
}

void main()
{
    gl_FragColor = hsv2rgb(vertex_hsv);
}
3 голосов
/ 05 марта 2012

Вы можете сделать это с помощью фрагментного шейдера. Вы рисуете квад и применяете свой фрагментный шейдер, который делает желаемую раскраску для квадратора. Я бы сделал так, чтобы установить цвета углов на нужные значения HSV, а затем в фрагментном шейдере преобразовать интерполированные значения цвета из HSV обратно в RGB. Для получения дополнительной информации о фрагментных шейдерах см. docs .

...