简体   繁体   English

片段着色器中的平滑渐变

[英]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 ). 我有11种颜色的调色板和用于定义颜色的value (范围从0.01.0 )。

I am trying to get smooth color translation with such fragment shader : 我正在尝试使用这样的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. 但是使用这种方法,我只能得到逐步的颜色分布。

在此处输入图片说明

And my desirable result looks like: 我期望的结果如下所示:

在此处输入图片说明

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 . 通过将单个float值传递到fragment shader我将获得如此平滑的分布。

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. 问题在于,尽管value在[0,1]中,但它不是适当的混合因子。 You need it to be scaled to [0,1] for the sub-range you have selected. 对于选定的子范围,需要将其缩放为[0,1]。 Eg, 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). 例如,当值在[ floorIndex=2 ,您的代码使用floorIndex=2index=3 ,因此现在您需要一个混合因子,当值是0.25时为0.0,当值为0.3时为0.5,当达到0.35时接近1.0 (当然,在3.5时,回合将切换到下一步)。

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. 通过使用fract()操作,可以对此进行一点优化。

Another thing which comes to mind is that you could use a (1D) texture for your palette and enable GL_LINEAR filtering. 想到的另一件事是,您可以为调色板使用(1D)纹理并启用GL_LINEAR过滤。 In that case, you can directly use value as texture coordinate and will get the result you need. 在这种情况下,您可以直接使用value作为纹理坐标,并获得所需的结果。 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. 因此,如果您没有不使用纹理的特定原因,强烈建议您这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM