Contenido principal
Programación de computadoras
Ruido Perlin
Un buen generador de números aleatorios produce números que no tienen relación y que no muestran un patrón discernible. Como estamos empezando a ver, un poco de aleatoriedad puede ser algo bueno cuando se programan comportamientos orgánicos, naturales. Sin embargo, la aleatoriedad como el único principio guía no es necesariamente natural.
Hay un algoritmo que produce resultados más naturales, y que se conoce como “ruido Perlin". Ken Perlin desarrolló la función de ruido mientras trabajaba en la película original de Tron al principio de la década de 1980; la usó para crear texturas procedurales de efectos generados por computadora. En 1997, Perlin ganó un premio de la Academia de logro técnico por este trabajo. El ruido Perlin se puede usar para generar varios efectos con cualidades naturales como nubes, paisajes y texturas estampadas como mármol.
El ruido Perlin tiene un aspecto más orgánico porque produce una secuencia naturalmente ordenada (“suave”) de números pseudoaleatorios. La gráfica a continuación muestra ruido Perlin a través del tiempo, con el eje x que representa al tiempo; observa la suavidad de la curva.
De manera contrastante, la siguiente gráfica a continuación muestra números aleatorios puros a través del tiempo.
ProcessingJS tiene una implementación del algoritmo de ruido Perlin integrada: la función
noise()
. La función noise()
toma uno, dos o tres argumentos, ya que el ruido se calcula en una, dos o tres dimensiones. Empecemos por ver el ruido unidimensional.Detalle del ruido
La referencia del ruido nos dice que el ruido se calcula a través de varias “octavas”. Llamar la función
noiseDetail()
cambiará tanto el número de octavas como la importancia relativa entre ellas. Esto, a su vez, cambia cómo se comporta el ruido.Considera dibujar un círculo en nuestra ventana de ProcessingJS en una posición x aleatoria:
var x = random(0, width);
ellipse(x, 180, 16, 16);
Ahora, en lugar de una posición x aleatoria, queremos una posición x con ruido Perlin que sea “más suave”. Podrías pensar que todo lo que necesitas hacer es reemplazar
random()
con noise()
, es decir,var x = noise(0, width);
ellipse(x, 180, 16, 16);
Mientras que conceptualmente esto es exactamente lo que queremos hacer, calcular un valor de x que oscile entre 0 y el ancho de acuerdo con el ruido Perlin, no es la implementación correcta. Mientras que los argumentos de la función
random()
especifican un rango de valores entre un mínimo y un máximo, noise()
no funciona de esa manera. En cambio, noise()
espera que le pasemos un argumento que significa "un momento en el tiempo" y siempre regresa un valor entre 0 y 1. Podemos pensar en el ruido Perlin unidimensional como una secuencia lineal de valores a través del tiempo. Por ejemplo, aquí hay ejemplos de entradas y valores de salida:Tiempo | Valor de ruido |
---|---|
0 | 0.469 |
0.01 | 0.480 |
0.02 | 0.492 |
0.03 | 0.505 |
0.04 | 0.517 |
Ahora, para poder acceder a uno de esos valores de ruido en ProcessingJS, tenemos que pasarle un momento específico en el tiempo a la función
noise()
. Por ejemplo:var n = noise(0.03);
De acuerdo con la tabla anterior,
noise()
regresará 0.505 al tiempo 0.03. Podemos escribir un programa que almacene una variable de tiempo y pida ese valor de ruido de manera continua en draw()
.El código anterior resulta en el mismo valor escrito una y otra vez. Esto sucede porque estamos pidiendo el resultado de la función
noise()
en el mismo punto en el tiempo una y otra vez. Sin embargo, si aumentamos la variable de tiempo
t
, obtendremos un resultado diferente.La tasa a la cual aumentamos
t
también afecta la suavidad del ruido. Si hacemos saltos grandes en el tiempo, entonces estamos saltando hacia adelante y los valores serán más aleatorios.Intenta ejecutar el código anterior varias veces, aumentando t en 0.01, 0.02, 0.05, 0.1, 0.0001, y verás resultados diferentes.
Mapear el ruido
Ahora estamos listos para responder a la pregunta de qué hacer con el valor del ruido. Una vez que tengamos el valor con un rango entre 0 y 1, depende de nosotros mapear ese rango a lo que queramos.
Podríamos simplemente multiplicarlo por el número máximo en el rango, pero esta también es una buena oportunidad para introducir la función
map()
de ProcessingJS, la cual nos ayudará en otras situaciones más adelante. La función map()
toma cinco argumentos. El primero es el valor que queremos mapear, en este caso n
. Después tenemos que darle el rango actual del valor (mínimo y máximo), seguido de nuestro rango deseado.En este caso, sabemos que el ruido tiene un rango entre 0 y 1, pero nos gustaría dibujar un rectángulo con un ancho de entre 0 y el ancho actual.
Podemos aplicar exactamente la misma lógica a nuestro caminante aleatorio y asignarle sus valores x y y de acuerdo con el ruido Perlin.
Observa cómo el ejemplo anterior requiere un par de variables adicionales:
tx
y ty
. Esto es porque necesitamos llevar un registro de dos variables de tiempo, una para la posición x del objeto Walker
y otra para la posición y. Pero hay algo un poco extraño acerca de esas variables. ¿Por qué
tx
empieza en 0 y ty
en 10,000? Mientras que estos números son opciones arbitrarias, inicializamos de manera muy específica nuestras dos variables de tiempo con valores muy diferentes. Esto es porque la función de ruido es determinista: cada vez te da el mismo resultado para un tiempo específico t
. Si pidiéramos el valor de ruido al mismo tiempo t
para x
y y
, entonces x
y y
siempre serían iguales, lo que significaría que el objeto Walker
solo se movería a lo largo de una diagonal. En lugar de eso, simplemente usamos dos partes diferentes del espacio de ruido, empezando en 0 para x
y en 10,000 para y
de modo que x
y y
parezcan actuar de manera independiente una de la otra.En verdad, no hay ningún concepto verdadero del tiempo en juego aquí. Es una metáfora útil para ayudarnos a entender cómo funciona la función de ruido, pero en realidad lo que tenemos es espacio, en lugar de tiempo. La gráfica anterior muestra una secuencia lineal de valores de ruido en un espacio unidimensional, y podemos pedir un valor en una posición x específica cada que queramos. En los ejemplos, a menudo verás una variable llamada
xoff
para indicar el desplazamiento en la dirección x a lo largo de la gráfica de ruido, en vez de t
para el tiempo (como se indica en el diagrama).En el próximo desafío, intentarás usar ruido con el
Walker
de una manera ligeramente diferente. ¡Que te diviertas!Este curso de "Simulaciones Naturales" es un derivado de "La Naturaleza del Código" por Daniel Shiffman, usado bajo una Licencia Creative Commons Reconocimiento-NoComercial 3.0 Unported.
¿Quieres unirte a la conversación?
- hola como hacen que aga ruido(3 votos)
- Hola yo te digo ahi un codigo que se llama `playSound' si pones asi 'playSond(getSound(retro/giant-yah));' asi luego escoge el ruido que quieres usar copias el sonido que quieres usar pero antes de escribir playSound tienes que escribi mouseClicked=function() { }; el codigo playsound tiene que estar adrentro de la funsion mouse(7 votos)