有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java GLSL着色器:在两个以上纹理之间插值

我已经在OpenGL中实现了一个高度映射。目前它只是一个正弦/余弦曲线地形。 目前,我正在白色“冰”和深色“石”纹理之间进行插值。 这是这样做的:

color = mix(texture2D(ice_layer_tex, texcoord), texture2D(stone_layer_tex, texcoord), (vertex.y + amplitude) / (amplitude * 2))

结果是:

from top

from bottom

它工作得很好,但是如果我想添加更多纹理,例如草纹理,那么插值顺序是“冰、石、草”,我该怎么办?我想,没有像mix(sampler2D[], percentages[])这样的函数吗?如何按照这种逻辑编写GLSL方法


共 (3) 个答案

  1. # 1 楼答案

    mix()实际上只是一个方便的函数,您可以自己轻松编写。定义是:

    mix(v1, v2, a) = v1 * (1 - a) + v2 * a
    

    或者换言之,它计算v1v2的加权平均值,其中两个权重w1w2是满足约束的介于0.0和1.0之间的浮点值w1 + w2 = 1.0

    v1 * w1 + v2 * w2
    

    您可以直接将其推广到计算2个以上输入的加权平均值。例如,对于3个输入v1v2v3,您将使用满足约束w1 + w2 + w3 = 1.0的3个权重w1w2v3,并将加权平均值计算为:

    v1 * w1 + v2 * w2 + v3 * w3
    

    对于您的示例,请确定要为3种纹理中的每种纹理使用的权重,然后使用以下方法:

    weightIce = ...;
    weightStone = ...;
    weightGrass = 1.0 - weightIce - weightStone;
    color = texture2D(ice_layer_tex, texcoord) * weightIce +
            texture2D(stone_layer_tex, texcoord) * weightStone +
            texture2D(grass_layer_tex, texcoord) * weightGrass;
    
  2. # 2 楼答案

    其他答案已经为您要求的genralizedmix()函数提供了解决方案。但我建议使用不同的方法,因为您明确地描述了“插值顺序(冰、石、草)”。在这种情况下,您不需要为每个元素指定任意权重,只需混合相邻元素,如冰+石或石+草,但决不混合冰+草或冰+石+草。如果是这种情况,您可以简单地使用3D纹理和(三)线性过滤。只需将每个2D纹理用作3D纹理中的切片。前两个texcoords可以保持原样,第三个可以直接用于选择两个相邻切片之间的任意混合。由于texcoords始终在[0,1]范围内,因此只需将范围映射到该间隔即可。第i个切片的“中心”位于

    p=i/num_layers + 1/(2*num_layers)
    

    假设你有3片冰、石头和草。所以你得到了

    0/3+1/6 = 0.16667       100% ice  
    1/3+1/6 = 0.5           100% stone
    2/3+1/6 = 0.83333       100% grass
    

    相邻层之间的任意线性混合,就像

    1/3 = 0.3333            50% ice + 50% stone  
          0.6               70% stone  + 30% grass
    ...
    
  3. # 3 楼答案

    不,根据mix()的GLSL文档,只有两个参数之间的插值重载

    您是否可以只插入“冰”和“石”,然后将结果与“草”纹理混合

    vec4 ice_color   = texture2D(ice_layer_tex,   texcoord);
    vec4 stone_color = texture2D(stone_layer_tex, texcoord);
    vec4 grass_color = texture2D(grass_layer_tex, texcoord);
    
    vec4 tmp = mix(ice_color, stone_color, pct);
    vec4 final_color = mix(tmp, grass_color, pct);