Texturas mediante fórmulas matemáticas

Texto: Miquel Barceló


Implementación de las texturas

Una vez vista la teoría, ha llegado el momento de llevar las texturas a la práctica. A continuación comentaremos cómo se ha hecho en el programa de ejemplo (RAY.EXE).

Lo primero es leer el fichero gráfico con la textura. Por su simplicidad se ha utilizado el formato TGA sin comprimir, que ya explicamos en un artículo anterior. De hecho, las rutinas que se han utilizado son exactamente las mismas que se utilizaron entonces.

A continuación, se ha modificado la estructura "RT_object" para añadir las propiedades de las texturas: una variable que indica si se utiliza textura, la imagen a utilizar y los factores de escalado (u_scale y v_scale). También nos aseguramos de tener bien definidos los tres ejes del objeto (EjeX, EjeY y EjeZ).

A la hora de implementar las texturas en sí, se ha optado por "unificar" los factores de iluminación ambiente, difusa y especular en uno solo (el "color" del objeto), que se corresponderá con el color que leemos de la textura. Aquí surge el primer problema, pues se había definido estos coeficientes para que variasen entre 0 y 1, mientras que los valores leídos desde la imagen se encuentran 0 y 255. Esto se podría arreglar mediante una división, pero hemos considerado que sería más eficiente ahorrarnos esta operación extra, por lo que al final se ha permitido que las tres componentes del color del objeto varíen entre 0 y 255. Evidentemente, esto se tiene que compensar por otro lado, por lo que las luces (que antes tomaban valores entre 0 y 255) ahora aceptan rangos entre 0 y 1.

"La mayor ventaja de las texturas procedurales es que ocupan poco, pero requieren un cierto tiempo de cálculo"

El siguiente dilema es dónde introducir la rutina que modificará el color del objeto según la textura. Para modificar en lo mínimo la estructura del programa teníamos dos posibilidades: calcular las coordenadas de mapeado cuando se calculan las intersecciones con los objetos o introducirlo en la rutina de calcular el vector normal del objeto (cosa que permite aprovechar algunos cálculos que se hacían). Al final se ha optado por la segunda alternativa, ya que así nos ahorramos de calcular el mapeado de objetos que tal vez sean ocultados por otros. Recordemos que la rutina de calcular el vector normal solo se llamaba cuando ya se había encontrado la intersección con el objeto más cercano al punto de origen del rayo. Como veremos más adelante, en algunos casos muy concretos es más conveniente utilizar la otra opción.

Una vez decidido todo esto, sólo hace falta introducir las fórmulas que hemos explicado para calcular las coordenadas de mapeado y asignar al color del objeto el color del punto de la textura que le corresponde.

Variaciones sobre las texturas

Como dice en el encabezado de este artículo, el tema de las texturas es mucho más complejo que lo que hemos contado hasta ahora. Las posibilidades que ofrece son enormes, tantas que sería imposible recogerlas todas en esta sección. Así que vamos a comentar algunos ejemplos relativamente simples de lo que se puede hacer con ellas.

Otras coordenadas de mapeado

Los tres tipos de coordenadas de mapeado que hemos comentado son las más utilizadas, las que podríamos llamar "estándar", pero en realidad uno se puede inventar las fórmulas que quiera para obtener las coordenadas de mapeado y conseguir efectos interesantes. Las posibilidades son infinitas, sólo hay que ir con cuidado en que las fórmulas utilizadas nos puedan dar un resultado no computable (infinito, por ejemplo) o que no incurramos en una incoherencia matemática (intentar buscar el arcoseno de un número no comprendido dentro del rango [-1,1] o la raíz cuadrada de un número negativo). Esto podría provocar un cuelgue total del programa y se tiene que evitar a toda costa. Veamos un ejemplo sencillo.

Lo usual al calcular las coordenadas de mapeado en un plano es utilizar un sistema de ejes cartesianos, pero también se podrían utilizar coordenadas polares:

En este caso, las ecuaciones de las coordenadas de mapeado quedarían como:

U= atan[(EjeX·(P-Pos))/ (EjeY·(P-Pos))]/2p

V= raiz[(EjeX·(P-Pos))2+(EjeY·(P-Pos))2]

Teniendo en cuenta que estamos en un plano, la coordenada V se puede simplificar como sigue:

V=raiz[(P-Pos)2]

"Se pueden utilizar imágenes como máscaras de objetos, permitiendo obtener figuras complejas a partir de objetos simples"

El resultado será algo similar al efecto "túnel" que explicamos hace tiempo, pero aplicado a un plano del raytracing.

En el CD-ROM se ha incluido el programa VAR1.EXE (lo de VAR viene de variación) con esta modificación, y la escena VAR_1.RAY, específica para este programa, que muestra este efecto.

El resultado de aplicar coordenadas polares en un plano.
En esta escena se ha alineado el origen de coordenadas en el plano para que quede justo debajo de la esfera.

Textura procedural 2D estilo "tablero de ajedrez" aplicada sobre diferentes objetos.
  Siguiente