I've implemented a heightmap in OpenGL. For now it is just a sine/cosine curved terrain. At the moment I am interpolating between the white "ice" and the darker "stone" texture. This is done like this:
color = mix(texture2D(ice_layer_tex, texcoord), texture2D(stone_layer_tex, texcoord), (vertex.y + amplitude) / (amplitude * 2))
The result:
It works fine, but what could I do if I want to add more textures, for example a grass texture, so that the interpolation order is "ice, stone, grass"? I think, there isn't a function like mix(sampler2D[], percentages[])
? How could I write a GLSL method following this logic?
mix()
is really just a convenience function for something you can easily write yourself. The definition is:
mix(v1, v2, a) = v1 * (1 - a) + v2 * a
Or putting it differently, it calculates a weighted average of v1
and v2
, with two weights w1
and w2
that are float values between 0.0 and 1.0 meeting the constraint w1 + w2 = 1.0
:
v1 * w1 + v2 * w2
You can directly generalize this to calculate a weighted average of more than 2 inputs. For example, for 3 inputs v1
, v2
and v3
, you would use 3 weights w1
, w2
and v3
meeting the constraint w1 + w2 + w3 = 1.0
, and calculate the weighted average as:
v1 * w1 + v2 * w2 + v3 * w3
For your example, determine the weights you want to use for each of the 3 textures, and then use something like:
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;