片段着色器中的平滑渐变

时间:2014-08-12 15:48:17

标签: opengl shader fragment-shader

我正在寻找一些如何使用片段着色器获得平滑渐变的方法。我有11颜色的调色板和用于定义颜色的value(它的范围从0.01.0)。

我正在尝试使用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);
}

但是使用这种方法我只能得到阶梯式的颜色分布。

enter image description here

我理想的结果如下:

enter image description here

我知道如何使用路径着色器将颜色作为属性传递,但这不是那种方式。我将获得如此平滑的分布,并将单个浮点值传递给fragment shader

1 个答案:

答案 0 :(得分:1)

您的混音功能在这里并没有真正有用:

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

问题是,虽然value在[0,1]中,但它不是正确的混合因子。对于您选择的子范围,您需要将其缩放为[0,1]。例如,当值为[0.25,0.35]时,您的代码使用floorIndex=2index=3,因此现在需要一个混合因子,当值为0.25时为0.0,当为0.3时为0.5,且goint接近1.0当它达到0.35时(在3.5时,该轮将切换到下一步,当然)。

所以你需要这样的东西:

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

使用fract()操作可以稍微优化一下。

我想到的另一件事是您可以为调色板使用(1D)纹理并启用GL_LINEAR过滤。在这种情况下,您可以直接使用value作为纹理坐标,并获得所需的结果。这将更加简单,并且可能更高效,因为它将大多数操作移动到专用纹理采样硬件。因此,如果您没有使用纹理的具体原因,我强烈建议您这样做。