Ruido perlín

ImprimirCitar
Tipo de ruido gradiente en gráficos de la computadora
Rebanada bidimensional a través del ruido 3D Perlin z = 0
El

ruido Perlin es un tipo de ruido de gradiente desarrollado por Ken Perlin en 1983. Tiene muchos usos, que incluyen, entre otros: generar terreno de forma procesal, aplicar cambios pseudoaleatorios a una variable y ayudando en la creación de texturas de imágenes. Generalmente se implementa en dos, tres o cuatro dimensiones, pero se puede definir para cualquier número de dimensiones.

Historia

Ken Perlin desarrolló el ruido Perlin en 1983 como resultado de su frustración con el sistema "parecido a una máquina" aspecto de las imágenes generadas por computadora (CGI) en ese momento. Describió formalmente sus hallazgos en un artículo de SIGGRAPH de 1985 llamado "An Image Synthesizer". Lo desarrolló después de trabajar en la película de ciencia ficción animada por computadora de Disney Tron (1982) para la compañía de animación Mathematical Applications Group (MAGI). En 1997, Perlin recibió un Premio de la Academia por logros técnicos por crear el algoritmo, cuya cita decía:

Para Ken Perlin para el desarrollo de Perlin Noise, una técnica utilizada para producir texturas naturales que aparecen en las superficies generadas por ordenador para efectos visuales de imagen de movimiento. El desarrollo de Perlin Noise ha permitido que los artistas gráficos computacionales representen mejor la complejidad de los fenómenos naturales en efectos visuales para la industria cinematográfica.

Perlin no solicitó ninguna patente sobre el algoritmo, pero en 2001 se le concedió una patente para el uso de implementaciones 3D+ de ruido simplex para la síntesis de texturas. El ruido simplex tiene el mismo propósito, pero utiliza una cuadrícula más simple para llenar el espacio. El ruido simplex alivia algunos de los problemas del "ruido clásico" de Perlin, entre ellos la complejidad computacional y los artefactos direccionales visualmente significativos.

Usos

Un paisaje virtual generado mediante el ruido de Perlin

El ruido Perlin es una textura primitiva de procedimiento, un tipo de ruido degradado utilizado por los artistas de efectos visuales para aumentar la apariencia de realismo en los gráficos por computadora. La función tiene una apariencia pseudoaleatoria, pero todos sus detalles visuales son del mismo tamaño. Esta propiedad le permite ser fácilmente controlable; Se pueden insertar múltiples copias escaladas de ruido Perlin en expresiones matemáticas para crear una gran variedad de texturas procesales. Las texturas sintéticas que utilizan ruido Perlin se utilizan a menudo en CGI para hacer que los elementos visuales generados por computadora (como superficies de objetos, fuego, humo o nubes) parezcan más naturales, imitando la apariencia aleatoria controlada de las texturas en la naturaleza.

Una superficie orgánica generada con ruido Perlin

También se utiliza con frecuencia para generar texturas cuando la memoria es extremadamente limitada, como en las demostraciones. Sus sucesores, como el ruido fractal y el ruido simplex, se han vuelto casi omnipresentes en las unidades de procesamiento de gráficos tanto para gráficos en tiempo real como para texturas procesales en tiempo no real en todo tipo de gráficos por computadora.

Se utiliza con frecuencia en videojuegos para crear terreno generado por procedimientos que parezca natural.

Detalle del algoritmo

El ruido perlín reescalcó y se añadió en sí mismo para crear ruido fractal.

El ruido Perlin se implementa más comúnmente como una función de dos, tres o cuatro dimensiones, pero se puede definir para cualquier número de dimensiones. Una implementación generalmente implica tres pasos: definir una cuadrícula de vectores de gradiente aleatorios, calcular el producto escalar entre los vectores de gradiente y sus desplazamientos e interpolar entre estos valores.

Definición de cuadrícula

Una cuadrícula bidimensional de vectores gradientes

Defina una cuadrícula n-dimensional donde cada intersección de la cuadrícula tenga asociada una nvector de gradiente de longitud unitaria de dimensiones, excepto en el caso unidimensional donde los gradientes son escalares aleatorios entre −1 y 1.

Producto escalar

El producto de puntos de cada punto con su valor gradiente de nodo de red más cercano. El producto de punto con los otros tres nodos en la célula no se muestra.

Para calcular el valor de cualquier punto candidato, primero encuentre la celda única de la cuadrícula en la que se encuentra el punto. Luego, identifica las 2n esquinas de esa celda y sus vectores de gradiente asociados. A continuación, para cada esquina, calcule un vector de desplazamiento. Un vector de desplazamiento es un vector de desplazamiento desde esa esquina hasta el punto candidato.

Para cada esquina, tomamos el producto escalar entre su vector de gradiente y el vector de desplazamiento hasta el punto candidato. Este producto escalar será cero si el punto candidato está exactamente en la esquina de la cuadrícula.

Tenga en cuenta que la influencia de un vector de gradiente crece con la distancia, lo que se puede evitar normalizando primero el vector de desplazamiento a una longitud de 1. Esto introduciría cambios bruscos notables, excepto que la distancia se tenga en cuenta en el siguiente paso de interpolación. Sin embargo, normalizar el vector de compensación no es una práctica común.

Para un punto en una cuadrícula bidimensional, esto requerirá el cálculo de cuatro vectores desplazados y productos escalares, mientras que en tres dimensiones requerirá ocho vectores desplazados y ocho productos escalares. En general, el algoritmo tiene O(2n) complejidad en n dimensiones.

Interpolación

El resultado final interpolado

El último paso es la interpolación entre los 2n productos escalares. La interpolación se realiza utilizando una función que tiene cero primera derivada (y posiblemente también segunda derivada) en los 2n nodos de la cuadrícula.. Por lo tanto, en puntos cercanos a los nodos de la cuadrícula, la salida aproximará el producto escalar del vector de gradiente del nodo y el vector de desplazamiento del nodo. Esto significa que la función de ruido pasará por 0 en cada nodo, dándole al ruido Perlin su aspecto característico.

Si n = 1, un ejemplo de una función que interpola entre el valor a0 en el nodo 0 de la cuadrícula y valor a1 en la cuadrícula el nodo 1 es

f()x)=a0+gradual⁡ ⁡ ()x)⋅ ⋅ ()a1− − a0)para0≤ ≤ x≤ ≤ 1{displaystyle f(x)=a_{0}+operatorname {smoothstep} (x)cdot (a_{1}-a_{0})quad {text{for }0leq xleq 1}

donde se utilizó la función smoothstep.

Did you mean:

Noise functions for use in computer graphics typically produce values in the range [–1.0, 1.0] and can be scaled accordingly.

Implementación

La siguiente es una implementación bidimensional del ruido Perlin clásico, escrita en C.

La implementación de referencia original de Perlin tenía diferencias importantes:

  • está utilizando un enfoque tridimensional interpolando entre 8 esquinas de un cubo en lugar de los 4 rincones de un cuadrado debajo.
  • la dirección gradiente aleatoria revuelve los pedazos de las coordenadas enteros de las esquinas, que es mucho más rápido que el recubrimiento usando la interferencia a alta frecuencia de las coordenadas del entero de las esquinas, fusionado y rotado de nuevo a alta frecuencia por un producto: las rotaciones no se distribuyen uniformemente.
  • El método de Perlin dividió el espacio entero en 256 × 256 × 256 cubos y luego utiliza una permutación aleatoria de estos cubos para eliminarlos, y luego cada cubo esquinas de posición se asigna una de doce direcciones a los cubos no permutados vecinos en un 4 × 4 × 4 espacio de pavimentación: esto requiere solamente operaciones enteros pero mantiene una distribución uniforme de direcciones.
  • la función de interpolación es el liso más suave de 4 grados (con los tres primeros derivados iguales a cero en los límites de sujeción) y no el paso lineal básico. Esto evita los artefactos visibles, especialmente a lo largo de vertices o diagonales que se unen a las esquinas de muestreo, donde el resultado sería visiblemente anisotrópico (teniendo el ruido blanco deseado en el ruido rosado; si el ruido se utiliza para generar un cristal sólido, no sería totalmente negro y opaco a la luz, pero parcialmente transparente y coloreado en algunas direcciones discretas de observación).
#include - No./* Función de interpolar linealmente entre a0 y a1 * Peso w debe estar en el rango [0.0, 1.0] */flotador interpolato()flotador a0, flotador a1, flotador w) {} /* // Usted puede querer aferrarse insertando: * si (0,0,0,0) regresa a0; * si (1.0) w) devuelve a1; */ retorno ()a1 - a0) * w + a0; /* // Use esta interpolación cúbica [[Smoothstep]] en su lugar, para una apariencia suave: * return (a1 - a0) * (3.0 - w * 2.0) * w * + a0; * * // Use [[Smootherstep] para un resultado aún más suave con un segundo derivado igual a cero en los límites: * Return (a1 - a0) * (w * (w * 6.0 - 15.0) + 10.0) * w * w * w * w) + a0; */}Tipodef struct {} flotador x, Sí.;} vector2;/* Crear dirección de pseudorandom vector */vector2 al azar Gradiente()int ix, int i) {} // Ningún gradiente precomputado significa que esto funciona para cualquier número de coordenadas de red const no firmado w = 8 * tamaño()no firmado); const no firmado s = w / 2; // ancho de rotación no firmado a = ix, b = i; a *= 3284157443; b ^= a .. s Silencio a > w-s; b *= 1911520717; a ^= b .. s Silencio b > w-s; a *= 2048419325; flotador al azar = a * ()3.14159265 / ~()~0u > 1)); // in [0, 2*Pi] vector2 v; v.x = #()al azar); v.Sí. = pecado()al azar); retorno v;}// Computa el producto de puntos de la distancia y los vectores gradientes.flotador dotGridGradient()int ix, int i, flotador x, flotador Sí.) {} // Obtener gradiente de las coordenadas enteros vector2 gradiente = al azar Gradiente()ix, i); // Computar el vector de distancia flotador dx = x - ()flotador)ix; flotador dy = Sí. - ()flotador)i; // Computar el producto de puntos retorno ()dx*gradiente.x + dy*gradiente.Sí.);}// Computar el ruido de Perlin en las coordenadas x, yflotador perlina()flotador x, flotador Sí.) {} // Coordenadas de celda de rejilla int x0 = ()int)planta baja()x); int x1 = x0 + 1; int Y0 = ()int)planta baja()Sí.); int y1 = Y0 + 1; // Determinar pesos de interpolación // También podría utilizar un orden superior polinomial / s-curve aquí flotador Sx = x - ()flotador)x0; flotador Sy = Sí. - ()flotador)Y0; // Interpolato entre gradientes de punto de rejilla flotador n0, n1, ix0, ix1, valor; n0 = dotGridGradient()x0, Y0, x, Sí.); n1 = dotGridGradient()x1, Y0, x, Sí.); ix0 = interpolato()n0, n1, Sx); n0 = dotGridGradient()x0, y1, x, Sí.); n1 = dotGridGradient()x1, y1, x, Sí.); ix1 = interpolato()n0, n1, Sx); valor = interpolato()ix0, ix1, Sy); retorno valor; // Volverá en rango -1 a 1. Para hacerlo en el rango 0 a 1, multiplicar por 0,5 y añadir 0,5}

Permutación

Muchas implementaciones de ruido Perlin utilizan el mismo conjunto de permutaciones que Ken Perlin utilizó en su implementación original. Esa implementación es la siguiente:

int permutación[] = {} 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180 };

Esta permutación específica no es absolutamente necesaria, aunque sí requiere una matriz aleatoria de números enteros del 0 al 255. Si se crea una nueva tabla de permutaciones, se debe tener cuidado para garantizar una distribución uniforme de los valores.

Complejidad

Para cada evaluación de la función de ruido, el producto escalar de los vectores de posición y gradiente debe evaluarse en cada nodo de la celda de la cuadrícula que lo contiene. Por lo tanto, el ruido Perlin aumenta con la complejidad O(2n) para n dimensiones. Las alternativas al ruido Perlin que producen resultados similares con una escala de complejidad mejorada incluyen el ruido simplex y el ruido OpenSimplex.

Contenido relacionado

Camino euleriano

En teoría de grafos, un camino euleriano es un sendero en un grafo finito que visita cada borde exactamente una vez (lo que permite volver a visitar los...

Lema de Fatou

En matemáticas, el lema de Fatou establece una desigualdad que relaciona la integral de Lebesgue del límite inferior de una sucesión de funciones con el...

Copia de objetos

En la programación orientada a objetos, copiar objetos es crear una copia de un objeto existente, una unidad de datos en la programación orientada a...
Más resultados...
Tamaño del texto:
Copiar