frankie
frankie

Reputation: 728

Smooth gradient in fragment shader

I am looking for some way how to get smooth gradient with fragment shader. I have palette with 11 colors and value which used to define color (it lays in range from 0.0 to 1.0).

I am trying to get smooth color translation with such fragment shader:

#version 150 core

in float value;    
uniform vec3 colors[11];

out vec4 out_Color;

void main(void) 
{
    int index = int(round(value * 10));

    int floorIndex = 0; 

    if (index != 0) floorIndex = index - 1;

    out_Color = vec4(mix(colors[floorIndex], colors[index], value), 1.0f);
}

But using such approach I could get only stepped colors distribution.

enter image description here

And my desirable result looks like:

enter image description here

I know how to get this with path-through shader just passing color as attribute, but this is not that way. I am going to get such smooth distribution with single float value passed to fragment shader.

Upvotes: 0

Views: 3595

Answers (1)

derhass
derhass

Reputation: 45322

Your mixing function is not really usefully applied here:

mix(colors[floorIndex], colors[index], value)

The problem is that, while value is in [0,1], it is not the proper mixing factor. You need it to be scaled to [0,1] for the sub-range you have selected. E.g, your code uses floorIndex=2 and index=3 when value is in [0.25, 0.35), so now you need a mix factor wich is 0.0 when value is 0.25, 0.5 when it is 0.3 and goint near 1.0 when it reaches 0.35 (at 3.5 the round will switch to the next step, of course).

So you will need something like:

float blend=(value * 10.0) - float(floorIndex) - 0.5;
mix(colors[floorIndex], colors[index], blend)

That can probably be optimized a bit by using the fract() operation.

Another thing which comes to mind is that you could use a (1D) texture for your palette and enable GL_LINEAR filtering. In that case, you can directly use value as texture coordinate and will get the result you need. This will be much simpler, and likely also more efficient as it moves most of the operations to the specialised texture sampling hardware. So if you don't have a specific reason for not using a texture, I strongly recommend doing that.

Upvotes: 1

Related Questions