Opengl 着色器:在两个纹理之间进行插值
Opengl Shader : Interpolating between two textures
我正在尝试用 c++ 和 opengl 构建一个随机地形生成器,但我在纹理方面遇到了一些问题。
我有两种质地:药草和岩石:
如你所见,山顶上是岩石,下面是草本植物。我通过顶点的高度在这两个纹理之间进行插值。我的高度值在 -1 和 1 之间。所以在我的片段着色器中我这样做:
float height = clamp(vs_position.y/20.f, -1f, 1f );
height = exp(height) / exp(1.f);
vec3 final_texture = mix(
vec3(texture(texture0, vs_texcoord)),
vec3(texture(texture1, vs_texcoord)),
vec3(height));
第一行并不重要,在我将顶点数据发送到我的着色器之前,我将高度乘以 20 以获得更明显的山丘。
口渴线:我按高度混合了两种纹理。
第二行:要进行"stronger"插值,我使用softmax函数使高度值接近0或1。老实说它并没有做太多,也许我不使用这个函数正确。
我想要的是做一个更强的softmax,并且能够控制插值的水平。所以我的高度值应该更接近于 0 或 1。因为我通过插值得到的结果现在看起来不太好。
因此,例如,如果我的身高是 0.7,则应将其转换为 0.95。 f(0.3) = 0.05,f(0.5) = 0.5。像那样的东西。
你知道这方面的秘诀吗?
编辑:
我做到了 !
很简单,我只是重复了几次softmax函数:
float softmax(float value, float max , int iteration, float offset)
{
value += offset;
for(int i=0; i<iteration; i++)
{
value = exp(value);
max = exp(max);
}
value = (value/max);
value = clamp(value, 0.f, 1.f);
return value;
}
然后我使用偏移量来选择插值开始的高度
我推荐使用smoothstep
to "smoothly" map the height from its range (e.g. [-20.0, 20.0]) to the range [0.0, 1.0] for the interpolation by mix
。例如:
(smoothstep
执行 Hermite interpolation)
vec3 color0 = texture(texture0, vs_texcoord).rgb;
vec3 color1 = texture(texture1, vs_texcoord).rgb;
float a = smoothstep(-20.0, 20.0, height);
vec3 final_texture = mix(color0, color1, a);
注意,甚至可以将插值限制在一定范围内。在下文中,如果 height < -1.0
,则使用 texture0
的颜色;如果 height > -1.0
,则使用 texture1
的颜色。在它之间平滑地插入纹理之间:
float a = smoothstep(-1.0, 1.0, height);
vec3 final_texture = mix(color0, color1, a);
我正在尝试用 c++ 和 opengl 构建一个随机地形生成器,但我在纹理方面遇到了一些问题。
我有两种质地:药草和岩石:
如你所见,山顶上是岩石,下面是草本植物。我通过顶点的高度在这两个纹理之间进行插值。我的高度值在 -1 和 1 之间。所以在我的片段着色器中我这样做:
float height = clamp(vs_position.y/20.f, -1f, 1f );
height = exp(height) / exp(1.f);
vec3 final_texture = mix(
vec3(texture(texture0, vs_texcoord)),
vec3(texture(texture1, vs_texcoord)),
vec3(height));
第一行并不重要,在我将顶点数据发送到我的着色器之前,我将高度乘以 20 以获得更明显的山丘。
口渴线:我按高度混合了两种纹理。
第二行:要进行"stronger"插值,我使用softmax函数使高度值接近0或1。老实说它并没有做太多,也许我不使用这个函数正确。
我想要的是做一个更强的softmax,并且能够控制插值的水平。所以我的高度值应该更接近于 0 或 1。因为我通过插值得到的结果现在看起来不太好。 因此,例如,如果我的身高是 0.7,则应将其转换为 0.95。 f(0.3) = 0.05,f(0.5) = 0.5。像那样的东西。 你知道这方面的秘诀吗?
编辑: 我做到了 !
很简单,我只是重复了几次softmax函数:
float softmax(float value, float max , int iteration, float offset)
{
value += offset;
for(int i=0; i<iteration; i++)
{
value = exp(value);
max = exp(max);
}
value = (value/max);
value = clamp(value, 0.f, 1.f);
return value;
}
然后我使用偏移量来选择插值开始的高度
我推荐使用smoothstep
to "smoothly" map the height from its range (e.g. [-20.0, 20.0]) to the range [0.0, 1.0] for the interpolation by mix
。例如:
(smoothstep
执行 Hermite interpolation)
vec3 color0 = texture(texture0, vs_texcoord).rgb;
vec3 color1 = texture(texture1, vs_texcoord).rgb;
float a = smoothstep(-20.0, 20.0, height);
vec3 final_texture = mix(color0, color1, a);
注意,甚至可以将插值限制在一定范围内。在下文中,如果 height < -1.0
,则使用 texture0
的颜色;如果 height > -1.0
,则使用 texture1
的颜色。在它之间平滑地插入纹理之间:
float a = smoothstep(-1.0, 1.0, height);
vec3 final_texture = mix(color0, color1, a);