在OpenGL中使用HSV而不是RGB进行渐变

在OpenGL中使用HSV而不是RGB进行渐变,opengl,colors,gradient,hsv,Opengl,Colors,Gradient,Hsv,OpenGL可以使用从一侧到另一侧的渐变颜色为矩形着色。我在C中使用了以下代码++ glBegin(GL_QUADS); { glColor3d(simulationSettings->hotColour.redF(), simulationSettings->hotColour.greenF(), simulationSettings->hotColour.blueF()); glVertex2d(keyPosX - keyWidth/2, keyPosY +

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颜色图

在这张彩色地图上,你可以看到红色在右边和左边都有,这使得这张带有RGB的彩色地图不可能有一个线性比例。但是对于HSV,线性比例非常容易实现,我只需要使用0到360之间的线性比例作为色调值

在这个范例中,我们可以看到热和冷颜色定义了渐变的方向,因此,例如,如果我选择色调为0表示冷,359表示热,HSV将给我一个介于0和359之间的渐变,并将包括渐变中的整个颜色光谱;然而,在OpenGL中,它基本上会从红色变为红色,这是没有梯度的

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


有什么想法吗?

您可以使用片段着色器来实现这一点。绘制一个四边形并应用片段着色器,该着色器对四边形进行所需的着色。我这样做的方法是将角点的颜色设置为所需的HSV值,然后在片段着色器中将插值颜色值从HSV转换回RGB。有关片段着色器的详细信息,请参见

如何强制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);
}

在你的第一次计算中,6从哪里来。;这意味着什么?还有,在vec2-cx=vec2v*s,c*1-absmodh,2.-1行中定义的c在哪里@托布森:我忘了在编辑中正确替换“c”。关于系数6:HSL中的色调以角度给出,上面的代码假设在0…1中对值范围h进行完整的颜色循环,对应于0°…360°或0到2pi中的h。因此,我们在颜色循环中有6个扇区,我们通过将h值范围放大6并在cx计算中取模2来提取扇区,然后一系列if语句在h圆周上的原色之间进行插值。