PrevNext

Procedural Texturing

Author: Oscar Julián Tinjacá y Luis Miguel Báez

Procedural Texturing

Edit This Page

Procedural Texturing

Las texturas de procedimiento son texturas (a veces también llamadas mapas) que genera la computadora utilizando un conjunto fijo de parámetros. ¡Esto significa que la computadora puede hacer variaciones únicas de una textura por sí misma!

El proceso utilizado para hacer esto se llama generación procedimental.

La generación de procedimientos es un término general para cuando una computadora genera datos automáticamente, en lugar de que el usuario tenga que hacerlo a mano.

Esto se usa a menudo en muchas otras áreas de trabajo y juegos en 3D. Minecraft, por ejemplo, tiene un mapa que se genera por procedimientos, lo que le permite ser tan grande. La mano de obra para hacer cosas de ese tamaño sería poco práctica.

Las texturas de procedimiento se pueden encontrar en algunos software 3D de forma predeterminada, y también en software de texturización creado específicamente.

Substance Painter es un buen ejemplo de software que tiene varios tipos de generadores de procedimientos para crear texturas únicas fácilmente.

Algoritmos de Generación de laberintos

Algoritmos clásicos de generación de laberintos a nivel de software

  • Randomized DFS
    • Utilizando Recursividad
    • Utilizando un Stack
  • Randomized Kruskal's algorithm
  • Randomized Prim's algorithm
  • Wilson's algorithm
  • Aldous-Broder algorithm
  • Cellular automaton algorithms

Como observamos anteriormente existen múltiples algoritmos para la generación aleatoria de laberintos a nivel de software, cada uno tiene ventajas y desventajas respecto a los demás dependiendo las necesidades y requerimientos qué se tengan. Sin embargo, nos encontramos con un gran problema cuando intentamos realizar esta generación utilizando estos algoritmos a nivel de hardware de forma paralela debido a qué la mayoría de estos algoritmos requieren información del estado de celdas previas y esto es imposible de realizar cuando se está ejecutando un procedimiento de forma paralela. Una posible solución a este problema es utilizar estructura de datos mediante memoria compartida transversal a todos los procesos. No obstante, revisando la documentación de Fragment Shader / GLSL, no es posible realizar este procedimiento, por lo cual debemos descartar la gran mayoría de los algoritmos a nivel de software qué realizan este procedimiento.

Patrón de Truchet

En el siglo XVIII el cura dominico frances Sébastien Truchet qué estaba muy interesado en los patrones qué se podían formar con las baldosas, para formar figuras geométricas novedosas con ellas. Empezó dividiendo las baldosas por la mitad en diagonal y las pintaba solo la mitad.

Después de ello se dió a la gran tarea de contar el número de distintas formas qué se pueden formar utilizando dos baldosas, rotandolas cada una. Sé dio cuenta qué se podian generar 54 patrones y el los agrupo en 10 grupos como se puede ver en la (imagen x)

El número posible de combinaciones es muy grande y muchas de ellas tienen algún tipo de simetría qué puede ser interesante observar, como lo realizó Truchet en la siguiente imagen:

Casi 300 Años después el ingeniero metalúrgico Cyril Stanley Smith en un proyecto como profesor de la universidad escribió un artículo científico relacionado y en continuación al trabajo de Truchet relacionándolos con los efectos de la materia y introduciendo de la misma forma unos diseños sencillos pero interesantes qué se combinan entre sí, consiguiendo un entramado de zonas abiertas y cerradas similares a un laberinto como lo puede ver a continuación:

Únicamente cambiando el diseño de una baldosa, se pueden formar laberintos geométricamente diferentes como se puede observar en la imagen de abajo.

Así mismo, cambiando la baldosa utilizando una, dos y más líneas diagonales y circulares, se pueden conseguir muchas figuras geométricas con geometrías complejas pero estéticamente interesantes.

Funciones e Interpolaciones utilizadas

Step step(edge, x)

Generar una función escalonada

Para el elemento i del valor devuelve, 0.0 Si x[i] < edge[i] y 1.0 en caso contrario.

Smoothstep smoothstep(edge0, edge1, x)

Realizar la interpolación de Hermite entre dos valores

Devuelve 0.0 si el valor de i está antes del rango edge1 <= x <= edge2, devuelve 1.0 si el valor de i está después de ese rango y realiza la interpolación suave de Hermite en cualquier otro caso.

Patrón de Truchet (codigo)

vec2 truchetPattern(in vec2 pos, in float rand){
rand = fract(((rand-0.5)*2.0));
if (rand > 0.75) { // [/]
pos = vec2(1.0) - pos;
} else if (rand > 0.5) { // [\]
pos = vec2(1.0-pos.x, pos.y);
} else if (rand > 0.25) { // [/]
pos = 1.0-vec2(1.0-pos.x, pos.y);
}
// [/] or [\]
return pos;
}

Generación de Laberinto

vec2 tile = truchetPattern(fpos, random(ipos));
// Pintamos la linea diagonal de grosor 0.6
color = smoothstep(tile.x - 0.3, tile.x, tile.y) - smoothstep(tile.x, tile.x + 0.3, tile.y);

Generación de Laberinto Circular

vec2 tile = truchetPattern(fpos, random(ipos));
color = (
(
step(length(tile), 0.6) -
step(length(tile), 0.4)
) +
(
step(length(tile - vec2(1.0)), 0.6) -
step(length(tile - vec2(1.0)), 0.4)
)
);

Generación de Laberinto utilizando Triángulos

vec2 tile = truchetPattern(fpos, random(ipos));
color = step(tile.x, tile.y);

A continuación se encuentra la implementación de los Patrones de Truchet en p5.js y Fragment Shader, para la generación de laberintos aleatorios utilizando diferentes baldosas:

P5.js

Fragment Shader

Resources: References
Concept Art Empire

Thomas Denham

Hacker Ludico Blog Spot

Chuso Jar

The Book of Shaders

Patricio Gonzalez Vivo & Jen Lowe

Module Progress:

PrevNext