6.7.2  Normal

El Raytracing es conocido por su impresionante forma de simular reflexiones, refracciones y efectos luminosos. Gran parte de nuestra percepción depende de las propiedades reflectivas de un objeto. El Raytracing puede aprovecharse de esto, engañando a nuestra percepción para hacernos ver detalles complejos donde realmente no los hay.

Supongamos que queremos una superficie muy abollada sobre nuestro objeto. Podría ser matemáticamente muy difícil modelar un montón de abolladuras. Sin embargo, podríamos simular una forma de apariencia muy abollada alterando la manera en la que los rayos de luz se reflejan sobre la superficie. Los cálculos de la reflexión dependen de un vector llamado normal a la superficie. Este vector apunta hacia fuera de la superficie y es perpendicular a ella. Modificando artificialmente (o perturbando) este vector normal, podremos simular las abolladuras. Para hacer esto, hay que añadir la expresión normal.

Nota: añadir un patrón normal no es modificar la superficie realmente. Sólo afecta a la forma en que la luz rebota o refracta sobre la superficie a fin de que tenga una apariencia abollada.

La sintaxis es:

NORMAL:
  normal { [NORMAL_IDENTIFIER] [NORMAL_TYPE] [NORMAL_MODIFIER...] }
NORMAL_TYPE:
  PATTERN_TYPE Amount |
  bump_map { BITMAP_TYPE "bitmap.ext" [BUMP_MAP_MODS...]}
NORMAL_MODIFIER:
  PATTERN_MODIFIER | NORMAL_LIST | normal_map { NORMAL_MAP_BODY } |
  slope_map{ SLOPE_MAP_BODY } | bump_size Amount |
  no_bump_scale Bool | accuracy Float
Cada modificador en la normal es opcional, pero si los usamos debemos hacerlo en el modo que aquí se muestra. Cualquier ítem después del identificador NORMAL_IDENTIFIER modifica o controla el patrón determinado en el identificador. Si no se especifica un identificador, entonces el valor de los modificadores de la normal son los que la textura tiene por defecto. El tipo de patrón (PATTERN_TYPE) puede ir seguido opcionalmente de un número en coma flotante que controla la aparente profundidad de las abolladuras. El valor usual se encuentra entre 0.0 y 1.0 pero se puede usar cualquier otro valor. Los valores negativos invierten el patrón. El valor por defecto es 0.5.

Hay cuatro tipos básicos de tipos de normal (NORMAL_TYPE): de patrón de bloque, de patrón continuo, normales especializados y mapas de bultos. Difieren en el tipo de modificadores que podemos usar con cada uno. El tipo de patrón va seguido opcionalmente por uno o más modificadores. Además de los modificadores comunes tales como transformaciones, turbulencia y combamiento, también pueden llevar una lista de normales (NORMAL_LIST), un mapa de inclinación (slope_map), un mapa de normal (normal_map), y la profundidad (bump_size). Estos modificadores son específicos para la normal. Ver "Modificadores de Patrones" para más información sobre los modificadores comunes. Los modificadores específicos para la normal se describen en las sub-secciones siguientes. Estos modificadores específicos de la normal sólo se aplican sobre la normal, y no sobre cualquier otra parte de la textura. Los modificadores deben especificarse en último lugar.

Originalmente POV-Ray tenía algunos patrones que se usaban exclusivamente en los pigmentos, mientras que otros se usaban exclusivamente para la normal. Desde POV-Ray 3.0 podemos usar cualquier patrón para pigmentos o para la normal. Por ejemplo, ahora es válido usar ripples como un pigmento, o wood como un tipo de normal. Los patrones bumps, dents, ripples, waves, wrinkles, y bump_map eran exclusivamente patrones de la normal que no podían usarse como pigmentos. Puesto que estos seis tipos se usan en los cálculos específicos de la normal, éstos no pueden tener slope_map, normal_map o modificadores de la forma de onda. Todos los otros tipos de patrones normales pueden usarlos. Puesto que los patrones checker, hexagon y brick no devuelven una serie continua de valores, no pueden usar estos modificadores. Ver "Patrones" para más detalles.

Una declaración normal es una parte específica de una declaración texture. Sin embargo, puede ser tedioso usar una declaración texture para añadir abolladuras a un objeto. Por consiguiente, podemos añadir una normal directamente a un objeto sin especificar explícitamente que es parte de una textura. Por ejemplo, en lugar de esto:

  object  {My_Object texture { normal { bumps 0.5 } } }
y podríamos acortarlo a:
  object { My_Object normal { bumps 0.5 } }
Haciéndolo así creamos una textura completa, con las declaraciones de pigment y finish por defecto, como si hubiésemos tecleado explícitamente una sentencia texture {...} alrededor de ella. Pueden declarase identificadores de normal, para hacer el archivo de la escena más legible y parametrizarla de forma que, cambiando una simple declaración, los cambios afecten a muchos valores. Un identificador puede ser declarado de la siguiente forma:
NORMAL_DECLARATION:
    #declare IDENTIFIER = NORMAL |
    #local IDENTIFIER = NORMAL
Donde IDENTIFIER es el nombre de una identificador de 40 caracteres de largo como máximo, y NORMAL es cualquier declaración de normal válida. Ver #declare frente a #local" para más información sobre el ámbito de aplicación del identificador.

6.7.2.1  Slope Maps ( Mapa de Pendiente)

Un  slope_map es un modificador del patrón normal que le da al usuario un mayor control sobre la forma exacta de las abolladuras. Cada uno de los tipos de patrones disponibles es de hecho una función matemática que toma cualquier posición  x, y, z  y devuelve un número comprendido entre 0.0 y 1.0, ambos inclusive. Estos números se usan para especificar dónde están los puntos altos y bajos del relieve. El mapa de pendiente nos permite trazar líneas de contorno más allá de la forma. Esto se ilustra mejor con un patrón normal de gradiente. Supongamos que tenemos....

  plane{ z, 0
    pigment{ White }
    normal { gradient x }
  }
Esto nos da un patrón ondulado parecido a pequeñas rampas lineales que suben desde el punto x=0 hasta x=1 y a continuación descienden bruscamente a 0, para repetir de nuevo la rampa de x=1 hasta x=2. Un slope map convierte esta simple rampa lineal en cualquier forma ondulada que nosotros queramos. La sintaxis es la siguiente...
SLOPE_MAP:
    slope_map { SLOPE_MAP_BODY }
SLOPE_MAP_BODY:
    SLOPE_MAP_IDENTIFIER | SLOPE_MAP_ENTRY...
SLOPE_MAP_ENTRY:
    [ Value, <Height, Slope> ]
Nota: Los [] corchetes son parte SLOPE_MAP_ENTRY, no son símbolos que denoten entradas opcionales. Los corchetes encierran cada entrada del slope map.

Puede haber de 2 a 256 entradas en el mapa.

Cada Value es un número decimal comprendido entre 0.0 y 1.0 inclusive y cada <Height,Slope> es un vector de dos componentes tal como <0,1> donde el primer valor representa la aparente altura de la onda y el segundo valor representa la pendiente de la onda en cada punto. La altura debería estar comprendida entre 0.0 y 1.0, pero se puede usar cualquier valor.

El valor de slope es el cambio en altura por unidad de distancia. Por ejemplo, un slope de 0 significa plano, un slope de 1.0 significa una pendiente hacia arriba de 45 grados y de -1 significa pendiente hacia abajo de 45 grados. Teóricamente una pendiente recta tiene pendiente infinita. En la práctica, los valores de slope deben estar en un rango comprendido entre -3.0 y +3.0. Ten en cuenta que esto es sólo una pendiente aparente: la normal no cambia la superficie.

Aquí tenemos por ejemplo cómo hacer una pendiente que va hacia arriba en la primera mitad, y retrocede en la segunda mitad creando una onda triangular con un pico afilado en el centro.

  normal {
    gradient x       // éste es el tipo de patrón
    slope_map {
      [0   <0, 1>]   // empieza abajo y comienza a subir
      [0.5 <1, 1>]   // a mitad de camino subiendo
      [0.5 <1,-1>]   // baja abruptamente
      [1   <0,-1>]   // acaba bajando
    }
  }
La función patrón se evalúa, y el resultado es un valor entre 0.0 y 1.0. La primera entrada dice que en  x=0 la altura aparente es 0 y la pendiente 1. En x=0.5 tenemos una altura de 1 y la pendiente es todavía 1. La tercera entrada especifica que en x=0.5 (realmente en alguna pequeña fracción alrededor de 0.5) tenemos una altura de 1 pero una pendiente de -1. Finalmente en x=1 tenemos una altura de 0 de nuevo, y aún seguimos bajando con pendiente -1.

Aunque en este ejemplo, los puntos se conectan usando líneas rectas, realmente la figura es un spline cúbico. El siguiente ejemplo crea una suave onda sinusoidal.

  normal {
    gradient x          // tipo de patrón
    slope_map {
      [0    <0.5, 1>]   // empieza a subir desde el medio
      [0.25 <1.0, 0>]   // zona plana en la cumbre
      [0.5  <0.5,-1>]   // hacia bajo hasta media altura
      [0.75 <0.0, 0>]   // zona plana en el fondo
      [1    <0.5, 1>]   // acaba en el medio, subiendo
    }
  }
Este ejemplo empieza con una altura de 0.5 y una pendiente hacia arriba de 1. En la cuarta parte del camino, tenemos en la parte superior de la curva una altura de 1 con una pendiente plana de 0. El espacio entre estas dos es una suave curva, puesto que el principio y el final de la pendiente es diferente. En la mitad del recorrido estamos a mitad de altura, con pendiente hacia abajo hasta que toca fondo en los 3/4 del camino. Para finalizar, subimos hasta pendiente 1 de nuevo, para completar el ciclo. Hay muchos ejemplos en el archivo slopemap.pov.

Un mapa de pendiente se puede usar con cualquier patrón, excepto brick, checker, object, hexagon, bumps, dents, ripples, waves, wrinkles y bump_map.

Se puede declarar y usar un identificador de mapa de pendiente. Por ejemplo:

  #declare Fancy_Wave =
    slope_map {       // Ahora dejémonos llevar por la imaginación
      [0.0  <0, 1>]   // Hacemos un pequeño triángulo desde aquí
      [0.2  <1, 1>]   //  abajo
      [0.2  <1,-1>]   //     hasta
      [0.4  <0,-1>]   //       aquí.
      [0.4  <0, 0>]   // Un área plana
      [0.5  <0, 0>]   //   hasta aquí.
      [0.5  <1, 0>]   // Una ola cuadrada dirigiéndose al borde
      [0.6  <1, 0>]   //   siguiendo la arista
      [0.6  <0, 0>]   // Otra vez plano
      [0.7  <0, 0>]   //   hasta aquí.
      [0.7  <0, 3>]   // empieza la onda
      [0.8  <1, 0>]   //   zona plana superior
      [0.9  <0,-3>]   //    acabando aquí
      [0.9  <0, 0>]   //  y plano hasta el final
    }
  object{ My_Object
    pigment { White }
    normal {
      wood
      slope_map { Fancy_Wave }
    }
  }
6.7.2.1.1  Precisión de las normales
Las normales de superficie construidos con patrones que no se diseñaron para su uso con normales (todos, excepto bumps, waves, ripples y wrinkes), usan un mapa de pendiente aunque no lo especifiquen. Para crear una perturbación de la normal a partir de un patrón, POV-Ray muestrea el patrón en cuatro puntos de una pirámide que encierra el punto, para determinar el gradiente del patrón en el centro de la pirámide. La distancia desde esos puntos hasta el centro determina la precisión de la aproximación. Si se usan puntos muy cercanos se provocan errores de precisión de coma flotante. Sin embargo, usando puntos muy lejanos puede provocar la aparición de artefactos y zonas borrosas.

Normalmente se desea usar puntos bastante cercanos. POV-Ray usa actualmente un valor delta o distancia de precisión de 0.02. A veces es necesario decrecer este valor para conseguir mejor precisión al hacer un primer plano de la textura. Otras veces querrás incrementarlo para definir más los ángulos de la normal (por ejemplo, al usar el patrón crackle solid).  Para estos fines se ha creado una nueva propiedad accuracy en las normales de superficie. Sólo tiene efecto si la normal utiliza un mapa de pendiente (explícito o implícito).

Puedes especificar el valor de la precisión (que es la distancia entre los puntos de muestreo para determinar el gradiente del patrón) añadiendo el modificador accuracy <valor de coma flotante> en tu normal. Para todos los patrones el valor por defecto es de 0.02.

6.7.2.2  Mapas de normales y listas de normales

En la mayoría de los casos sólo querrás aplicar un patrón de normal a toda la superficie, aunque también se pueden crear patrones mezclando varias normales con el mapa de normales normal_map. Su sintaxis es idéntica a la de los mapas de pigmento, excepto en que debes especificar una normal para cada entrada del mapa:

NORMAL_MAP:
    normal_map { NORMAL_MAP_BODY }
NORMAL_MAP_BODY:
    NORMAL_MAP_IDENTIFIER | NORMAL_MAP_ENTRY...
NORMAL_MAP_ENTRY:
    [ Value NORMAL_BODY ]
Donde Value es un valor de coma flotante entre 0.0 y 1.0 inclusive, y cada NORMAL_BODY es cualquier cosa que pueda ir dentro de una sentencia normal{...}. La palabra reservada normal y las llaves {} no son obligatorias.

Nota: los corchetes [] son parte de la entrada del mapa (NORMAL_MAP_ENTRY), no son símbolos de notación que indiquen partes opcionales. Estos corchetes deben encerrar cada entrada del mapa de normales.

El mapa puede tener desde 2 hasta 256 entradas.

Por ejemplo:

  normal {
    gradient x       // éste es el tipo de patrón
    normal_map {
      [0.3  bumps scale 2] // bultos
      [0.3  dents]  // otros bultos
      [0.6  dents] // hasta aquí
      [0.9  marble turbulence 1]  // algo de mármol
    }
  }
Cuando la función gradient x devuelve valores desde 0.0 a 0.3, se utiliza el normal bumps. Desde 0.3 a 0.6, se usa el patrón dents, que se va mezclando con marble desde 0.6 hasta 0.9, y de ahí continúa con el patrón de mármol hasta el final.

Los mapas de normales se pueden anidar hasta cualquier nivel de complejidad. Las normales usadas en el mapa pueden tener también mapas de pendiente o mapas de normal, o cualquier otro tipo de normal que desees.

Los mapas de normales también pueden usarse con el tipo de normal average. Véase la sección "Average" para conocer los detalles.

También se puede usar una lista de normales completos con los patrones de bloque como checker, hexagon y brick. Por ejemplo...

  normal {
    checker
    normal { gradient x scale .2 }
    normal { gradient y scale .2 }
  }
Nota: en el caso de los patrones de bloque, el envoltorio normal{} debe obligatoriamente encerrar toda la información de la normal.

No puedes usar mapas de normales ni normales individuales con un mapa de bultos (bump_map). Véase la sección "Mapas de texturas" para conocer un método alternativo para ello.

Puedes declarar y usar identificadores de mapas de normales, pero la única manera de declarar una normal de patrón de bloque es declarar un identificador de normal para toda la normal.

6.7.2.3  Mapas de bultos (bump_map)

Cuando todo lo demás falla, y ninguno de los tipos de normal descritos se ajusta a tus necesidades, puedes usar un mapa de bultos bump_map para envolver el objeto con un mapa de bultos a partir de una imagen 2D.

En lugar de poner los colores de la imagen en la superficie, como hace un image_map, el mapa de bultos perturba la normal de la superficie basándose en el color de la imagen en ese punto. El resultado es similar al efecto de bajorrelieve. Por defecto, el mapa de bultos utiliza el brillo o intensidad del color del píxel, siendo los colores convertidos a escala de grises internamente, antes de calcular la altura. El negro representa las partes bajas, mientras el blanco las más altas. Se pueden utilizar los índices del color en lugar del color mismo: véase las secciones "Use_Index y Use_Color" más abajo.

6.7.2.3.1  Especificando un mapa de bultos
La sintaxis de un bump_map es la siguiente:
BUMP_MAP:
    normal
    {
        bump_map
        {
            BITMAP_TYPE "bitmap.ext"
            [BUMP_MAP_MODS...]
        }
        [NORMAL_MODFIERS...]
    }
BITMAP_TYPE:
    gif | tga | iff | ppm | pgm | png | jpeg | tiff | sys
BUMP_MAP_MOD:
    map_type Type | once | interpolate Type | use_color | 
    use_colour | bump_size Value
Después de la palabra reservada del tipo de mapa de bits (BITMAP_TYPE), debe ir una expresión de cadena que contenga el nombre del archivo a usar como mapa de bultos. Algunos modificadores opcionales, descritos más adelante, pueden ir a continuación de la especificación del archivo.

Nota: antiguas versiones de POV-Ray permitían especificar algunos modificadores delante del tipo de mapa de bits, pero se ha cambiado la sintaxis en favor de la anteriormente descrita.

Nota: el formato sys es específico de la plataforma, siendo BMP para Windows o Pict para Macintosh, por ejemplo.

Los nombres de archivos que se especifican en un mapa de bultos se buscan primero en el directorio de la escena y, si no se encuentran, se buscarán en los directorios especificados en cualquier interruptor +L o cualquier opción Library_Path activa. Esto permite que puedas tener todos los mapas de bultos en una carpeta separada, que especificarás en una opción Library_Path. Véase "Trayectorias de librerías" para conocer más detalles.

Por defecto, el patrón de bultos se mapea en el plano x-y. Éste es proyectado sobre el objeto como si hubiera un proyector de diapositivas en el eje z. El patrón llena totalmente el área cuadrada que va desde x=0, y=0 hasta x=1, y=1 independientemente del tamaño original en píxeles del patrón. Puedes cambiar este comportamiento trasladando, rotando o escalando el patrón para mapearlo sobre la superficie del objeto en la forma deseada.

El nombre del archivo puede ir seguido opcionalmente de uno o más modificadores de mapas de bits. Los modificadores bump_size, use_color y use_index son específicos de los mapas de bultos y se detallan en las siguientes secciones. Véase la sección "Modificadores de mapas de bits" para conocer los modificadores genéricos de mapas de bits map_type, once e interpolate, que se describen en dicha sección.

6.7.2.3.2  Altura del mapa (bump_size)
La altura relativa de los bultos puede escalarse usando el modificador bump_size. El valor que especifica la altura puede ser cualquier número distinto de 0, pero los valores típicos van desde 0.1 hasta 4.0 ó 5.0.
  normal {
    bump_map {
      gif "stuff.gif"
      bump_size 5.0
    }
  }
Originalmente, el modificador bump_size sólo podía usarse dentro de un mapa de bultos, aunque ahora puede usarse con cualquier normal. Se utiliza normalmente para sobrescribir el valor previamente definido. Por ejemplo:
  normal {
    My_Normal   // éste es un identificador de normal previamente definido
    bump_size 2.0
  }
6.7.2.3.3  Use_Index y Use_Color

Normalmente, el mapa de bultos convierte el color del píxel del mapa a un valor de intensidad en una escala de grises, en el rango 0-1, y calcula la perturbación basándose en ese valor. Si especificas el modificador use_index, el mapa de bultos usará en su lugar el índice del color dentro de la paleta. Así, el color número 0 sería el más bajo, mientras que el color número 255 sería el más alto (si la imagen tiene 256 entradas en la paleta). El color real de los píxeles no importa cuando se utiliza el índice. Esta opción sólo está disponible para formatos de imagen que usen paleta de colores. El modificador use_color puede usarse para especificar explícitamente el método basado en el color del píxel. También se puede usar la sintaxis alternativa use_colour. Estos modificadores sólo pueden usarse con la sentencia bump_map.

6.7.2.4  Escalando normales

Cuando se escala una normal, o cuando se escala un objeto después de haberle aplicado una normal, la profundidad del patrón normal se ve afectado por la operación de escalado, lo cual puede no ser siempre lo deseado. Si deseas desactivar el escalado de la profundiad de la normal en una textura, añade el modificador no_bump_scale en la sentencia de la textura o la normal. Este modificador se pasará automáticamente a todas las normales contenidas en esa textura o normal.

Tambien es importante observar que si añades el modificador no_bump_scale a una normal o textura que está contenida en otro patrón (como un texture_map o normal_map), la desactivación del escalado sólo afectará a esta textura o normal.  El escalado de la textura o normal "padre" seguirá afectando a la altura de los bultos, a no ser que se use no_bump_scale en el nivel más alto de la textura o normal.