Question

OpenGL can colour a rectangle with a gradient of colours from 1 side to the other. I'm using the following code for that in 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);
}

I'm using some Qt libraries to do the conversions between HSV and RGB. As you can see from the code, I'm drawing a rectangle with colour gradient from what I call hotColour to coldColour.

Why am I doing this? The program I made draws 3D Vectors in space and indicates their length by their colour. The user is offered to choose the hot (high value) and cold (low value) colours, and the program will automatically do the gradient using HSV scaling.

Why HSV scaling? because HSV is single valued along the colour map I'm using, and creating gradients with it linearly is a very easy task. For the user to select the colours, I offer him a QColourDialog colour map

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

On this colour map, you can see that red is available on the right and left side, making it impossible to have a linear scale for this colour-map with RGB. But with HSV, the linear scale is very easily achievable, where I just have to use a linear scale between 0 and 360 for Hue values.

With this paradigm, we can see that hot and cold colours define the direction of the gradient, so for example, if I choose hue to be 0 for cold and 359 for hot, HSV will give me a gradient between 0 and 359, and will include the whole spectrum of colours in the gradient; whilst, in OpenGL, it will basically go from red to red, which is no gradient!!!!!!

How can I force OpenGL to use an HSV gradient rather than RGB? The only idea that occurs to me is slicing the rectangle I wanna colour and do many gradients over smaller rectangles, but I think this isn't the most efficient way to do it.

Any ideas?

Was it helpful?

Solution

How can I force OpenGL to use an HSV gradient rather than RGB?

I wouldn't call it "forcing", but "teaching". The default way of OpenGL to interpolate vertex attributes vectors is by barycentric interpolation of the single vector elements based on the NDC coordinates of the fragment.

You must tell OpenGL how to turn those barycentric interpolated HSV values into RGB.

For this we introduce a fragment shader that assumes the color vertex attribute not being RGB but 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);
}

OTHER TIPS

You can do this with a fragment shader. You draw a quad and apply your fragment shader which does the coloring you want to the quad. The way I would do this is to set the colors of the corners to the HSV values that you want, then in the fragment shader convert the interpolated color values from HSV back to RGB. For more information on fragment shaders see the docs.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top