在OpenGL中使用HSV而不是RGB的梯度

时间:2012-03-05 15:17:55

标签: opengl colors gradient hsv

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。

为什么我这样做?我制作的程序在空间中绘制3D矢量,并用颜色表示它们的长度。用户可以选择热(高值)和冷(低值)颜色,程序将使用HSV缩放自动执行渐变。

为什么HSV缩放?因为HSV沿我正在使用的颜色图是单值的,并且线性地创建渐变是一项非常容易的任务。为了让用户选择颜色,我给他提供了一个QColourDialog颜色图

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

在此颜色地图上,您可以看到左侧和右侧都有红色,因此无法使用RGB的此颜色映射具有线性比例。但是对于HSV,线性刻度非常容易实现,我只需要在0到360之间使用线性刻度来表示Hue值。

通过这个范例,我们可以看到冷热颜色定义了渐变的方向,例如,如果我选择hue为0表示冷,359表示热,HSV将给出0到359之间的渐变,并将包括渐变中的整个色彩范围;而在OpenGL中,它基本上会从红色变为红色,这是没有渐变!!!!!!

如何强制OpenGL使用HSV渐变而不是RGB?对我来说,唯一的想法是切割矩形我想要着色并在较小的矩形上做很多渐变,但我认为这不是最有效的方法。

有什么想法吗?

2 个答案:

答案 0 :(得分:7)

  

如何强制OpenGL使用HSV渐变而不是RGB?

我不会称之为“强迫”,而是“教导”。 OpenGL插入顶点属性向量的默认方式是基于片段的NDC坐标对单个向量元素进行重心插值。

您必须告诉OpenGL如何将这些重心插值的HSV值转换为RGB。

为此,我们引入了一个片段着色器,它假定颜色顶点属性不是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);
}

答案 1 :(得分:3)

您可以使用片段着色器执行此操作。您绘制四边形并应用片段着色器,它将您想要的颜色添加到四边形。我这样做的方法是将角的颜色设置为您想要的HSV值,然后在片段着色器中将内插颜色值从HSV转换回RGB。有关片段着色器的更多信息,请参阅docs