
En este artículo explicaré un algoritmo de salpicaduras de textura que le permite crear un terreno más natural. Este algoritmo se puede usar en sombreadores de juegos 3D, así como en juegos 2D.
Una de las formas más comunes de texturizar el terreno es combinar múltiples capas de mosaico. Cada capa tiene un mapa de opacidad que define el alcance de la presencia de textura en el terreno. El método funciona aplicando un mapa de opacidad a los niveles superiores, revelando las capas debajo de donde el mapa de opacidad es parcial o completamente transparente. El mapa de opacidad se mide en porcentaje. Por supuesto, en cada punto de un terreno, la suma de las opacidades de todas las capas es cien por ciento, ya que el terreno no puede ser transparente. En lugar de texturas de mosaico, el mapa de opacidad se extiende completamente en todo terreno y, por lo tanto, tiene un nivel de detalle bastante bajo.
Ahora pasaremos a la parte más interesante: algoritmos de mezcla de texturas. Por simplicidad y claridad, nuestro terreno consistirá en arena y adoquines grandes.

La forma más simple de mezclar es multiplicar el color de la textura con opacidad y luego sumar los resultados.
float3 blend(float4 texture1, float a1, float4 texture2, float a2) { return texture1.rgb * a1 + texture2.rgb * a2; }
Dicha técnica se utiliza en Unity3D en el editor de terreno estándar. Como puede ver, la transición es suave pero poco natural. Las piedras se ven uniformemente sucias por la arena, pero en el mundo real no sucede así. La arena no se pega a las piedras, sino que se cae y llena las grietas entre ellas, dejando la parte superior de las piedras puras.
Intentemos simular este comportamiento en trazados de Excel. Como queremos que la arena se "caiga" entre los adoquines, para cada textura necesitamos el mapa de profundidad. En este ejemplo, consideramos que el mapa de profundidad se genera a partir de una imagen en escala de grises y se almacena en el canal alfa de una textura. En Unity3D se puede hacer en el inspector de texturas configurando la bandera "Alfa de escala de grises".
En primer lugar, consideraremos el modelo simplificado del mapa de profundidad de arena y piedras.

La línea azul en la parcela simboliza el mapa de profundidad de arena y el rojo es de adoquines. Tenga en cuenta que la parte superior de las piedras se encuentra más alta que el nivel de arena. Considerando este hecho, trataremos de dibujar píxeles de esa textura que está arriba.
float3 blend(float4 texture1, float a1, float4 texture2, float a2) { return texture1.a > texture2.a ? texture1.rgb : texture2.rgb; }

Excelente! Las partes superiores de los adoquines permanecen puras, mientras que la arena se encuentra en grietas entre ellas. Pero aún no consideramos la opacidad de la capa. Para usarlo, solo sumamos el mapa de profundidad y el mapa de opacidad.
float3 blend(float4 texture1, float a1, float4 texture2, float a2) { return texture1.a + a1 > texture2.a + a2 ? texture1.rgb : texture2.rgb; }
A expensas de la suma, la textura menos transparente será más alta de lo habitual.


Entonces tenemos una transición más natural de la arena a las piedras. Como puede ver, los granos de arena comienzan a llenar grietas entre los adoquines, ocultándolos gradualmente. Pero a medida que los cálculos se realizan píxel por píxel, comienzan a aparecer artefactos en el borde entre las texturas. Para obtener un resultado uniforme, tomaremos varios píxeles de profundidad en lugar de uno y los combinaremos.
float3 blend(float4 texture1, float a1, float4 texture2, float a2) { float depth = 0.2; float ma = max(texture1.a + a1, texture2.a + a2) - depth; float b1 = max(texture1.a + a1 - ma, 0); float b2 = max(texture2.a + a2 - ma, 0); return (texture1.rgb * b1 + texture2.rgb * b2) / (b1 + b2); }
En el código anterior, al principio obtenemos parte de un terreno visto a cierta profundidad.

Y luego lo normalizamos para obtener nuevas opacidades.


Como resultado, encontramos el algoritmo de mezcla de texturas, que nos permite acercarnos a una imagen de terreno natural.