colores y sombras
colores y sombras
colores y sombras
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
Universidad & Salamanca<br />
Ingeniería Superior Informática.<br />
TEMA 7<br />
Colores y Sombras<br />
Informática Gráfica<br />
José María Corral Martín<br />
Álvaro F. García Sánchez
Colores y <strong>sombras</strong> 2<br />
7.1. Introducción................................................................................................. 4<br />
7.2. ¿Qué es el color? ........................................................................................ 4<br />
7.2.1. La luz como Onda................................................................................. 5<br />
7.2.2. La luz como partícula............................................................................ 6<br />
7.2.3. Dualidad onda - partícula...................................................................... 6<br />
7.3. Percepción del color.................................................................................... 6<br />
7.3.1. Características psicológicas del color................................................... 7<br />
7.4. Dispositivos de visualización ....................................................................... 9<br />
7.4.1. TRC ...................................................................................................... 9<br />
7.4.1.1. Análisis de los tiempos involucrados............................................ 10<br />
7.4.1.2. Exploración de línea..................................................................... 10<br />
7.4.1.3. Sincronizaciones horizontales y verticales ................................... 11<br />
7.4.2. LCD..................................................................................................... 12<br />
7.4.2.1. Funcionamiento............................................................................ 14<br />
7.4.2.2 LCD de texto ................................................................................. 14<br />
7.4.2.3. TFT............................................................................................... 14<br />
7.4.3. Pantalla de plasma ............................................................................. 15<br />
7.5. El monitor vs. El ojo................................................................................... 16<br />
7.6. Profundidad del color ................................................................................ 16<br />
7.6.1. Color de 1-bit ...................................................................................... 16<br />
7.6.2. Color de 4-bits .................................................................................... 17<br />
7.6.3. Color de 8-bits .................................................................................... 18<br />
7.6.4. Color de 24-bits .................................................................................. 18<br />
7.7. Modelos de color ....................................................................................... 19<br />
7.7.1. Modelo de color XYZ .......................................................................... 19<br />
7.7.1.1. Espacio de color CIE.................................................................... 19<br />
7.7.1.1.1. Diagrama de cromaticidad CIE.............................................. 20<br />
7.7.1.1.2. Gama de <strong>colores</strong> ................................................................... 20<br />
7.7.2. El modelo de color RGB ..................................................................... 21<br />
7.7.3. El modelo de color CMY (Cyan, Magenta, Amarillo)........................... 23<br />
7.7.4. El modelo de color YUV...................................................................... 24<br />
7.7.5. El modelo de color YIQ ....................................................................... 24<br />
7.7.6. El modelo de color HSI ....................................................................... 25<br />
7.7.7. El sistema HLS (Hue, Saturation and Luminance).............................. 26<br />
7.7.8. Modelo HSV........................................................................................ 26<br />
7.8. Colores en OpenGL .................................................................................. 28<br />
7.8.1. Utilización de <strong>colores</strong> con OpenGL..................................................... 28<br />
7.8.2. Modelo de color RGBA ....................................................................... 30<br />
7.8.3. Modelo de color indexado................................................................... 36<br />
7.8.4. Modelo de color RGBA vs. Modelo de color Indexado........................ 48<br />
7.8.5. Ocultaciones ....................................................................................... 49<br />
7.8.5.1. Algoritmo de las caras de detrás.................................................. 49<br />
7.8.5.2 Algoritmo del Z-buffer.................................................................... 50<br />
7.8.5.3. Combinando ambos algoritmos.................................................... 51<br />
7.8.6. El color de los materiales.................................................................... 52<br />
7.9. Sombras.................................................................................................... 58<br />
7.9.1 Efecto falloff (Distance falloff) .............................................................. 60<br />
7.9.2 Sombreado .......................................................................................... 61<br />
7.9.3 Tipos de sombreado ............................................................................ 62<br />
7.9.3.1 Sombreado plano (Flat Shading)................................................... 62
Colores y <strong>sombras</strong> 3<br />
7.9.3.2 Sombreado de Gouraud................................................................ 63<br />
7.9.3.3 Sombreado de Phong ................................................................... 65<br />
7.9.3.4 Sombreado Blinn–Phong .............................................................. 67<br />
7.9.4 Sombreado en OpenGL....................................................................... 68<br />
7.9.4.1 Sombreado Plano (Flat) ................................................................ 68<br />
7.9.4.2 Sombreado Interpolativo y Gouraud.............................................. 70<br />
7.9.4.3 Stencil Buffer................................................................................. 71<br />
7.9.4.4 Buffer de Profundidad o Z buffer ................................................... 75<br />
7.9.5. Volúmenes de <strong>sombras</strong> ...................................................................... 76<br />
7.9.5.1 Paso de profundidad (Depth pass)................................................ 78<br />
7.9.5.2 Error de Profundidad (Depth fail)................................................... 78<br />
7.9.7.3 OR exclusivo ................................................................................ 78<br />
7.10 Fusión (Dithering)..................................................................................... 78<br />
7.11. Creación de Paletas de Ventana............................................................. 80<br />
7.11.1 Arbitraje de paletas............................................................................ 80<br />
7.11.2. Creación de una paleta..................................................................... 82<br />
7.11.3 Estructura de la paleta....................................................................... 82<br />
7.11.4 Destrucción de una paleta. ............................................................... 85<br />
7.12 Conclusión................................................................................................ 87<br />
7.13 Otras funciones para luces y <strong>sombras</strong> ..................................................... 87<br />
glAccum........................................................................................................ 87<br />
glColorMask.................................................................................................. 88<br />
glDrawBuffer................................................................................................. 88<br />
glFog............................................................................................................. 89<br />
glIndexMask.................................................................................................. 90<br />
glIsEnabled................................................................................................... 90<br />
glLogicOp...................................................................................................... 90<br />
glPolygonMode ............................................................................................. 91<br />
7.14 Bibliografia................................................................................................ 92<br />
7.15 Enlaces de interés.................................................................................... 96
Colores y <strong>sombras</strong> 4<br />
7.1. Introducción<br />
Los despliegues realistas de objetos se obtienen generando<br />
proyecciones en perspectiva con superficies ocultas eliminadas y después<br />
aplicando modelos de sombreado y color a las superficies visibles. Un modelo<br />
de sombreado se utiliza para calcular la intensidad de luz que debe observarse<br />
cuando se visualiza una superficie. Estos cálculos de intensidad se basan en<br />
las propiedades ópticas de las superficies, las posiciones relativas de las<br />
superficies y su orientación con respecto a las fuentes de luz.<br />
En este tema se introducirán los conceptos de color y sombreado,<br />
algunos de los modelos más utilizados actualmente para su representación<br />
para posteriormente mostrar todo lo necesario para la utilización del color y del<br />
sombreado en escenas con OpenGL con multitud de ejemplos sencillos.<br />
7.2. ¿Qué es el color?<br />
El color de un objeto percibido por la vista se debe a las propiedades<br />
inherentes al mismo, de reflejar, seleccionar y absorber determinados rayos de<br />
los que integran la luz blanca. La luz solar es un fenómeno vibratorio de<br />
innumerables variaciones en cuanto a longitud de onda. Al pasar la luz por un<br />
prisma se ve que está compuesta por un sinnúmero de <strong>colores</strong>; los<br />
fundamentales son: violeta (que corresponde a la vibración más pequeña y<br />
simple), añil, azul, verde, amarilla, naranja y rojo. El color negro resulta de la<br />
ausencia de toda impresión luminosa.<br />
Diccionario Enciclopédico Abreviado Espasa-Calpe.S.A<br />
Según la definición el color de un objeto se debe a la combinación de las<br />
distintas longitudes de onda que el objeto refleja, así por ejemplo un objeto rojo<br />
sería aquel que absorbiese todos los rayos que componen la luz blanca menos<br />
el de menor longitud de onda (el rojo).<br />
El color en las artes es el medio más valioso para que una obra<br />
transmita las mismas sensaciones que el artista experimenta frente a la escena<br />
o motivo original; utilizando el color adecuadamente y con conocimiento de su<br />
naturaleza y efectos será posible expresar la alegría o tristeza, la luminosidad u<br />
oscuridad, tranquilidad o la exaltación, etc.<br />
El color en la informática gráfica se desenvuelve de la misma manera<br />
que en el arte de la pintura, aunque en su actuación va mucho mas allá porque<br />
su fin es especialmente especifico, puede servir para favorecer, destacar,<br />
disimular y aún ocultar, para crear una sensación excitante o tranquila, para<br />
denotar temperatura, tamaño, profundidad o peso y como la música, puede ser<br />
utilizada deliberadamente para despertar un sentimiento.<br />
El color tiene su propia técnica y está sometido a ciertas leyes,<br />
conociéndolas será posible dominar el arte de la armonización, conocer los<br />
medios útiles que sirven para evitar la monotonía en una combinación
Colores y <strong>sombras</strong> 5<br />
cromática, estimular la facultad del gusto selectivo y afirmar la sensibilidad,<br />
desconociéndolas es posible trastornar y anular las percepciones deseadas.<br />
7.2.1. La luz como Onda<br />
Lo que percibimos como color es una banda de frecuencias del espectro<br />
electromagnético, otras bandas de frecuencias incluidas en el espectro son las<br />
ondas de radio, infrarrojos, etc. Cada<br />
frecuencia contenida en el espectro<br />
visible se corresponde con un color<br />
distinto.<br />
El espectro visible abarca<br />
desde los 4.3*10 14 Hz (rojo) hasta los<br />
7.5 * 10 14 Figura 1 - Estructura de una onda<br />
Hz (violeta). En este<br />
intervalo de frecuencias el ojo humano distingue aproximadamente unos<br />
400.000 <strong>colores</strong> diferentes (esta gama se extiende desde el rojo pasando por el<br />
anaranjado y amarillo en el extremo de las bajas frecuencias hasta los azules y<br />
violetas de las altas frecuencias).<br />
Figura 2 - Espectro Electromagnético<br />
Lo que se designa como luz blanca es la impresión creada por el<br />
conjunto de radiaciones que son visibles por nuestro ojo; la luz blanca cuando<br />
es descompuesta produce el fenómeno de arco iris, estos son los que<br />
llamamos <strong>colores</strong>, el conjunto de estos, o franja continua de longitudes de onda<br />
creada por la luz al descomponerse, constituye el espectro.<br />
Describimos los <strong>colores</strong> en función de su frecuencia o de su longitud de<br />
onda dado que la luz es una onda electromagnética (C = λ*f). La longitud de<br />
onda en el espectro visible varía desde los 720 nanómetros del rojo a los 390<br />
nanómetros del violeta.<br />
Cualquier fuente de luz (sol, foco de luz ...) emite todas las<br />
frecuencias en el intervalo visible para producir la luz blanca.
Colores y <strong>sombras</strong> 6<br />
Un objeto sobre el que incide luz blanca absorberá algunas frecuencias<br />
y reflejará otras. La combinación de éstas últimas determinará el color del<br />
objeto. Describimos el objeto como violeta si predominan las altas frecuencias<br />
en la luz reflejada, es decir, la luz tiene una frecuencia dominante o longitud<br />
de onda dominante en el extremo violeta del espectro. La frecuencia<br />
dominante se denomina color o matiz de la luz.<br />
7.2.2. La luz como partícula<br />
La luz puede ser descrita como una onda oscilante, pero también puede<br />
ser considerada como un haz de partículas viajando a altas velocidades (3,0 x<br />
10 8 m/s). Los haces de luz están compuestos por partículas denominadas<br />
fotones.<br />
A nivel físico, los llamados <strong>colores</strong> compuestos, están hechos de<br />
diversas cantidades de de <strong>colores</strong> “puros” encontrados en el espectro.<br />
Al iluminar cualquier objeto dado con una fuente de luz es golpeado por<br />
“billones y billones” de fotones, o pequeñas partículas de luz, algunos de ellos<br />
serán absorbidos y otros reflejados. La reflexión de la luz sobre un objeto<br />
depende del tipo, distribución y cantidad de átomos que contenga.<br />
Cada uno de esos fotones es también una onda, con su correspondiente<br />
longitud de onda y por tanto un color específico en el espectro.<br />
7.2.3. Dualidad onda - partícula<br />
La frecuencia (υ) de la teoría de las ondas se puede relacionar con la<br />
teoría del fotón (E) de la teoría de la partícula a través de la ecuación de<br />
Planck:<br />
E = h υ<br />
donde h es la constante de planck (factor de proporcionalidad = 6,63 x<br />
10 -34 (Js)).<br />
La frecuencia (υ) de una determinada onda es inversamente<br />
proporcional a su longitud de onda.<br />
7.3. Percepción del color<br />
El color es la impresión producida al incidir en la retina los rayos<br />
luminosos difundidos o reflejados por los cuerpos. El ojo humano es capaz de<br />
captar las variaciones de la longitud de onda del espectro electromagnético<br />
visualizándolo como diferentes <strong>colores</strong>, desde el violeta hasta el rojo.
Colores y <strong>sombras</strong> 7<br />
Este fenómeno se debe al aspecto físico de la radiación, el ojo humano<br />
que actúa como sensor y el cerebro que es capaz de percibir, diferenciar e<br />
interpretar las imágenes que<br />
conforman este espectro.<br />
La retina del ojo, a<br />
través de una estructura<br />
formada por unos elementos<br />
denominados bastones<br />
(concentrados en los lados de<br />
la retina) y conos<br />
(concentrados en el centro),<br />
tiene la capacidad para<br />
discernir los <strong>colores</strong>, la<br />
forma, los detalles y la<br />
posición de los objetos.<br />
Los conos están especializados en la visión del color, así unos ven<br />
solamente el azul y el violeta, otros el verde y el amarillo y otros el rojo y el<br />
naranja. Además, es capaz de adaptarse a las diferentes cantidades de luz y al<br />
brillo de las escenas y discernir e identificar los diferentes <strong>colores</strong>.<br />
Los bastones al contrario que los conos requieren muy poca luz, lo que<br />
los hace muy adecuados para la visión nocturna, sin embargo, no son capaces<br />
de discernir los <strong>colores</strong>.<br />
Los fotones penetran en nuestro ojo enfocándose en la retina, ésta actúa<br />
como una película fotográfica. Las células de la retina son excitadas por los<br />
fotones, lo cual provoca un estímulo que es transmitido por las neuronas al<br />
cerebro.<br />
El cerebro interpreta esta información como luz y color. El nivel de<br />
excitación es proporcional al número de fotones que llegan a la retina.<br />
7.3.1. Características psicológicas del color<br />
Figura 3 - Sección de un ojo humano<br />
Necesitamos otras propiedades, además de la frecuencia, para<br />
caracterizar nuestra percepción de la luz.<br />
La cromaticidad hace referencia al conjunto de variables del color que<br />
se utilizan normalmente para describir las diferentes propiedades de una fuente<br />
de luz.<br />
- El matiz es el croma de un color y depende de la longitud de onda<br />
dominante. Es la cualidad que permite clasificar a los <strong>colores</strong> como<br />
amarillo, rojo, violeta, etc. El matiz se mide de acuerdo con la proximidad<br />
que tiene un color con relación a otro que se halle próximo en el círculo<br />
cromático; por ejemplo: verde amarillento, naranja rojizo, azul violáceo,<br />
etcétera
Colores y <strong>sombras</strong> 8<br />
Figura 4 – Matiz<br />
- Valor o luminosidad indica las luminancias de un color; es decir, el<br />
grado de claridad u oscuridad que posee como cualidad intrínseca.<br />
Dentro del círculo cromático, el amarillo es el color de mayor luminancia<br />
y el violeta el de menor. Independientemente de los valores propios de<br />
los <strong>colores</strong>, éstos se pueden alterar mediante la adición de blanco que<br />
lleva el color a claves o valores de luminancia más altos, o de negro que<br />
los disminuye.<br />
- El tono es la resultante de la mezcla de los <strong>colores</strong> con blanco o<br />
negro y tiene referencia de valor y de matiz. Por ejemplo, el amarillo<br />
mezclado con negro modifica su matiz hacia el verde y se oscurece.<br />
Figura 5 - Tono<br />
- La saturación se refiere al grado de pureza de un color y se mide<br />
con relación al gris. Los <strong>colores</strong> muy saturados poseen mayor grado de<br />
pureza y se presentan con más intensidad luminosa en relación con su<br />
valor. Los <strong>colores</strong> con menor saturación se muestran más agrisados,<br />
con mayor cantidad de impurezas y con menor intensidad luminosa.<br />
Figura 6 - Saturación<br />
Se utilizan modelos de color con combinaciones de luz en términos de<br />
frecuencia dominante haciendo uso de 3 <strong>colores</strong> para obtener una gama amplia<br />
de <strong>colores</strong>. Esto se suele denominar gama de color del modelo. Los tres<br />
<strong>colores</strong> utilizados en el modelo se denominan <strong>colores</strong> primarios.<br />
Ningún conjunto de <strong>colores</strong> primarios describe todas las frecuencias del<br />
espectro visible. Agregando <strong>colores</strong> primarios aumentamos el número de<br />
posibles <strong>colores</strong> pero harían falta un número infinito de <strong>colores</strong> para poder<br />
representar todos los posibles <strong>colores</strong>. Para muchos fines con los tres <strong>colores</strong>
Colores y <strong>sombras</strong> 9<br />
primarios es suficiente, sino se puede representar un color concreto se pueden<br />
utilizar métodos extendidos.<br />
Cuando se proyectan juntas luces rojas, verdes y azules, obtenemos el<br />
blanco.<br />
Los <strong>colores</strong> secundarios se obtienen de la mezcla de los <strong>colores</strong><br />
primarios.<br />
Figura 7 - Colores Primarios<br />
7.4. Dispositivos de visualización<br />
7.4.1. TRC<br />
Figura 8 - Colores Secundarios<br />
Un monitor para mostrar una imagen utiliza un tubo de rayos catódicos<br />
(TRC) cuyo frente se "ilumina" con un cañón de electrones localizado en la<br />
parte posterior del tubo, el cual dispara un haz de electrones muy concentrado<br />
que al impactar con el material sensible del frente del tubo lo excita iluminando<br />
los puntos que componen la imagen.<br />
La forma en<br />
que el haz "barre" la<br />
pantalla para<br />
desplegar una<br />
imagen se denomina<br />
deflexión. Ésta se<br />
realiza excitando<br />
convenientemente un<br />
juego de bobinas<br />
(def. Horizontal y def.<br />
Vertical) que están<br />
colocadas de forma<br />
muy precisa en el<br />
cuello del TRC. El<br />
campo magnético que<br />
Figura 9 - Tubo de rayos catódicos<br />
generan al ser<br />
excitadas desvía el haz para conseguir que apunten al frente del tubo a la<br />
posición deseada.<br />
Un monitor no forma la imagen, ésta se procesa y forma en la placa de<br />
video del ordenador. Después se almacena en la memoria de video y se envía<br />
esta información (señales de video y sincronización) al monitor. Éste la toma y<br />
la ordena para poder mostrarla, para ello se utilizan dos señales de
Colores y <strong>sombras</strong> 10<br />
sincronización de eventos consiguiendo que la imagen se muestre de forma<br />
coherente y ordenada. La señales de sincronismo horizontal y vertical se<br />
generan en la placa de video y sus características dependen del modo de video<br />
elegido (resolución).<br />
7.4.1.1. Análisis de los tiempos involucrados<br />
Tiempo activo horizontal<br />
Para desplegar una imagen, el haz apunta a la esquina superiorizquierda<br />
de la pantalla y se mueve horizontalmente hasta el derecho de la<br />
misma. El tiempo que emplea el haz para desplazarse del lado izquierdo al<br />
derecho se denomina "tiempo activo horizontal".<br />
Retardo Horizontal o tiempo de borrado<br />
Es el tiempo utilizado en el regreso del haz a la izquierda de la pantalla<br />
cuando éste ha alcanzado el lado derecho de la misma.<br />
Tiempo Total horizontal<br />
El haz cumple un ciclo horizontal completo cuando, empezando en el<br />
borde izquierdo de la pantalla va hacia el lado derecho, y regresa atrás de<br />
nuevo. Este “tiempo total horizontal” se obtiene sumando los tiempos de<br />
Retardo Horizontal y Activo Horizontal<br />
Velocidad de Refresco Horizontal<br />
Dependiendo de la velocidad con la que el monitor puede trabajar,<br />
pueden ocurrir cada segundo unos 20.000 a 80.000 ciclos horizontales . El<br />
número de ciclos horizontales por segundo es denominado Refresco Horizontal<br />
y normalmente está en KHz.<br />
Tiempo Total Horizontal<br />
Cuando trabajamos con la velocidad horizontal de un monitor<br />
generalmente utilizamos el Refresco Horizontal. Sin embargo, al tratar con los<br />
ciclos horizontales de un monitor específico, normalmente utilizaremos el<br />
tiempo real de cada ciclo horizontal. El ciclo horizontal de un monitor es la<br />
suma de los tiempos real horizontal y tiempo de borrado o retrazo.<br />
7.4.1.2. Exploración de línea<br />
Para desplegar una imagen completa no sólo hay que desplegar el haz<br />
“de izquierda a derecha” de la pantalla, es decir, horizontalmente, sino también<br />
“de arriba abajo”, es decir, verticalmente. Cada recorrido horizontal del haz se<br />
llama exploración de línea "scanline”.
Colores y <strong>sombras</strong> 11<br />
Tiempo activo vertical<br />
Es el tiempo total que necesita el monitor para desplegar todas las líneas<br />
horizontales. Dependiendo de la resolución vertical de un monitor, una imagen<br />
en la pantalla puede componerse de 320 a 1600 líneas horizontales.<br />
Retrazo o borrado vertical o tiempo de retardo<br />
Es el tiempo que necesita el haz para una vez que ha alcanzado la<br />
esquina inferior derecha de la pantalla retornar rápidamente a la parte superior<br />
izquierda de la misma.<br />
Tiempo Total Vertical<br />
Es el tiempo que utiliza el haz para "barrer" desde la parte superior hasta<br />
la inferior de la pantalla y volver a la esquina superior-izquierda.<br />
Tiempo Total Vertical = Tiempo activo Vertical + Tiempo de Retrazo<br />
Vertical<br />
Hz.<br />
Velocidad de Refresco Vertical o refresco vertical de un monitor<br />
Es el número de ciclos verticales completados por segundo medido en<br />
Raster: Es el ciclo completo de formación de un cuadro de imagen<br />
7.4.1.3. Sincronizaciones horizontales y verticales<br />
Señal de sincronización vertical<br />
Utilizando esta señal el monitor controla el regreso del haz desde la<br />
esquina inferior-derecha a la esquina superior-izquierda<br />
Señal de sincronización Horizontal<br />
Con esta señal el monitor controla el regreso del haz desde el lado<br />
derecho al izquierdo<br />
Pulso de Sincronización horizontal y posición de la imagen<br />
Durante el tiempo de retardo horizontal el monitor recibe el pulso de<br />
sincronización horizontal. El tiempo entre el extremo del tiempo activo<br />
horizontal y la salida del pulso de la sincronización horizontal se denomina el<br />
Porche Delantero Horizontal.<br />
El tiempo durante el cual el pulso de sincronización horizontal<br />
permanece activo, se denomina Ancho de Sincronización Horizontal.<br />
Después de recibir el pulso de la sincronización horizontal, el monitor<br />
devuelve el haz al lado izquierdo de la pantalla. El periodo de tiempo entre el<br />
extremo del pulso de la Sincronización Horizontal y el comienzo del próximo<br />
tiempo activo horizontal es denominado Porche Trasero Horizontal.
Colores y <strong>sombras</strong> 12<br />
Modificando la posición del pulso de la sincronización horizontal respecto<br />
al tiempo de retrazo horizontal se ajusta la posición de la imagen en la pantalla<br />
a la derecha o izquierda.<br />
Figura 10 - Pulso de sincronización horizontal<br />
Pulso de Sincronización vertical y posición de imagen<br />
Durante el tiempo de retrazo vertical el monitor recibe el pulso de la<br />
sincronización vertical. El tiempo entre el extremo del tiempo activo vertical y la<br />
salida del pulso de la sincronización vertical se llama el Porche Delantero<br />
Vertical.<br />
El tiempo durante el cual el pulso de la sincronización vertical<br />
permanece activo se denomina la Anchura de la Sincronización Vertical.<br />
Después de recibir el pulso de la sincronización vertical, el monitor devuelve el<br />
haz al tope de la pantalla.<br />
El periodo de tiempo entre el extremo del pulso de la Sincronización<br />
Vertical y la salida del próximo tiempo activo vertical es el Porche Trasero<br />
Vertical.<br />
Modificando la posición del pulso de la sincronización vertical respecto al<br />
tiempo de retardo vertical se ajusta la situación de la imagen en la pantalla<br />
arriba o abajo.<br />
7.4.2. LCD<br />
LCD (Liquid Crystal Display) son las siglas en inglés de Pantalla de<br />
Cristal Líquido, dispositivo inventado por Jack Janning, quien fue empleado de<br />
NCR.<br />
Se trata de un sistema eléctrico de presentación de datos formado por 2<br />
capas conductoras transparentes y en medio un material especial cristalino<br />
(cristal líquido) que tienen la capacidad de orientar la luz a su paso.
Colores y <strong>sombras</strong> 13<br />
Cuando la<br />
corriente circula<br />
entre los<br />
electrodos<br />
transparentes con<br />
la forma a<br />
representar (por<br />
ejemplo, un<br />
segmento de un<br />
número) el<br />
material cristalino<br />
se reorienta<br />
alterando su<br />
transparencia.<br />
Figura 11 - LCD<br />
El material base de un LCD lo constituye el cristal líquido, el cual exhibe<br />
un comportamiento similar al de los líquidos y unas propiedades físicas<br />
anisotrópicas similares a las de los sólidos cristalinos. Las moléculas de cristal<br />
líquido poseen una forma alargada y son más o menos paralelas entre sí en la<br />
fase cristalina. Según la disposición molecular y su ordenamiento, se clasifican<br />
en tres tipos: nemáticos, esméticos y colestéricos. La mayoría de cristales<br />
responden con facilidad a los campos eléctricos, exhibiendo distintas<br />
propiedades ópticas en presencia o ausencia del campo. El tipo más común de<br />
visualizador LCD es, con mucho, el denominado nemático de torsión, término<br />
que indica que sus moléculas en su estado desactivado presentan una<br />
disposición en espiral. La polarización o no de la luz que circula por el interior<br />
de la estructura, mediante la aplicación o no de un campo eléctrico exterior,<br />
permite la activación de una serie de segmentos transparentes, los cuales<br />
rodean al cristal líquido. Según sus características ópticas, pueden también<br />
clasificarse como: reflectivos, transmisivos y transreflectivos.<br />
Las pantallas LCD se encuentran en multitud de dispositivos industriales<br />
y de consumo: máquinas expendedoras, electrodomésticos, equipos de<br />
telecomunicaciones, computadoras, etc. Todos estos dispositivos utilizan<br />
pantallas fabricadas por terceros de una manera más o menos estandarizada.<br />
Cada LCD se compone de una pequeña placa integrada que consta de:<br />
• La propia pantalla LCD.<br />
• Un microchip controlador.<br />
• Una pequeña memoria que contiene una tabla de caracteres.<br />
• Un interfaz de contactos eléctricos, para conexión externa.<br />
• Opcionalmente, una luz trasera para iluminar la pantalla.<br />
El controlador simplifica el uso del LCD proporcionando una serie de<br />
funciones básicas que se invocan mediante el interfaz eléctrico, destacando:<br />
• La escritura de caracteres en la pantalla.<br />
• El posicionado de un cursor parpadeante, si se desea.<br />
• El desplazamiento horizontal de los caracteres de la pantalla<br />
(scrolling).
Colores y <strong>sombras</strong> 14<br />
La memoria implementa un mapa de bits para cada carácter de un juego<br />
de caracteres, es decir, cada octeto de esta memoria describe los puntitos o<br />
píxel que deben iluminarse para representar un carácter en la pantalla.<br />
Generalmente, se pueden definir caracteres a medida modificando el contenido<br />
de esta memoria. Así, es posible mostrar símbolos que no están originalmente<br />
contemplados en el juego de caracteres.<br />
El interfaz de contactos eléctricos suele ser de tipo paralelo, donde<br />
varias señales eléctricas simultáneas indican la función que debe ejecutar el<br />
controlador junto con sus parámetros. Por tanto, se requiere cierta<br />
sincronización entre estas señales eléctricas.<br />
La luz trasera facilita la lectura de la pantalla LCD en cualquier condición<br />
de iluminación ambiental.<br />
Existen dos tipos de pantallas LCD en el mercado: pantallas de texto y<br />
pantallas gráficas.<br />
7.4.2.1. Funcionamiento<br />
El funcionamiento de estas pantallas se fundamenta en sustancias que<br />
comparten las propiedades de sólidos y líquidos a la vez. Cuando un rayo de<br />
luz atraviesa una partícula de estas sustancias tiene necesariamente que<br />
seguir el espacio vacío que hay entre sus moléculas como lo haría atravesar un<br />
cristal sólido pero a cada una de estas partículas se le puede aplicar una<br />
corriente eléctrica que cambie su polarización dejando pasar a la luz o no.<br />
Una pantalla LCD esta formada por 2 filtros polarizados colocados<br />
perpendicularmente de manera que al aplicar una corriente eléctrica al segundo<br />
de ellos dejaremos pasar o no la luz que ha atravesado el primero de ellos.<br />
Para conseguir el color es necesario aplicar tres filtros más para cada uno de<br />
los <strong>colores</strong> básicos rojo, verde y azul y para la reproducción de varias<br />
tonalidades de color se deben aplicar diferentes niveles de brillo intermedios<br />
entre luz y no luz lo, cual consigue con variaciones en el voltaje que se aplicaba<br />
los filtros.<br />
7.4.2.2 LCD de texto<br />
Los LCD de texto son los más baratos y simples de utilizar. Solamente<br />
permiten visualizar mensajes cortos de texto. Existen algunos modelos<br />
estandarizados en la industria, en función de su tamaño medido en número de<br />
líneas y columnas de texto. Existen modelos de una, dos y cuatro filas<br />
únicamente. El número de columnas típico es de ocho, dieciséis, veinte y<br />
cuarenta caracteres.<br />
7.4.2.3. TFT<br />
TFT o Thin Film Transistor (Transistor de Película Fina) es un tipo<br />
especial de transistor de efecto campo construido depositando finas películas<br />
sobre contactos metálicos, capa activa semiconductora y capa dieléctrica.
Colores y <strong>sombras</strong> 15<br />
La aplicación más conocida de los TFT son las pantallas de visualización<br />
planas de LCD, en las cuales cada píxel se controla mediante uno a cuatro<br />
transistores. La tecnología de TFT proporciona la mejor resolución de todas las<br />
técnicas flat-panel, pero es también la más costosa. Las pantallas de TFT a<br />
veces se llaman LCDs de matriz activa.<br />
Opera de forma individual con cada píxel, es decir, es direccionamiento<br />
directo o de matriz activa. esto se consigue mediante una delgada capa de<br />
transistores que controlan de forma individual cada píxel obteniendo mejores<br />
tiempos de respuesta al no ser necesario el barrido completo de la pantalla ya<br />
que el tiempo de de excitación de un píxel es menor que el tiempo de barrido<br />
de la pantalla consiguiendo imágenes más nítidas y sin parpadeos.<br />
7.4.3. Pantalla de plasma<br />
Una pantalla de plasma es una pantalla plana en la cual la luz se crea<br />
por la excitación de sustancias<br />
fosforecentes mediante una<br />
descarga de plasma entre dos<br />
pantallas planas de vidrio. La<br />
descarga de gas no contiene<br />
mercurio (como en la luz de fondo<br />
de las pantallas de LCD); una<br />
mezcla de gases nobles (neón y<br />
xenón) es utilizada en su lugar. Esta<br />
mezcla de gas es inerte y totalmente<br />
inofensiva.<br />
La pantalla de plasma fue<br />
inventada en la Universidad de Illinois<br />
en Urbana-Champaign por Donald L.<br />
Bitzer y H. Gene Slottow en 1964 para<br />
Figura 12 – Funcionamiento de una<br />
pantalla de plasma<br />
el sistema informático PLATO. Los paneles originales eran monocromáticos.<br />
Desde 1975, Larry Weber, de la Universidad de Illinois en Urbana-<br />
Champaign, intentó crear una pantalla de plasma de color, consiguiéndolo<br />
finalmente en 1995.<br />
El mayor brillo y ángulo de visión de las pantallas de plasma actuales ha<br />
provocado que estas pantallas sean cada vez más populares.<br />
El plasma consiste en una sustancia eléctrica neutra con una lata de<br />
ionización compuesta por iones, electrones y partículas neutras. Básicamente<br />
el plasma es un mar de electrones e iones que conduce de manera excelente<br />
la electricidad. Si se aplica suficiente calor los electrones se separan de sus<br />
núcleos.
Colores y <strong>sombras</strong> 16<br />
Una pantalla de plasma se compone de una matriz de celdas conocidas<br />
como píxeles, que se componen a su vez de tres sub-píxeles, que<br />
corresponden a los <strong>colores</strong> rojo, verde y azul.<br />
El gas en estado de plasma reacciona con el fósforo de cada sub-píxel<br />
para producir luz coloreada (roja, verde o azul). Estos fósforos son los mismos<br />
que se utilizan en los tubos de rayos catódicos de los televisores y monitores<br />
convencionales. Cada sub-píxel está controlado individualmente por un<br />
procesador y se pueden producir más de 16 millones de <strong>colores</strong> diferentes.<br />
Imágenes perfectas en un display de profundidad mínima.<br />
7.5. El monitor vs. El ojo<br />
El ojo no es como una cámara de televisión, la cámara produce una<br />
imagen como la superposición de una serie de puntos brillantes y oscuros<br />
obtenidos cuando los electrones acelerados por el cañón del televisor a lo largo<br />
del tubo que se halla en el interior impactan contra una pantalla de material<br />
fluorescente: este material absorbe la energía del choque, se excita y<br />
posteriormente se des-excita emitiendo luz... ¡el puntito brillante que vemos!<br />
Para una televisión en color, esos puntos brillantes corresponden cada<br />
uno a un color primario, emitido en función de la energía que ha cedido el<br />
electrón acelerado en el choque. Además existe una conexión uno-a-uno entre<br />
cada punto del objeto y su imagen final, la cual se mantiene a través del<br />
proceso por el que la cámara lo produce. Por lo tanto se puede interrumpir el<br />
proceso en cualquiera de sus fases y se puede establecer que esa señal<br />
electrónica proviene de ese punto en particular del objeto.<br />
En el cerebro, ¡las cosas son muy distintas! Una parte de la corteza<br />
visual que es la que procesa la señal, puede conectarse a muchas partes<br />
diferentes de la retina de modo que el proceso de ver se hace muy complejo.<br />
Se cree que ciertas partes de la corteza son muy buenas en el reconocimiento<br />
de líneas horizontales y otras lo son en el reconocimiento de las verticales,<br />
otras reconocen mejor el contorno de los objetos, etc... Esta compleja<br />
arquitectura es la que hace que el cerebro sea mucho mejor en procesar la<br />
información visual que incluso el más moderno de los ordenadores, el cual,<br />
como una cámara de televisión, trabaja la información sobre la base de uno-auno<br />
(1:1).<br />
7.6. Profundidad del color<br />
La calidad de la imagen se puede mejorar incrementando la resolución<br />
de la pantalla, el número de píxeles del dibujo o también incrementando el<br />
número de <strong>colores</strong> disponibles.<br />
7.6.1. Color de 1-bit<br />
No existe un nombre que se utilice habitualmente para denominar este<br />
simple modo de color. La denominación de “blanco y negro” ha sido utilizada
Colores y <strong>sombras</strong> 17<br />
incorrectamente para referirnos a la “escala de grises” cuando en realidad sólo<br />
se pueden representar 2 <strong>colores</strong>.<br />
Este modo de video permite 2 <strong>colores</strong> ya que se utiliza 1 bit dedicado a<br />
la información de color por cada píxel (2 1 ).<br />
Cuando hablamos de color de 1 bit nos<br />
referimos a blanco o negro; algunas veces los 2 <strong>colores</strong><br />
no son blanco y negro, hubo terminales que utilizaron 2<br />
tipos de verdes: claro y oscuro. El siguiente dibujo es<br />
un ejemplo de una imagen de 1 bit de profundidad, sólo<br />
utiliza el blanco y el negro.<br />
El color de 1-bit se utilizó en dispositivos<br />
de texto, hubo excepciones, los Macintosh (que<br />
no tenían este modo de texto) y los originales IBM<br />
MGA (Monochome Graphics Adapter, que tenía<br />
un modo grafico adicional al modo de texto).<br />
7.6.2. Color de 4-bits<br />
Fue utilizado por los dispositivos IBM EGA (Enhanced Graphics<br />
Adapter), también por el Commodore 64 y 128 y otros muchos.<br />
BLACK DARK GREY BLUE LIGHT BLUE<br />
GREEN LIGHT GREEN CYAN LIGHT CYAN<br />
RED LIGHT RED PURPLE LIGHT PURPLE<br />
YELLOW LIGHT YELLOW LIGHT GREY<br />
Figura 13 - Imagen con<br />
1 bit de profundidad<br />
WHITE<br />
Este modo de video permite 16 <strong>colores</strong> ya que se utilizan 4 bits<br />
dedicados a la información de color por cada píxel (2 4 )<br />
El Commodore Amiga e IBM VGA (Vídeo Graphics Adapter) permitían<br />
indexación. Sólo se podía disponer de 16 <strong>colores</strong> de manera simultánea, pero<br />
los 16 <strong>colores</strong> se pueden elegir de una amplia paleta y cada paleta puede<br />
redefinir sus <strong>colores</strong>. Así un programa puede utilizar una escala de 16 grises,<br />
los 16 <strong>colores</strong> originales de EGA, o elegir cualquier combinación de <strong>colores</strong> de<br />
la amplia paleta de <strong>colores</strong> disponible. La única restricción es la utilización de<br />
16 <strong>colores</strong> de forma simultánea.
Colores y <strong>sombras</strong> 18<br />
7.6.3. Color de 8-bits<br />
Este modo de video permite 256 <strong>colores</strong><br />
en pantalla ya que se utilizan 8 bits dedicados a<br />
la información de color por cada píxel (2 8 ). Con<br />
estos bits se hace referencia al índice de la<br />
paleta de color. La paleta nos permite<br />
seleccionar entre 16 millones de <strong>colores</strong>. Cada<br />
color de la paleta se selecciona especificando 8<br />
bits para cada intensidad de rojo, verde y azul<br />
(la intensidad de cada componente puede tener<br />
una valor entre 0 y 255)<br />
Este modo de color combinado con la fusión<br />
permite obtener resultados aceptables para<br />
ciertas aplicaciones. También se pueden utilizar<br />
los 8 bits para imágenes de un tono continuo en<br />
blanco y negro con 256 matices de color, vemos<br />
un ejemplo de imagen de tono continuo.<br />
7.6.4. Color de 24-bits<br />
Este modo de video permite 16.777.216 <strong>colores</strong> en pantalla ya que se<br />
utilizan 24 bits dedicados a la información de color por cada píxel (2 24 ). Este<br />
modo de color mantiene 8 bits de color para componente de color rojo, verde y<br />
azul. Disponemos de los más de 16 millones de <strong>colores</strong> en cada píxel de la<br />
pantalla.<br />
Figura 15 - Imagen con 24 bits de profundidad<br />
Figura 14 - Imagen byn<br />
con 256 matices de color<br />
El inconveniente de la utilización de este modo es la utilización de<br />
memoria que se necesita para pantallas de alta resolución (2MB para<br />
1024x768). También es más lento mover grandes cantidades de memoria para<br />
realizar una animación o simplemente dibujar en pantalla. Aunque las tarjetas<br />
aceleradoras están optimizadas para este tipo de operaciones.
Colores y <strong>sombras</strong> 19<br />
7.7. Modelos de color<br />
El propósito de un modelo de color es facilitar la especificación de<br />
<strong>colores</strong> en algún formato estándar. Un modelo de color es una especificación<br />
de un modelo de coordenadas 3-D y un subespacio dentro de ese sistema<br />
donde cada color se representa por un punto único.<br />
La mayoría de los modelos de color que se utilizan están orientados<br />
hacia el hardware como monitores o impresoras o aplicaciones de<br />
manipulación de color. El modelo orientado al hardware más común es el RGB<br />
(red-green-blue), el modelo CMY (cyan-magenta-yellow) para impresoras en<br />
color y el YIQ que es el estándar para la difusión de TV ( Y = luminancia, I y Q<br />
son dos componentes cromáticas). Para la manipulación del color se suelen<br />
utilizar los modelos HSI (matiz, saturación e intensidad) y HSV (matiz,<br />
saturación y valor).<br />
Los modelos más utilizados en el procesamiento de imágenes son RGB,<br />
YIQ y HSI.<br />
7.7.1. Modelo de color XYZ<br />
En los años 30, la Commission Internationale de l'Eclairage (CIE) definió<br />
un espacio de color estándar, una manera de definir <strong>colores</strong> en términos<br />
matemáticos, para facilitar la comunicación de la información de color. Este<br />
espacio de color está basado en la investigación sobre la naturaleza de la<br />
percepción del color.<br />
7.7.1.1. Espacio de color CIE<br />
En el intento de lograr una representación que utilice solamente<br />
coeficientes de mezcla positivos, el CIE ("d'Eclairage de Internationale de la<br />
Comisión") definió tres nuevas fuentes de luz hipotéticas, x, y, y z, resultando<br />
curvas positivas:<br />
Figura 16 - representación de las fuentes de luz x, y, z<br />
Dado un espectro y un deseamos encontrar los valores correspondientes<br />
de X, de Y, y de Z, lo podemos lograr integrando el producto de la energía
Colores y <strong>sombras</strong> 20<br />
espectral con cada una de las tres curvas sobre todas las longitudes de onda.<br />
Los pesos de X, Y y Z se toman del espacio tridimensional del CIE XYZ, según<br />
lo mostrado arriba.<br />
Esto es logrado proyectando el espacio de color 3D sobre el plano<br />
X+Y+Z=1, resultando un diagrama de la cromaticidad del CIE.<br />
Se define la proyección como:<br />
Resultando el diagrama de cromaticidad CIE<br />
7.7.1.1.1. Diagrama de cromaticidad CIE<br />
El diagrama de cromaticidad CIE es un<br />
modelo de dos dimensiones de visión del color.<br />
El arco alrededor de la parte superior de la<br />
herradura incluye los <strong>colores</strong> espectrales puros<br />
desde el violeta azulado hasta el rojo.<br />
Mezclando dos <strong>colores</strong> espectrales puros<br />
en diferentes proporciones es posible crear<br />
todos los <strong>colores</strong> que se encuentran en la línea<br />
recta dibujada entre ellos en el diagrama. Es<br />
posible crear el mismo tono de gris mezclando el<br />
verde azulado y el rojo o mezclando el verde<br />
amarillento y el violeta azulado. Esto es<br />
posible debido a un fenómeno peculiar<br />
de la visión del color llamado<br />
metamerismo. Los <strong>colores</strong> púrpura, que<br />
no existen en el espectro de la luz pura, se encuentran en la parte inferior del<br />
diagrama. Los púrpuras son mezclas de rojo y azul, los extremos opuestos del<br />
espectro.<br />
El diagrama de cromaticidad CIE refleja el tono y la saturación, pero es<br />
necesario un modelo tridimensional para añadir el componente del brillo.<br />
Muchas aplicaciones informáticas incluyen cuadros de diálogo en los que es<br />
posible seleccionar <strong>colores</strong> manipulando el tono, la saturación y el brillo. Por<br />
ejemplo, Adobe Photoshop utiliza un cuadro Selector de Color que puede<br />
configurarse según las preferencias personales.<br />
7.7.1.1.2. Gama de <strong>colores</strong><br />
Figura 17 - Diagrama de cromaticidad<br />
CIE<br />
El diagrama de cromaticidad se puede utilizar para comparar las<br />
"gamas" de varios dispositivos de salida posibles (es decir, los monitores e<br />
impresoras). Note que una impresora de color no puede reproducir todos los<br />
<strong>colores</strong> visibles en un monitor de color.
Colores y <strong>sombras</strong> 21<br />
7.7.2. El modelo de color RGB<br />
Figura 18 - Comparación de gamas de <strong>colores</strong><br />
El modelo aditivo de color utilizado para los gráficos de computadora es<br />
representado por el cubo del color del RGB, donde R, G, y B representan los<br />
<strong>colores</strong> producidos por los fósforos rojos, verdes y azules, cubo del color de<br />
respectivamente. El cubo se proyecta dentro del espacio de color del CIE XYZ<br />
Nuestros ojos perciben el color a través de la simulación de tres<br />
pigmentos visuales en los conos de la retina. Estos pigmentos tienen una<br />
sensibilidad pico en las longitudes de onda 630 nm (rojo), 530 nm (verde), y<br />
430 nm (azul). Comparando las intensidades en una fuente de luz, se percibe<br />
el color de la luz. Esta teoría es la base para desplegar la salida de color en un<br />
monitor de video mediante el uso de los tres <strong>colores</strong> primarios, conocido como<br />
modelo de color RGB.<br />
Cada color aparece en sus componentes primarias espectrales rojo,<br />
verde y azul. El modelo está basado en un sistema de coordenadas cartesiano.<br />
El subespacio de interés es el cubo que se muestra en la figura 19.<br />
Todos los <strong>colores</strong> han sido normalizados de<br />
forma que el cubo es unitario, es decir, se supone<br />
que todos los valores de rojo, verde y azul están<br />
en el rango [0, 1].<br />
Este esquema de color es un modelo<br />
aditivo: las intensidades de los <strong>colores</strong> primarios<br />
se suman para producir otros <strong>colores</strong>. Cada punto<br />
de color contenido en los límites del cubo puede<br />
representarse como la tríada (R,G,B), donde los<br />
valores de R,G,B se asignan en el intervalo de 0 a<br />
1. Por ejemplo, el vértice magenta se obtiene<br />
sumando el rojo y el azul para producir la tríada Figura 19 - Cubo RGB<br />
(1,0,1) y el blanco en (1,1,1) es la suma de los<br />
vértices rojo, verde y azul. Las <strong>sombras</strong> de gris se representan a lo largo de la<br />
diagonal principal del cubo del origen (negro) al vértice blanco. Cada punto<br />
situado en esta diagonal tiene una contribución igual de cada color primario, de<br />
manera que una sombra de gris en medio del negro y el blanco se representan<br />
como (0.5, 0.5, 0.5).
Colores y <strong>sombras</strong> 22<br />
Las imágenes en el modelo de color RGB están formadas por tres<br />
planos de imágenes independientes, cada una de los <strong>colores</strong> primarios.<br />
Cuando se introducen en un monitor RGB, las tres imágenes se combinan en la<br />
pantalla de fósforo para producir una imagen de color compuesta. Por tanto, se<br />
utiliza el modelo RGB para el procesamiento de imágenes si las imágenes se<br />
expresan en términos de los tres planos de <strong>colores</strong>. La mayoría de las cámaras<br />
en color que se usan para adquirir imágenes digitales utilizan el formato RGB.<br />
Uno de los mejores ejemplos de la utilidad del modelo RGB es el<br />
procesamiento de imágenes aéreas y de satélites multiespectrales. Estas<br />
imágenes se obtienen para diferentes rangos espectrales. Por ejemplo, las<br />
imágenes LANDSAT se obtienen como mínimo en cuatro ventanas espectrales<br />
distintas de la misma escena. Dos ventanas estarán alojadas en el espectro<br />
visible y se corresponden aproximadamente con verde y rojo; las otras dos se<br />
encontrarán en el infrarrojo. Así pues cada plano de la imagen tiene sentido<br />
físico y la combinación de color utilizando el modelo RGB para procesamiento y<br />
visualización tiene sentido cuando se ve en una pantalla en color.<br />
A continuación se muestra una imagen en color de verduras y frutas<br />
junto con sus tres bandas de color rojo, verde y azul. El mayor nivel de gris en<br />
cada banda corresponde con el color predominante en cada objeto (fruta o<br />
verdura).<br />
Figura 20 - (a) Imagen original en color. (b) Plano de rojo. (c) Plano verde. (d)<br />
Plano azul<br />
Sin embargo este modelo de color no siempre es el mejor para el<br />
procesamiento de imágenes, por ejemplo para realizar una imagen en color con<br />
sombra de una cara humana. Este problema puede resolverse mediante la<br />
igualación del histograma. Al tener tres bandas y puesto que el histograma<br />
trabaja sólo con las intensidades, cuando igualemos el histograma en cada
Colores y <strong>sombras</strong> 23<br />
banda, en cada una de ellas tendremos mejora, sin embargo, el resultado<br />
global, (cuando se combinen las tres bandas), será impredecible.<br />
A pesar de todo este modelo es la elección más corriente para gráficos<br />
por ordenador ya que los CRT usan fósforo rojo, verde y azul para crear el<br />
color deseado. Sin embargo, este modelo no describe de forma eficiente las<br />
tres componentes de color (R,G,B). El igual ancho de banda da lugar a la<br />
misma profundidad del píxel y resolución del dispositivo para cada<br />
componente. Sin embargo, la sensibilidad de la componente de color del ojo<br />
humano es menor que la de la luminancia.<br />
Por estas razones, muchos métodos de codificación de imágenes y<br />
sistemas de transmisión utilizan la luminancia y dos diferencias de <strong>colores</strong>.<br />
Estos son los formatos YUV, YIQ, Y CbCr.<br />
7.7.3. El modelo de color CMY (Cyan, Magenta, Amarillo)<br />
Un modelo de color definido con los <strong>colores</strong> primarios cyan, magenta y<br />
amarillo (CMY) es útil para describir la salida de color de los dispositivos de<br />
copia hardware. A diferencia de los monitores de video, que producen un<br />
modelo de color combinando luz de los fósforos de la pantalla, los dispositivos<br />
hardware como las impresoras producen una imagen de color cubriendo un<br />
papel con pigmentos de color. Se obtienen los <strong>colores</strong> por luz reflejada, lo cual<br />
es un proceso sustractivo.<br />
Por ejemplo, el cyan (azul-verde) puede formase combinando luz verde<br />
con luz azul, por tanto cuando se refleja luz blanca sobre un objeto que es<br />
verde-azul la luz reflejada no debe tener componente roja, es decir, la luz roja<br />
es absorbida, o sustraída por el objeto. De forma análoga para obtener el<br />
magenta se resta la componente verde de la luz incidente y el amarillo sustrae<br />
la componente azul.<br />
En el modelo CMY, el<br />
punto (1,1,1) representa el<br />
negro, ya que todas las<br />
componentes de la luz incidente<br />
se sustraen. El origen representa<br />
la luz blanca. Cantidades iguales<br />
de cada uno de los <strong>colores</strong><br />
primarios producen grises a lo<br />
largo de la diagonal principal del<br />
cubo.<br />
Rojo<br />
Magenta<br />
Azul<br />
Negro<br />
Blanco<br />
Amarillo Verde<br />
Figura 21 - Cubo de Color<br />
Cyan (Verde-Azul)<br />
Como ya sabemos el cyan, magenta y amarillo son los <strong>colores</strong><br />
secundarios. Para convertir los <strong>colores</strong> primarios en secundarios hemos de<br />
realizar la siguiente transformación:
Colores y <strong>sombras</strong> 24<br />
⎛ C ⎞ ⎛1⎞<br />
⎛ R ⎞<br />
⎜ ⎟ ⎜ ⎟ ⎜ ⎟<br />
⎜ M ⎟ = ⎜1⎟<br />
⋅⎜<br />
G⎟<br />
⎜ ⎟ ⎜ ⎟ ⎜ ⎟<br />
⎝ Y ⎠ ⎝1⎠<br />
⎝ B ⎠<br />
La figura 20 (a,b,c) muestra las representaciones en las<br />
correspondientes bandas de la imagen en la figura 20 (a). Para obtener estas<br />
imágenes se ha normalizado cada canal a uno independientemente,<br />
dividiéndolo por 255, a continuación se le ha restado a uno dicha cantidad y por<br />
último se ha multiplicado el resultado por 255.<br />
7.7.4. El modelo de color YUV<br />
Este es el formato de color que se utiliza por los estándares de TV<br />
NTSC, PAL y SECAM. La Y representa la componente de blanco y negro y la<br />
información de color U y V se añade para mostrar una imagen en color. La<br />
transformación es:<br />
⎛ Y ⎞ ⎛ 0.<br />
299<br />
⎜ ⎟ ⎜<br />
⎜U<br />
⎟ = ⎜−<br />
0.<br />
147<br />
⎜ ⎟ ⎜<br />
⎝V<br />
⎠ ⎝ 0.<br />
615<br />
0.<br />
587<br />
− 0.<br />
289<br />
− 0.<br />
515<br />
0.<br />
114 ⎞ ⎛ R ⎞<br />
⎟ ⎜ ⎟<br />
0.<br />
436 ⎟ − ⎜G<br />
⎟<br />
− 0.<br />
100⎟<br />
⎜ ⎟<br />
⎠ ⎝ B ⎠<br />
Observemos que U = 0.492 (B - Y). y que V = 0.877 (R – Y ).<br />
Normalmente U y V son submuestreados por un factor de dos a cuatro en la<br />
dimensión espacial, ya que el ojo humano es mucho menos sensible a estos<br />
factores. Esto es muy útil, por ejemplo, para reducir el número de bits utilizado<br />
en técnicas de compresión de imágenes.<br />
7.7.5. El modelo de color YIQ<br />
Este modelo se utiliza en las emisiones de TV en color. Básicamente,<br />
YIQ es una recodificación de RGB para aumentar la eficiencia en la trasmisión<br />
y para mantener la compatibilidad con los estándares de TV monocromo. De<br />
hecho, la componente Y del sistema YIQ proporciona toda la información de<br />
video que se requiere para una televisión monocromo. La conversión de RGB a<br />
YIQ viene dada por:<br />
⎛Y<br />
⎞ ⎛0.<br />
299<br />
⎜ ⎟ ⎜<br />
⎜ I ⎟ = ⎜0.<br />
596<br />
⎜ ⎟ ⎜<br />
⎝Q<br />
⎠ ⎝0.<br />
212<br />
0.<br />
587<br />
− 0.<br />
275<br />
− 0.<br />
523<br />
0.<br />
114 ⎞ ⎛ R ⎞<br />
⎟ ⎜ ⎟<br />
− 0.<br />
321⎟<br />
• ⎜G<br />
⎟<br />
0.<br />
311 ⎟ ⎜ ⎟<br />
⎠ ⎝ B ⎠<br />
Este sistema fue diseñado teniendo en cuenta las características del<br />
sistema visual humano, obteniendo mayor sensibilidad a los cambios en<br />
luminancia que a los cambios de matiz o saturación. Así pues, este estándar<br />
usa más bits (o ancho de banda) para representar Y y menos para I y Q.<br />
Es uno de los modelos que más se utilizan. Una de sus mayores<br />
ventajas es que las informaciones de luminancia (Y) y color (I y Q) están<br />
separadas, esto nos permite procesar la luminancia sin afectar al color.
Colores y <strong>sombras</strong> 25<br />
La figura 22 (d,e,f) muestra las representaciones en las correspondientes<br />
bandas de la imagen en la figura 22 (a).<br />
Figura 22 - (a) Plano C del modelo CMY (b) Plano M del modelo CMY (c) Plano<br />
Y del modelo CMY (d) Plano Y del modelo YIQ (e) Plano I del modelo YIQ (f)<br />
Plano Q del modelo YIQ.<br />
Observemos que la figura 22(d) es una imagen en niveles de gris de la<br />
imagen original. Puesto que las bandas YUV tienen rangos distintos todas han<br />
sido llevadas al [0,255] para la visualización. Tengamos en cuenta que tanto la<br />
banda U como V pueden tener valores negativos.<br />
7.7.6. El modelo de color HSI<br />
El matiz es un atributo que describe la pureza de un color. La saturación<br />
es una medida del grado en el que un color puro se diluye con la luz blanca. La<br />
utilidad del modelo de color HSI se debe principalmente a estas dos<br />
características:<br />
- La componente de intensidad se separa de la información de color<br />
- Las otras dos componentes están muy relacionadas con la forma en<br />
la que el ser humano percibe el color.<br />
Gracias a estas propiedades este modelo es muy apropiado para el<br />
desarrollo de algoritmos de procesamiento de imágenes basados en<br />
propiedades del sistema de visión humano.
Colores y <strong>sombras</strong> 26<br />
7.7.7. El sistema HLS (Hue, Saturation and Luminance)<br />
Este modelo utiliza los tres componentes básicos del color: matiz (Hue),<br />
saturación (Saturation) y brillo (Luminance). Una representación gráfica<br />
incluyendo estas tres propiedades genera el<br />
denominado "espacio y color".<br />
En el perímetro del disco están situados<br />
los <strong>colores</strong> azul, magenta, rojo, amarillo, verde<br />
y cyan, separados 60º uno de otro:<br />
Cada punto del perímetro describe un<br />
color que es mezcla de los dos adyacentes.<br />
Un punto que no esté en el perímetro<br />
contendrá una mezcla de todos. Por lo tanto,<br />
estos puntos describen <strong>colores</strong> pastel que<br />
contienen una cierta cantidad de blanco. La<br />
distancia al centro (radio) indicará la<br />
saturación del color. El brillo (intensidad del<br />
color) depende de la altura en el doble cono, y<br />
es un valor entre 0 y 1.<br />
El punto medio del disco central<br />
describe un blanco de intensidad media.<br />
Supongamos que, por ejemplo, comenzamos<br />
en el perímetro del cono en el ángulo cero<br />
(color azul) y nos movemos en línea recta<br />
hacia arriba: estamos añadiendo más blanco,<br />
Figura 23 - Modelo HLS<br />
por lo que pasaremos por un azul claro, un azul pastel casi blanco hasta llegar<br />
finalmente a un blanco brillante. Esto sucede con todos los <strong>colores</strong>.<br />
La conclusión es que todos los <strong>colores</strong> convergen al blanco a medida<br />
que avanzamos hacia el vértice superior y hacia el negro a medida que<br />
bajamos.<br />
7.7.8. Modelo HSV<br />
Fue creado a partir de un concepto intuitivo de la manera de trabajar de<br />
un artista y su modo de mezclar <strong>colores</strong> para obtener el correcto sombreado y<br />
la obtención de los tonos intermedios. La selección y obtención de <strong>colores</strong> en el<br />
modelo HSV es mucho más intuitiva que en los modelos RGB y CMY. Se basa<br />
principalmente en el control de los valores de matiz, saturación y valor (HSV).<br />
− Hue (Matiz): Se representa en un ángulo en torno a un eje vertical<br />
(0º...360º). Los vértices del hexágono se separaran a intervalos de 60º. El rojo<br />
está en 0º, el amarillo en 60º, el verde en 120º y el azul-verde opuesto al rojo<br />
en H = 180º. Los <strong>colores</strong> complementarios distan 180º.
Colores y <strong>sombras</strong> 27<br />
− Saturation (Saturación): Varia<br />
de 0 a 1. Representa la pureza de un<br />
matiz. La pureza máxima se representa<br />
en S = 1. En S = 0 se tiene la escala de<br />
gris.<br />
− Value (Valor): Varia de 0 en la<br />
cúspide del cono hexagonal a 1 en la<br />
parte superior. En la cúspide se<br />
encuentra el negro, en la parte superior<br />
los <strong>colores</strong> de máxima intensidad.<br />
Los conceptos de color<br />
Figura 24 - Modelo HSV<br />
asociados con los términos <strong>sombras</strong>,<br />
tintes y tonos se representan en un plano seccional-transversal del cono<br />
hexagonal HSV. Si se agrega negro a un matiz puro se disminuye V hacia el<br />
lado del cono hexagonal. Por lo tanto, varias <strong>sombras</strong> se representan con<br />
valores S=1 y 0
Colores y <strong>sombras</strong> 28<br />
7.8. Colores en OpenGL<br />
7.8.1. Utilización de <strong>colores</strong> con OpenGL<br />
OpenGL especifica un color utilizando las intensidades separadas de<br />
componentes rojo, verde y azul. Por lo tanto un color se especifica con 3<br />
valores positivos, y puesto que el máximo disponible en el PC para el<br />
almacenamiento de esta información son 24 bits (8 bits para cada componente)<br />
podemos modelar los <strong>colores</strong> disponibles mediante un cubo de 255 unidades<br />
en cada cara. A este volumen lo denominamos el espacio de color RGB.<br />
Este “cubo de color” contiene todos los <strong>colores</strong> que podremos utilizar en<br />
nuestras aplicaciones, tanto en la superficie como en el interior del mismo.<br />
El modelo de color RGBA es el que utilizamos cuando definimos un color<br />
con la función glColor*; utilizamos el modelo de color indexado cuando<br />
seleccionamos un color de dibujo indicando un índice en una matriz de <strong>colores</strong><br />
disponible llamada paleta. Dentro de esta paleta, especificamos el color exacto<br />
que queremos seleccionando las intensidades de las componentes roja, verde<br />
y azul.<br />
Los elementos geométricos se dibujan con los atributos activos en cada<br />
momento. En cualquier momento se pude modificar el valor de<br />
los atributos, sustituyendo el nuevo valor al anterior. Los atributos<br />
podrán apilarse y desapilarse.<br />
La figura siguiente muestra el dibujo simple de dos<br />
triángulos de diferentes <strong>colores</strong>. Estos se definen con la<br />
instrucción glColor3f(red,green,blue) tal como se muestra en el<br />
código C (ver código completo en el anexo, ejemplo 1).<br />
void triangulo1(void)<br />
{<br />
}<br />
glBegin(GL_TRIANGLES);<br />
glColor3f(1.0,0.0,0.0);<br />
glVertex2f(0.0,0.4);<br />
glVertex2f(-0.4,0.0);<br />
glVertex2f(0.4,0.0);<br />
glEnd();<br />
void triangulo2(void)<br />
{<br />
}<br />
glBegin(GL_TRIANGLES);<br />
glColor3f(0.0,0.0,1.0);<br />
glColor3f(0.0,1.0,0.0);<br />
glVertex2f(0.0,-0.4);<br />
glVertex2f(-0.4,0.2);<br />
glVertex2f(0.4,0.2);<br />
glEnd();<br />
Figura 25 - Triángulos
Colores y <strong>sombras</strong> 29<br />
Listado 1 - Ejemplo de definición de <strong>colores</strong><br />
A pesar de que existe una instrucción que establece el color del segundo<br />
triángulo a azul, ésta no tendrá efecto ya que quedará anulado por la siguiente<br />
instrucción que lo pone a verde.<br />
La sintaxis de la función glColor es la siguiente:<br />
• Propósito: Selecciona el color actual en el modo de color RGBA.<br />
• Fichero de inclusión: <br />
• Sintaxis: void glColor. Donde número de argumentos<br />
puede ser 3 ó 4 (si hay componente alfa), y tipo de argumentos puede ser b(byte),<br />
d(double), f(float), etc.. Por ejemplo: void glColor4b( GLbyte rojo, GLbyte verde,<br />
GLbyte azul, GLbyte alfa); o void glColor3fv(const GLfloat *v);<br />
• Descripción: Selecciona el color activo especificando por separado las<br />
componentes roja, verde y azul. Algunas aceptan también la componente alfa (si no<br />
se especifica vale por defecto 1.0). Las funciones con sufijo v toman un puntero a<br />
una matriz que especifica las componentes.<br />
• Parámetros:<br />
rojo<br />
Especifica la componente roja del color.<br />
verde<br />
Especifica la componente verde del color.<br />
azul<br />
Especifica la componente azul del color.<br />
alfa<br />
Especifica la componente alfa del color. (Ver siguiente apartado)<br />
*v<br />
Al dibujar polígonos se puede controlar que se dibujen sus aristas o solo<br />
el interior. Es normal dibujar las aristas al realizar esquemas, mientras que<br />
estas se suelen suprimir cuando se desea general imágenes realistas. El<br />
control de visibilidad de las aristas se realiza con la función glEdgeflag(b)<br />
donde el argumento b será 0 o 1 dependiendo de que se active o no el dibujo<br />
de las aristas.<br />
Pero no sólo podemos conseguir <strong>colores</strong> solidos, también gradientes. Eso<br />
lo podemos llevar a la con un triángulo, por ejemplo; bastará con que le<br />
asignemos un color distinto a cada vértice para que OpenGL rendere la imagen<br />
con el gradiente de color resultante entre ellos (fijémonos que estamos con lo<br />
que se denomina, color suave). La construcción del triángulo quedará así:
Colores y <strong>sombras</strong> 30<br />
glBegin GL_TRIANGLES<br />
glColor3f( 1.0,0.0,0.0 ) //color rojo<br />
glVertex3f( 0.0,1.0,0.0 )<br />
glColor3f( 0.0,1.0,0.0 ) //color verde<br />
glVertex3f( -1.0,-1.0,0.0 )<br />
glColor3f( 0.0,0.0,1.0 ) //color azul<br />
glVertex3f( 1.0,-1.0,0.0 )<br />
glEnd<br />
Listado 2 - Ejemplo de definición de un gradiente<br />
El resultado de la coloración de la escena es la siguiente:<br />
7.8.2. Modelo de color RGBA<br />
Figura 26 - Gradiente<br />
En el modelo RGBA utilizamos la función glColor*( ) para seleccionar el<br />
color actual que establece los <strong>colores</strong> rojo, verde, azul y la componente alfa (si<br />
se utiliza transparencia). Todos los objetos dibujados después de la aplicación<br />
de esta función tendrán el último color especificado en la misma.<br />
Canal alpha<br />
El canal alpha no es más que una imagen de 8 bits en escala de grises.<br />
OpenGL interpreta esta información como sigue:<br />
• Un valor alpha de 0 (color negro) indica transparencia total, es<br />
decir, que la zona del polígono afectada por este valor no se verá.<br />
• Un valor de 128 (color gris "puro") indica semitransparencia.<br />
• Un valor de 255 (color blanco) indica opacidad total<br />
El funcionamiento es el siguiente:<br />
El modelo RGBA de color dota a cada punto de una cuarta componente<br />
llamada canal alfa. Este sirve para decidir que debe hacerse con ese punto si<br />
contribuye junto con otros a colorear un píxel. Hasta ahora el citado píxel se
Colores y <strong>sombras</strong> 31<br />
pintaría del color del polígono más cercano pero si activamos el canal alfa<br />
obtendremos “mezclas de <strong>colores</strong>” para el píxel. Cada polígono contribuirá en<br />
un cierto tanto por ciento a colorear el píxel de forma que podemos obtener<br />
interesantes efectos como emular un cristal tintado o un papel de celofán rojo,<br />
por ejemplo:<br />
Figura 27 - Funcionamiento<br />
canal alpha<br />
En esta imagen se observa que<br />
mezclando dos <strong>colores</strong> generamos un<br />
tercero o lo que es lo mismo, que si tengo<br />
un objeto de color rojo y le pongo delante<br />
un papel translúcido de color azul, la<br />
intersección de ambos se verá de color<br />
lila.<br />
Eso ocurre porque el polígono que<br />
está más cerca tiene un cierto grado de<br />
transparencia por lo cuál nos deja ver lo<br />
que tiene detrás. A esto se le llama<br />
“Blending”. Siempre se habla de una<br />
fuente (source) y un destino (destination). El destino es el valor de color que<br />
un píxel ya tiene asignado en el frame buffer. La fuente es el color que<br />
viene, el color que se mezclará con el que ya tiene.<br />
Se combinan los <strong>colores</strong> de la fuente y del destino según el valor de<br />
alfa que tiene cada uno de ellos. Se define una función de mezclado, o de<br />
“blending” que, según sea, aplicará de una forma o de otra el canal alfa de<br />
cada color.<br />
Para hacer esto con OpenGL se deberá activar el mezclado de<br />
<strong>colores</strong> y desactivarlo con las funciones glEnable(GL_BLEND) y<br />
glDisable(GL_BLEND).<br />
Para indicar como debe hacerse la mezcla se usará la función<br />
glBlendFunc(Glenum factorfuente, Glenum factordestino). Dos<br />
ejemplos:<br />
1. glBlendFunc(GL_ONE,GL_ZERO). En este caso estamos<br />
dando una importancia de 1 (máxima) al canal alfa de la fuente y<br />
de 0 (nula) al canal alfa del destino. Eso equivale a decir que el<br />
color final se compone de un 100% del de la fuente y de un 0%<br />
del color destino por lo cual el píxel acaba siendo del color de la<br />
fuente.<br />
2. glBlendFunc(GL_SRC_ALPHA, GL_ONE). En este caso le<br />
decimos que multiplique a la fuente por su valor de alfa y sume el<br />
resultado al color destino. En este caso y asumiendo un valor de<br />
alfa igual a 0.75 para la fuente, podríamos decir que el color<br />
resultante=(color de la fuente*0.75)+Color del destino.<br />
Sintaxis de la funcion:<br />
glBlendFunc(Glenumfactor_o,Glenumfactor_d):
Colores y <strong>sombras</strong> 32<br />
• Propósito: Define el color de las funciones de mezcla.<br />
• Fichero de inclusión: <br />
• Sintaxis: void glBlendFunc( GLenum factor_o, GLenum factor_d);<br />
• Descripción: Selecciona los factores de origen y destino para la mezcla de <strong>colores</strong>.<br />
Primero debemos llamar a glEnable(GL_BLEND) para activar la mezcla de <strong>colores</strong>.<br />
• Parámetros:<br />
factor_o<br />
GLenum: la función de mezcla de color en origen.<br />
factor_d<br />
GLenum: la función de mezcla de color en destino.<br />
• Retornos: Ninguno
Colores y <strong>sombras</strong> 33<br />
Para las funciones glColor que aceptan valores enteros el rango de<br />
valores que se acepta varía entre 0.0 y 1.0. el máximo y el mínimo valor que<br />
puede ser almacenado en el framebuffer.<br />
Cuando se especifican las componentes de color utilizando enteros sin<br />
signo, estas componentes son mapeadas linealmente a valores de coma<br />
flotante, de manera que representen valores comprendidos entre el 1.0<br />
(intensidad total) y 0.0 (intensidad nula). Las componentes especificadas<br />
utilizando valores enteros con signo son mapeadas linealmente a valores de<br />
coma flotante, de manera que el valor más positivos representa al 1.0 y el<br />
más negativo al 0.0<br />
Sufijo Tipo de Dato Valor mínimo mínimo Valor de<br />
Mapeo<br />
Valor<br />
Máximo<br />
B 1-byte-integer -128 -1.0 127 1.0<br />
S 2-byte-integer -32768 -1.0 32767 1.0<br />
I 4-byte-integer -<br />
Ub Unsigned 1- byte-<br />
integer<br />
Us Unsigned 2- byte-<br />
integer<br />
Ui Unsigned 4- byte-<br />
integer<br />
2.147.483.648<br />
-1.0 2.147.483.647 1.0<br />
0 0.0 255 1.0<br />
0 0.0 65535 1.0<br />
0 0.0 4.294.967.295 1.0<br />
Valor Máximo de<br />
Mapeo<br />
• Propósito: Selecciona los valores de color y alfa para borrar los buffers de color.<br />
• Fichero de inclusión: <br />
• Sintaxis: void glClearColor(GLclampf rojo, GLclampf verde, GLclampf azul,<br />
GLclampf alfa);<br />
• Descripción: Selecciona los valores de relleno para borrar los buffers rojo, verde,<br />
azul y alfa, que varían entre [0.0f,1.0f].<br />
• Parámetros:<br />
rojo<br />
GLclampf: la componente roja del valor de relleno.<br />
verde<br />
GLclampf: la componente verde del valor de relleno.<br />
azul<br />
GLclampf: la componente azul del valor de relleno.<br />
alfa<br />
GLclampf: la componente alfa del valor de relleno.<br />
• Retornos: Ninguno.<br />
Una de las primeras acciones que hay que realizar en nuestras<br />
aplicaciones es limpiar el área de dibujo en la que vamos a trabajar.
Colores y <strong>sombras</strong> 34<br />
Limpiaremos la ventana cada vez que dibujemos una nueva imagen. Utilizando<br />
el modelo tetradimensional RGBA podemos crear efectos en la ventana de<br />
dibujo que interactúa con otras ventanas que se encuentren debajo de ella,<br />
manipulando la opacidad de la ventana al limpiarla.<br />
La función glClearColor(GLclampf rojo, GLclampf verde, GLclampf azul,<br />
GLclampf alfa) selecciona los valores de relleno para<br />
borrar los buffers rojo, verde, azul y alfa, que varían entre<br />
[0.0f,1.0f]. Su sintaxis es la siguiente:<br />
La figura muestra un ejemplo de modelo de color<br />
RGBA en el que se muestra la transparencia de un<br />
cristal de color rojo que deja ver parte de la esfera verde<br />
situada por detrás de él. El código correspondiente a la<br />
misma es el siguiente:<br />
Figura 28 – modelo<br />
de color RGBA
Colores y <strong>sombras</strong> 35<br />
#include <br />
#include <br />
#include <br />
#include <br />
int idventana;<br />
void cristal(void)<br />
{<br />
glShadeModel(GL_FLAT);<br />
glEnable(GL_BLEND);<br />
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);<br />
glPushMatrix();<br />
glTranslatef(-10,-10,-100.0);<br />
glBegin(GL_QUADS);//Dibuja el cristal<br />
glColor4f(1.0,0.0,0.0,0.10);<br />
glVertex3f(0,0,0);<br />
glVertex3f(0,10,0);<br />
glVertex3f(10,10,0);<br />
glVertex3f(10,0,0);<br />
glEnd();<br />
}<br />
glPopMatrix();<br />
glDisable(GL_BLEND);<br />
void bola(void)<br />
{<br />
glPushMatrix();<br />
glTranslatef(0,0,-150);<br />
glColor4f(0.0,0.8,0.0,1.0);//Dibuja la bola amarilla<br />
glutSolidSphere(6,20,10);<br />
glPopMatrix();<br />
}<br />
void display(void)<br />
{<br />
GLfloat pos[4]={2.0,12.0,3.0,0.0};<br />
glClearColor(1,1,1,1);<br />
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);<br />
bola();<br />
cristal();<br />
glutSwapBuffers();<br />
glFlush();<br />
}<br />
void myReshape(GLsizei w, GLsizei h)<br />
{<br />
glViewport(0,0,w,h);<br />
glMatrixMode(GL_PROJECTION);
Colores y <strong>sombras</strong> 36<br />
}<br />
glLoadIdentity();<br />
if (h==0)<br />
gluPerspective(20,(GLdouble)w,1.0,500.0);<br />
else<br />
gluPerspective(20,(GLdouble)w/(GLdouble)h,1.0,500.0);<br />
glMatrixMode(GL_MODELVIEW);<br />
glLoadIdentity();<br />
glFlush();<br />
void Idle(void)<br />
{<br />
angulo+=0.5;<br />
if (angulo>360) angulo=0;<br />
glutPostRedisplay();<br />
}<br />
int main(int argc, char **argv)<br />
{<br />
glutInit(&argc,argv);<br />
glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);<br />
glutInitWindowPosition(0,0);<br />
glutInitWindowSize(300,300);<br />
idventana=glutCreateWindow("Transparencia");<br />
glutReshapeFunc(myReshape);<br />
glutDisplayFunc(display);<br />
glutIdleFunc(Idle);<br />
glutMainLoop();<br />
}<br />
return 0;<br />
Listado 3 - Ejemplo de definición de transparencia<br />
7.8.3. Modelo de color indexado<br />
Muchos sistemas tienen frame buffer limitado en profundidad. Podemos<br />
tener una resolución espacial para el frame buffer de 1280x1024, pero cada<br />
píxel tendría solo 8 bits de profundidad. Podemos dividir estos 8 bits en grupos<br />
más pequeños de bits para asignar rojo, verde y azul. En algunas aplicaciones<br />
esta técnica puede ser adecuada, pero no es muy flexible en la asignación de<br />
<strong>colores</strong> ya que divide los bytes en distintos grupos de bits que pueden afectar<br />
al resultado.
Colores y <strong>sombras</strong> 37<br />
Podemos seleccionar los <strong>colores</strong> interpretando nuestra limitación de<br />
profundidad (en los píxeles) como índices mejor que como valores de color.<br />
Estos índices corresponden a filas o entradas en una tabla. Suponiendo que<br />
nuestro frame buffer tiene k bits por píxel. Cada valor de píxel o índice es un<br />
entero entre 0 y 2 k -1. Si podemos mostrar <strong>colores</strong> con una precisión de m bits<br />
podremos elegir entre 2 m rojos, 2 m verdes y 2 m azules. Produciremos<br />
cualquiera de los 2 3m <strong>colores</strong> aunque el frame buffer solo pueda especificar 2 k<br />
<strong>colores</strong>. Utilizamos una tabla de búsqueda de <strong>colores</strong> de tamaño 2 k * 3 m, el<br />
programa del usuario considerará 2 k filas de la tabla con los <strong>colores</strong> deseados<br />
utilizando m bits para cada rojo, verde y azul.<br />
Una vez que el usuario ha construido la tabla puede especificar un color<br />
por su índice que apunta a la posición adecuada en la tabla de búsqueda de<br />
color. Para k=m=8, una configuración muy común, se pueden elegir 256<br />
<strong>colores</strong> de entre 16 millones de <strong>colores</strong>. Las 256 entradas en la tabla<br />
constituyen la paleta de color del usuario.<br />
Entrada Rojo Verde Azul<br />
0 0 0 0<br />
1 2 m -1 0 0<br />
. 0 2 m -1 0<br />
. . . .<br />
. . . .<br />
2 k -1 . . .<br />
m bits m bits m bits<br />
Si estamos utilizando el modelo de color indexado, el color actual es<br />
seleccionado llamando a la función:<br />
void glIndex{sifd ub} (TYPE c );<br />
void glIndex{sifd ub}v (const TYPE *c );<br />
Sintaxis de la función glIndex:
Colores y <strong>sombras</strong> 38<br />
• Propósito: Selecciona el índice de color actual para usar con las<br />
operaciones de color.<br />
• Fichero de inclusión: <br />
• Sintaxis:<br />
• void glIndexd( GLdouble c);<br />
• void glIndexf( GLfloat c);<br />
• void glIndexi( GLint c);<br />
• void glIndexs( GLshort c);<br />
• void glIndexdv( const GLdouble *c);<br />
• void glIndexfv( const GLfloat*c);<br />
• void glIndexiv( const GLint *c);<br />
void glIndexsv( const GLshort *c);<br />
• Descripción: Esta función cambia el índice de color actual al<br />
especificado por c.<br />
• Parámetros:<br />
c<br />
El índice del nuevo color para uso en las siguientes operaciones.<br />
*c<br />
Un puntero al índice del nuevo color para uso en las siguientes<br />
operaciones.<br />
• Retornos: Ninguno.<br />
En el modelo RGBA vimos la especificación de glClearColor(), para el<br />
modelo de color indexado existe su análogo que es glClearIndex().<br />
Formato de la instrucción glClearIndex:<br />
• Propósito: Especifica un índice de color para el buffer de<br />
color.<br />
• Fichero de inclusión: <br />
• Sintaxis: void glClearIndex(GLfloat indice);<br />
• Descripción: Selecciona el valor de color que usaremos<br />
para borrar el buffer de color con<br />
glClear(GL_COLOR_BUFFER_BIT).<br />
• Parámetros:<br />
índice<br />
GLfloat: el índice de color para el buffer de color.<br />
• Retornos: Ninguno.<br />
Para especificar el modo indexado de color debemos seleccionar el<br />
miembro iPixelType de la estructura PIXELFORMATDESCRIPTOR como se<br />
muestra a continuación:
Colores y <strong>sombras</strong> 39<br />
PIXELFORMATDESCRIPTOR pfd; //declaración estructura<br />
pfd.iPixelType = PFD_TYPE_COLORINDEX; //Selección modo<br />
indexado de color<br />
Si por el contrario trabajamos con el modo RGBA de color<br />
seleccionaremos el miembro iPixelType de la estructura<br />
PIXELFORMATDESCRIPTOR de esta manera:<br />
pfd.iPixelType = PFD_TYPE_RGBA; //Selección<br />
modo RGBA de color<br />
Pegar código paleta.c<br />
/////////////////////////////////////////////////////<br />
// Principal o punto de entrada para todos los<br />
programas Windows<br />
/////////////////////////////////////////////////////<br />
int APIENTRY WinMain(HINSTANCE hCurrentInst, HINSTANCE<br />
hPreviousInst,<br />
{<br />
LPSTR lpszCmdLine, int nCmdShow)<br />
HGLRC hRC; // Contexto para OpenGL<br />
HWND hWnd; // Almacenamiento<br />
para la gestion de Ventana<br />
MSG msg; // Estructura de<br />
mensajes de Windows<br />
buffer<br />
color<br />
DWORD buffer = PFD_DOUBLEBUFFER; // tipo de<br />
BYTE color = PFD_TYPE_RGBA; // tipo de<br />
// Si en la llamada a la aplicación se ha<br />
incluido el parámetro -sb<br />
if (strstr(lpszCmdLine, "-sb")) { // Modo RGB<br />
}<br />
buffer = 0;
Colores y <strong>sombras</strong> 40<br />
// Si en la llamada a la aplicación se ha<br />
incluido el parámetro -ci<br />
color Indexado<br />
if (strstr(lpszCmdLine, "-ci")) {<br />
}<br />
color = PFD_TYPE_COLORINDEX; // Modo de<br />
// Si en la llamada a la aplicación se ha<br />
incluido el parámetro -h<br />
el tipo<br />
if (strstr(lpszCmdLine, "-h")) {<br />
}<br />
//Mostramos ayuda<br />
MessageBox(NULL, "paleta [-ci] [-sb]\n"<br />
" -sb single buffered\n"<br />
" -ci color index\n",<br />
"Usage help", MB_ICONINFORMATION);<br />
exit(0); //saliendo!!<br />
// Crea la ventana principal de la aplicación con<br />
// y buffer de color seleccionado<br />
hWnd = CreateOpenGLWindow("paleta", 0, 0, 256,<br />
256, color, buffer);<br />
if (hWnd == NULL)<br />
salimos del programa!!<br />
// Si no se puede crear correctamente<br />
exit(1);<br />
// Almacena el contexto de dispositivo<br />
hDC = GetDC(hWnd);<br />
// Crea el contexto de generación y lo activa<br />
hRC = wglCreateContext(hDC);<br />
wglMakeCurrent(hDC, hRC);<br />
// Visualiza la ventana<br />
ShowWindow(hWnd, SW_SHOW);
Colores y <strong>sombras</strong> 41<br />
hasta que<br />
UpdateWindow(hWnd);<br />
while (1) //bucle infinito!!<br />
{<br />
PM_NOREMOVE)) {<br />
programa<br />
}<br />
rota, colorea, ...)<br />
}<br />
// Procesa los mensajes de la aplicación<br />
// la aplicación se cierra<br />
while(PeekMessage(&msg, hWnd, 0, 0,<br />
if(GetMessage(&msg, hWnd, 0, 0))<br />
{<br />
}<br />
else<br />
{<br />
}<br />
TranslateMessage(&msg);<br />
DispatchMessage(&msg);<br />
goto quit; //solicitada salida del<br />
// Le hace de todo al triangulo (lo dibuja,<br />
triangulo();<br />
//Solicitan salir del programa<br />
quit:<br />
activado<br />
// Deselecciona el contexto de generación<br />
wglMakeCurrent(NULL, NULL);<br />
ReleaseDC(hDC, hWnd);<br />
wglDeleteContext(hRC);<br />
//destruye la ventana window!<br />
DestroyWindow(hWnd);
Colores y <strong>sombras</strong> 42<br />
}<br />
// Borra la paleta si fue creada<br />
if (hPalette)<br />
DeleteObject(hPalette);<br />
return 0;<br />
/////////////////////////////////////////////////////<br />
// Creacion de la ventana para la aplicación<br />
/////////////////////////////////////////////////////<br />
HWND CreateOpenGLWindow(char* title, int x, int y, int<br />
width, int height,<br />
{<br />
BYTE type, DWORD flags)<br />
int n, pf;<br />
HWND hWnd; //<br />
Almacenamiento para la gestion de Ventana<br />
clase de Windows<br />
WNDCLASS wc; // Estructura de<br />
LOGPALETTE* lpPal; // Puntero a<br />
memoria para la paleta logica<br />
PIXELFORMATDESCRIPTOR pfd; // Descriptor<br />
del formato de pixel<br />
almacenamiento<br />
vez<br />
static HINSTANCE hInstance = 0; // Instancia de<br />
// Tan solo registro la clase de la ventana una<br />
// uso hInstance como un flag<br />
if (!hInstance) {<br />
hInstance = GetModuleHandle(NULL);<br />
// Registra el estilo de la Ventana<br />
wc.style = CS_OWNDC;
Colores y <strong>sombras</strong> 43<br />
ventana OpenGL<br />
wc.lpfnWndProc = (WNDPROC)WindowProc;<br />
wc.cbClsExtra = 0;<br />
wc.cbWndExtra = 0;<br />
wc.hInstance = hInstance;<br />
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);<br />
wc.hCursor = LoadCursor(NULL, IDC_ARROW);<br />
// No se necesita para la brocha de fondo de la<br />
wc.hbrBackground = NULL;<br />
wc.lpszMenuName = NULL;<br />
wc.lpszClassName = "OpenGL";<br />
// Registra la clase de la ventana<br />
if (!RegisterClass(&wc)) {<br />
Window.", "Error", MB_OK);<br />
}<br />
}<br />
MessageBox(NULL, "RegisterClass() failed: "<br />
return NULL;<br />
"No puedo registrar la class<br />
// Crea la ventana principal de la aplicación<br />
hWnd = CreateWindow("OpenGL", title,<br />
WS_OVERLAPPEDWINDOW |<br />
hInstance, NULL);<br />
mostramos error!<br />
WS_CLIPSIBLINGS | WS_CLIPCHILDREN,<br />
x, y, width, height, NULL, NULL,<br />
// Si no se puede crear la ventana principal<br />
if (hWnd == NULL) {<br />
MessageBox(NULL, "CreateWindow() failed: No<br />
puedo crear la ventana.","Error", MB_OK);<br />
return NULL;
Colores y <strong>sombras</strong> 44<br />
}<br />
hDC = GetDC(hWnd);<br />
// No hay garantías de que el contenido de la<br />
pila que comienza en<br />
la estructura<br />
esta estructura<br />
// pfd este a 0, nos aseguramos de ello<br />
memset(&pfd, 0, sizeof(pfd));<br />
pfd.nSize = sizeof(pfd); // Tamaño de<br />
pfd.nVersion = 1; // Version de<br />
// Dibuja<br />
en la ventana (No en el mapa de bits), // Soporta llamada<br />
OpenGL en la ventana, flags<br />
pfd.dwFlags = PFD_DRAW_TO_WINDOW |<br />
PFD_SUPPORT_OPENGL | flags;<br />
pfd.iPixelType = type; // Tipo de pixel<br />
pfd.cColorBits = 32; // Tamaño del<br />
Buffer de Profundidad<br />
lo descrito por pfd<br />
// Escoge el formato de pixel que mejor encaje en<br />
pf = ChoosePixelFormat(hDC, &pfd);<br />
if (pf == 0) {<br />
MessageBox(NULL, "ChoosePixelFormat() failed: "<br />
ajuste!.", "Error", MB_OK);<br />
}<br />
return 0;<br />
"No encuentro un formato de píxel que se<br />
// Selecciona el formato de píxel para el<br />
contexto de dispositivo<br />
if (SetPixelFormat(hDC, pf, &pfd) == FALSE)<br />
{
Colores y <strong>sombras</strong> 45<br />
"<br />
"Error", MB_OK);<br />
}<br />
return 0;<br />
MessageBox(NULL, "SetPixelFormat() failed:<br />
"No encuentro el formato especificado.",<br />
//Toma el formato de píxel y recupera la<br />
descripcion del formato de píxel<br />
DescribePixelFormat(hDC, pf,<br />
sizeof(PIXELFORMATDESCRIPTOR), &pfd);<br />
necesita una paleta<br />
/* Si el tipo de píxel seleccionado es Index ó se<br />
entradas especificadas*/<br />
entonces realiza selecciona una paleta con las<br />
if (pfd.dwFlags & PFD_NEED_PALETTE ||<br />
pfd.iPixelType == PFD_TYPE_COLORINDEX) {<br />
n = 1 256) n = 256;<br />
lpPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +<br />
sizeof(PALETTEENTRY) * n);<br />
memset(lpPal, 0, sizeof(LOGPALETTE) +<br />
sizeof(PALETTEENTRY) * n);<br />
>palPalEntry[0]);<br />
lpPal->palVersion = 0x300;<br />
lpPal->palNumEntries = n;<br />
GetSystemPaletteEntries(hDC, 0, n, &lpPal-<br />
/* Si el tipo de píxel seleccionado es RGBA,<br />
entonces realiza selección
Colores y <strong>sombras</strong> 46<br />
se selecciona Indexado<br />
individual 1 a 1 */<br />
de las mascaras para RGB, si por el contrario<br />
hay que elegir los elementos de forma<br />
if (pfd.iPixelType == PFD_TYPE_RGBA) {<br />
int redMask = (1 pfd.cRedShift) & redMask) *<br />
lpPal->palPalEntry[i].peGreen =<br />
(((i >> pfd.cGreenShift) & greenMask) *<br />
lpPal->palPalEntry[i].peBlue =<br />
(((i >> pfd.cBlueShift) & blueMask) *<br />
lpPal->palPalEntry[i].peFlags = 0;<br />
/* Rellena las entradas con los <strong>colores</strong><br />
lpPal->palPalEntry[0].peRed = 0;<br />
lpPal->palPalEntry[0].peGreen = 0;<br />
lpPal->palPalEntry[0].peBlue = 0;<br />
lpPal->palPalEntry[0].peFlags =
Colores y <strong>sombras</strong> 47<br />
PC_NOCOLLAPSE;<br />
PC_NOCOLLAPSE;<br />
PC_NOCOLLAPSE;<br />
}<br />
lpPal->palPalEntry[1].peRed = 255;<br />
lpPal->palPalEntry[1].peGreen = 0;<br />
lpPal->palPalEntry[1].peBlue = 0;<br />
lpPal->palPalEntry[1].peFlags =<br />
lpPal->palPalEntry[2].peRed = 0;<br />
lpPal->palPalEntry[2].peGreen = 255;<br />
lpPal->palPalEntry[2].peBlue = 0;<br />
lpPal->palPalEntry[2].peFlags =<br />
lpPal->palPalEntry[3].peRed = 0;<br />
lpPal->palPalEntry[3].peGreen = 0;<br />
lpPal->palPalEntry[3].peBlue = 255;<br />
lpPal->palPalEntry[3].peFlags =<br />
//Crea la paleta<br />
hPalette = CreatePalette(lpPal);<br />
if (hPalette) {<br />
//Avanza, selecciona y realiza la paleta<br />
para este contexto de dispositivo<br />
}<br />
}<br />
}<br />
SelectPalette(hDC, hPalette, FALSE);<br />
RealizePalette(hDC);<br />
//libera la memoria de la estructura lpPal<br />
free(lpPal);<br />
ReleaseDC(hDC, hWnd);<br />
return hWnd;<br />
Listado 4 - Color indexado vs. Color RGBA
Colores y <strong>sombras</strong> 48<br />
Figura 29 - Paleta modelo de color RGB<br />
7.8.4. Modelo de color RGBA vs. Modelo de color Indexado<br />
Figura 30 - Paleta modelo de color Index<br />
No podemos usar el modo de color indexado y el modo de color RGBA<br />
juntos. Esto significa que si usamos el modo indexado en un dispositivo de<br />
color real, no tendremos acceso a todos los <strong>colores</strong> disponibles. Bajo algunas<br />
implementaciones, la paleta de color indexado puede tener hasta 4096<br />
entradas; sin embargo, la implementación de Microsoft sólo soporta 256<br />
entradas.<br />
Además de limitar la selección de <strong>colores</strong>, el modo indexado de color no<br />
soporta otros efectos especiales de OpenGL, incluidos muchos efectos de<br />
iluminación y sombreado, niebla, anti-escalonado y mezcla alfa. Generalmente<br />
es mejor usar el modo RGBA. La ventaja más significativa de usar el indexado<br />
es un mayor control de la paleta en dispositivos de pantalla de 8 bits.<br />
Nuestra decisión en la utilización de modelo de color RGBA o Indexado<br />
puede basarse en el hardware disponible y en las necesidades de nuestra<br />
aplicación. Para la mayoría de sistemas muchos <strong>colores</strong> pueden ser<br />
representados simultáneamente tanto con el modelo de color RGBA como con<br />
el modelo de color Indexado. Sin embargo, en muchos efectos como el<br />
sombreado, la iluminación, mapeado de texturas y niebla, el modelo RGBA<br />
proporciona una mayor flexibilidad que el modelo de color indexado.<br />
Podemos optar por utilizar el modelo de color indexado en tres casos:<br />
1. Si estamos migrando una aplicación que hace un uso importante del<br />
modelo de color indexado es más sencillo no cambiarlo al modelo RGBA.
Colores y <strong>sombras</strong> 49<br />
2. Si disponemos de un pequeño numero de planos de color el modelo<br />
RGBA puede producir sombreados de color de baja calidad. Por ejemplo,<br />
si sólo disponemos de 8 planos de color con el modelo RGBA sólo<br />
dispondremos de 3 bits para el rojo, 3 bits para el verde y 2 para el azul,<br />
es decir, 8 (2 3 ) <strong>sombras</strong> de rojo y verde, y sólo 4 de azul.<br />
En esta situación si tenemos limitados los requerimientos de sombreado<br />
podemos utilizar una tabla de búsqueda de color para obtener mas<br />
<strong>colores</strong> de sombra. Por ejemplo, si requerimos sólo <strong>sombras</strong> azules se<br />
puede utilizar el modelo de color indexado y almacenar 256 (2 8 ) <strong>sombras</strong><br />
de color azul, esto es mucho mejor que las 4 <strong>sombras</strong> que nos ofrecía el<br />
modelo de color RGBA.<br />
3. El modelo de color indexado puede ser utilizado para hacer varios<br />
trucos, como mapas de color, animaciones y dibujo por capas.<br />
En general, utilizaremos el modelo de color RGBA siempre que sea<br />
posible ya que permite mapeado de texturas y trabaja mejor con sombreado,<br />
iluminación, niebla, antialiasing y combinación de <strong>colores</strong> (blending).<br />
7.8.5. Ocultaciones<br />
OpenGL permite utilizar dos métodos de ocultación: el algoritmo de las<br />
caras de detrás (Back Face Removal), y el algoritmo del Z-buffer.<br />
7.8.5.1. Algoritmo de las caras de detrás<br />
Consiste en ocultar las caras que no se dibujarían porque formarían<br />
parte de la parte trasera del objeto. Para decirle a OpenGL que queremos<br />
activar este método de ocultación, tenemos que escribir:<br />
glEnable(GL_CULL_FACE)
Colores y <strong>sombras</strong> 50<br />
Figura 32 - Ocultando caras de detrás<br />
Figura 31 - Sin ocultaciones<br />
Importante. OpenGL ignora totalmente la normal que le podamos pasar<br />
con la función glNormalf, así que esta normal sólo se utiliza a efectos de<br />
iluminación. A efectos de ocultación de caras, OpenGL decide si oculta o no<br />
una cara a partir del orden de definición de los vértices que la forman.<br />
Así, si la proyección sobre del camino que forman los vértices del<br />
primero al último es en el sentido de las agujas del reloj, entonces se dice que<br />
el orden es clockwise. Si es en sentido inverso, se dice que es<br />
counterclockwise. Por defecto, OpenGL sólo renderiza aquellos polígonos<br />
cuyos vértices estan en orden counterclockwise cuando son proyectados<br />
sobre la ventana. Pero los objetos definidos por la GLUT no tienen porqué estar<br />
definidos clockwise (como es el caso de la tetera). Por tanto, antes de<br />
renderizarlos usando este algoritmo de ocultación, debemos llamar a<br />
glFrontFace(GL_CW) o a glFrontFace(GL_CCW).<br />
7.8.5.2 Algoritmo del Z-buffer<br />
El algoritmo del Z-buffer es del tipo espacio-imagen. Cada vez que se va<br />
a renderizar un pixel, comprueba que no se haya dibujado antes en esa<br />
posición un pixel que esté más cerca respecto a la cámara. Este algoritmo<br />
funciona bien para cualquier tipo de objetos: cóncavos, convexos, abiertos y<br />
cerrados. Para activarlo, hay que hacer una llamada a:<br />
glEnable(GL_DEPTH_TEST)
Colores y <strong>sombras</strong> 51<br />
Esta llamada le dice a OpenGL que active el test de profundidad.<br />
Además, cada vez que se redibuje la escena, a parte de borrar el buffer de<br />
color, hay que borrar el buffer de profundidad. Esto se hace con la llamada:<br />
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT).<br />
Por último, pero no menos importante, al inicializar OpenGL se le tiene<br />
que decir que cree el buffer de profundidad. Esto se hace al definir el modo de<br />
visualización (ver capítulo GLUT).<br />
Figura 33 - Sin Z-Buffer Figura 34 - Con Z-Buffer<br />
7.8.5.3. Combinando ambos algoritmos<br />
El algoritmo de la eliminación de las caras de detrás es suficiente para<br />
renderizar para objetos convexos y cerrados, como este octahedro, pero para<br />
objetos cóncavos y cerrados no basta. Por ejemplo, un objeto con una cara<br />
parcialmente oculta, como el de la figura, no tiene porqué renderizarse bien:<br />
Figura 35 - Sin ocultaciones Figura 36 - Eliminando caras de detrás<br />
Ahora bien, si sabemos que todos nuestros objetos están cerrados, es<br />
decir, no se ve el interior, podemos combinarlo con el Z-buffer, ya que<br />
descartaremos ya para empezar las caras que no vamos a ver, ganando así en<br />
velocidad de renderización.
Colores y <strong>sombras</strong> 52<br />
Figura 37 - Z-Buffer Figura 38 - Caras de detrás + Z-Buffer<br />
Ahora bien, la combinación de estos dos algoritmos no siempre es<br />
adecuada. En el caso de la tetera, por ejemplo, puesto que la tapa no está<br />
perfectamente ajustada a la tetera, y por tanto, queda un hueco (es decir, se ve<br />
el interior) ¡Si utilizamos el algoritmo de las caras de detrás veremos a través!<br />
Por tanto, en este caso lo mejor es utilizar sólo el algoritmo del Z-buffer.<br />
Figura 39 - Caras de detrás + Z-Buffer Figura 40 - Sólo Z-Buffer<br />
7.8.6. El color de los materiales<br />
La forma en que la luz incide sobre las superficies de los objetos<br />
depende de las propiedades del material de los mismos. En OpenGL la forma<br />
de definir estas propiedades es la función glMaterial cuya sintaxis es void<br />
glMaterial{if}[v](GLenum face, GLenum pname, TYPEparam);<br />
El primer argumento determina la cara del objeto donde se aplica el<br />
material, puede tomar los valores GL_FRONT, GL_BACK, o<br />
GL_FRONT_AND_BACK.<br />
El siguiente argumento indica la propiedad del material que va a fijarse<br />
(sus posibles valores se muestran en la tabla). Finalmente, el argumento param<br />
permite asignar los valores a la propiedad pname.
Colores y <strong>sombras</strong> 53<br />
Nombre del parámetro Valor por<br />
defecto<br />
GL_AMBIENT (0.2, 0.2, 0.2,<br />
1.0)<br />
GL_DIFFUSE (0.8, 0.8, 0.8,<br />
1.0)<br />
Significado<br />
ambient color of material<br />
diffuse color of material<br />
GL_AMBIENT_AND_DIFFUSE ambient and diffuse color of<br />
GL_SPECULAR (0.0, 0.0, 0.0,<br />
1.0)<br />
material<br />
specular color of material<br />
GL_SHININESS 0.0 specular exponent<br />
GL_EMISSION (0.0, 0.0, 0.0,<br />
1.0)<br />
emissive color of material<br />
GL_COLOR_INDEXES (0,1,1) ambient, diffuse, and specular<br />
Reflexión ambiente y difusa<br />
color indices<br />
La reflexión difusa determina el color de un objeto y la reflexión ambiente<br />
la forma en que el objeto redistribuye la luz ambiente que recibe. Los objetos<br />
del mundo real suelen tener el mismo color de reflexión ambiente y difusa.<br />
Reflexión especular<br />
La componente especular define el color de los brillos del objeto cuya<br />
forma se controla con el parámetro GL_SHININESS de modo que cuando<br />
mayor sea este parámetro el brillo aparecerá más concentrado.<br />
Emisión<br />
OpenGL permite asignar a los objetos un color de emisión para que<br />
parezca que dichos objetos emiten luz de un color, lo que permite simular<br />
lámparas y objetos luminosos. Se pueden conseguir mejores efectos simulando<br />
fuentes de luz en la misma posición que los objetos para los que se define un<br />
color de emisión.<br />
Cambio de las propiedades del material<br />
Para minimizar el coste asociado a la realización de cambios en las<br />
propiedades del material se usa la función glColorMaterial cuya sintaxis es la<br />
siguiente:
Colores y <strong>sombras</strong> 54<br />
Propósito: Permite que los <strong>colores</strong> del material sigan el color definido<br />
por glColor.<br />
• Fichero de inclusión: <br />
• Sintaxis: void glColorMaterial(GLenum cara, GLenum modo);<br />
• Descripción: Esta función permite seleccionar las propiedades de un<br />
material sin tener que llamar directamente a glMaterial. Usando esta<br />
función, podemos definir ciertas propiedades del material siguiendo<br />
el color especificado actualmente por glColor. Para habilitar el<br />
seguimiento, llamaremos a glEnable(GL_COLOR_MATERIAL).<br />
• Parámetros:<br />
func<br />
• Retornos: Ninguno.<br />
Cara podrá tomar los valores GL_FRONT_AND_BACK, GL_FRONT o<br />
GL_BACK y modo GL_AMBIENT_AND_DIFFUSE, GL_DIFFUSE,<br />
GL_SPECULAR o GL_EMISIÓN.<br />
Una vez que se realiza la llamada a la función, se puede cambiar el color<br />
de la propiedad que indica el parámetro modo para la cara definida en cara<br />
usando glColor.<br />
Después de llamar a la función glColorMaterial es necesario realizar<br />
una llamada a glEnable con el argumento GL_COLOR_MATERIAL.<br />
glColorMaterial(GL_FRONT, GL_DIFFUSE);<br />
glEnable(GL_COLOR_MATERIAL);<br />
glColor3f(0.2, 0.5, 0.8);<br />
......../* dibujamos algo aquí */<br />
glColor3f(0.9, 0.0, 0.2);<br />
......... /*y otros */<br />
glDisable(GL_COLOR_MATERIAL);<br />
Veamos un ejemplo de todo esto:<br />
#include <br />
Listado 5 - Definiciones para materiales
Colores y <strong>sombras</strong> 55<br />
#include <br />
#include <br />
GLfloat mat_diffuse [] = {0.5, 0.5,<br />
0.5, 1.0};<br />
GLfloat mat_specular [] = {0.5, 0.5,<br />
0.5, 1.0};<br />
GLfloat mat_shininess [] = {50};<br />
void init (void)<br />
{<br />
GLfloat light_position[] = {1.0, 1.0,<br />
1.0, 0.0};<br />
glLightfv(GL_LIGHT0, GL_POSITION,<br />
light_position);<br />
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);<br />
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);<br />
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);<br />
glEnable (GL_LIGHTING);<br />
glEnable (GL_LIGHT0);<br />
glDepthFunc(GL_LEQUAL);<br />
glEnable (GL_DEPTH_TEST);<br />
}<br />
void display (void)<br />
{<br />
int i,j;<br />
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);<br />
for (i=-1; i
Colores y <strong>sombras</strong> 56<br />
glTranslatef((float)i*3.0,(float)j*3.0,0.0);<br />
}<br />
}<br />
}<br />
glutSwapBuffers();<br />
glutSolidSphere(1.0,16,16);<br />
glPopMatrix();<br />
void reshape(int w, int h)<br />
{<br />
glViewport ( 0, 0, w, h );<br />
glMatrixMode ( GL_PROJECTION );<br />
glLoadIdentity ( );<br />
if ( h==0 )<br />
else<br />
1.0, 20.0 );<br />
gluPerspective ( 60, ( float ) w, 1.0, 20.0 );<br />
gluPerspective ( 60, ( float ) w / ( float ) h,<br />
glMatrixMode ( GL_MODELVIEW );<br />
glLoadIdentity ( );<br />
gluLookAt(0.0,0.0,10.0,0.0,0.0,0.0,0.0,1.0,0.0);<br />
}<br />
/* Ciclo principal<br />
* Abre una ventana con tamaño inicial definido, barra de<br />
titulo,<br />
* modo RGB, y control de eventos */<br />
int main (int argc, char** argv)<br />
{<br />
glutInit (&argc, argv);
Colores y <strong>sombras</strong> 57<br />
glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE |<br />
GLUT_DEPTH);<br />
glutInitWindowSize (250,250);<br />
glutInitWindowPosition (100,100);<br />
glutCreateWindow ("Ejemplo de luz");<br />
init ();<br />
/* llamada a inicializacion*/<br />
glutReshapeFunc (reshape); /* llamada<br />
para eventos de reshape de ventana*/<br />
glutDisplayFunc (display); /* llamada<br />
para dibujar...*/<br />
glutMainLoop (); /* Crea la<br />
ventana y dibuja...*/<br />
}<br />
Listado 6 - Ejemplo uso de propiedades de materiales
Colores y <strong>sombras</strong><br />
7.9. Sombras<br />
Una sombra es una región de oscuridad donde la luz es obstaculizada.<br />
Una sombra ocupa todo el espacio de detrás de un objeto opaco con una<br />
fuente de luz frente a él. La sección eficaz de una sombra es una silueta<br />
bidimensional o una proyección invertida del objeto que bloquea la luz.<br />
Cuanto menor es el ángulo entre la dirección de la luz y un objeto<br />
alargado que la obstaculice, más corta será su sombra. Por otro lado, cuanto<br />
menor sea el ángulo entre la dirección de la luz y la superficie en la que<br />
aparece la sombra, más larga será ésta. Si el objeto está cerca de la fuente<br />
luminosa, la sombra será mayor que si el objeto se encuentra lejos. Si la<br />
superficie está curvada, habrá más distorsiones.<br />
Cuando la fuente de luz no es puntual, la sombra se divide en umbra y<br />
penumbra. Cuanto más ancha es la fuente de luz, más difuminada o borrosa<br />
será la sombra.<br />
Si hay múltiples fuentes luminosas, habrá múltiples <strong>sombras</strong>, con las<br />
partes solapadas más oscuras, o con una combinación de <strong>colores</strong>. Cuando una<br />
persona o un objeto está en contacto con la superficie, como una persona<br />
sentada en el suelo o un poste clavado, las <strong>sombras</strong> convergen al punto de<br />
contacto.<br />
Si sólo existe una fuente de luz, las <strong>sombras</strong> arrojadas por aquella serán<br />
siempre grises, sea cual sea el color de la fuente. En cambio, si existen dos<br />
fuentes de luz de distintos <strong>colores</strong>, supongamos rojo y azul, las <strong>sombras</strong><br />
proyectadas por cada una de ellas serán del color de la otra fuente de luz, y<br />
sólo la intersección de ambas <strong>sombras</strong> será gris. Es decir, la sombra de la luz<br />
roja será azul, pues está iluminada por la fuente azul, y viceversa. En el caso<br />
de que existan más fuentes de luz, cada sombra será del color resultante de la<br />
adición de las fuentes que aún iluminan esa zona, permaneciendo en gris las<br />
zonas donde intersecten las <strong>sombras</strong> de todas las fuentes luminosas.<br />
El proceso de sombreado o shading (en el contexto de los gráficos<br />
realizada por ordenador) implica la simulación de computadora (o más<br />
exactamente; el cálculo) como las caras de un polígono se comportarán<br />
cuando es iluminado por una fuente de la luz virtual. El cálculo exacto varía<br />
según no sólo que datos están disponibles sobre la cara sombreada, sino<br />
también la técnica de sombreado.<br />
Generalmente este afecta propiedades de la especularidad y valores de<br />
intensidad, reflexión y transparencia.<br />
Este proceso se realiza durante el renderizado.<br />
El sombreado altera el color de las caras de un modelo 3D basándose<br />
en el ángulo de la superficie con la fuente de luz. Las siguientes imágenes<br />
muestran las diferencias:<br />
58
Colores y <strong>sombras</strong><br />
Figura 42 Imagen renderizada de una caja.<br />
Esta imagen no tiene sombreado de las caras, pero usa líneas en los<br />
bordes para separar las caras.<br />
Figura 43 Imagen sin líneas en los bordes<br />
Aquí se observa como el sombreado altera el color de las 3 caras<br />
basándose en el ángulo de las fuentes de luz.<br />
Figura 44 Imagen son sombreado en las caras<br />
59
Colores y <strong>sombras</strong><br />
7.9.1 Efecto falloff (Distance falloff)<br />
Teóricamente, dos superficies que son paralelas son iluminadas con la<br />
misma intensidad por una fuente de luz distante, como por ejemplo el sol.<br />
Incluso si una superficie está más distante, el ojo ve más en el mismo espacio,<br />
por eso la iluminación parece la misma.<br />
Nótese que en la primera imagen el color de las caras frontales de las<br />
dos cajas son exactamente iguales. Parece que hay una pequeña diferencia en<br />
el punto de encuentro de las caras, pero esto es una ilusión óptica causada por<br />
el borde vertical debajo de donde se encuentran las caras.<br />
En la segunda imagen se puede observar que las superficies de las<br />
caras son brillantes en la caja delantera y más oscuras en la situada en la parte<br />
de atrás. También la superficie sobre la que están pasa de claro a oscuro<br />
según se aleja.<br />
Este efecto falloff produce imágenes que parezcan más realistas.<br />
Figura 45 Cajas renderizadas con OpenGL<br />
Figura 46 Cajas renderizadas con ARRIS CAD, efecto falloff<br />
Un modelo de intensidad puede aplicarse al sombreado de superficies de<br />
varias formas dependiendo del tipo de superficie y de los requisitos de la<br />
aplicación. Los objetos con varias superficies suelen sombrearse de forma<br />
realista con una sola intensidad por cada superficie. Para una superficie curva<br />
60
Colores y <strong>sombras</strong><br />
podríamos aplicar el modelo de intensidad a cada punto de la superficie;<br />
aunque esto produce un efecto muy realista es un proceso muy lento.<br />
Para acelerar el proceso se podría representar una superficie curva<br />
como un conjunto de polígonos y aplicar el modelo de sombreado a cada<br />
plano. Cada una de estas superficies poligonales podría sombrarse después<br />
con intensidad constante o bien podríamos variar el sombrado con valores de<br />
intensidad interpolados.<br />
Los algoritmos de superficies visibles determinan qué superficies ve el<br />
ojo dependiendo de su posición. Los algoritmos de <strong>sombras</strong> determinan que<br />
objetos se ven desde la fuente de luz. Por tanto, estos dos tipos de algoritmos<br />
son esencialmente iguales. Las superficies visibles desde la fuente de luz están<br />
iluminadas, las no visibles están en sombra.<br />
Cuando hay múltiples fuentes de luz una superficie debe clasificarse<br />
respecto a cada fuente de luz. Consideraremos en este tema algoritmos de<br />
sombra para fuentes de luz puntuales. La visibilidad a partir de una fuente<br />
puntual de luz es como la visibilidad en el ojo: “todo o nada”.<br />
Cuando un punto en la superficie no puede verse desde una fuente<br />
puntual de luz, el cálculo de iluminación debe ajustarse para tenerlo en cuenta.<br />
Las áreas en la sombra de todas las fuentes puntuales de luz todavía<br />
están iluminadas por la luz ambiente.<br />
Aunque la utilización de <strong>sombras</strong> requiere el cálculo de la visibilidad de la<br />
fuente de luz, pueden generarse <strong>sombras</strong> falsas sin hacer pruebas de<br />
visibilidad.<br />
7.9.2 Sombreado<br />
La intensidad de luz que se observa en cada superficie de un objeto<br />
depende del tipo de fuentes de luz que la ilumine y de las características de la<br />
superficie del objeto. Algunos objetos tienen superficies brillantes y otros<br />
opacas o mate. Además, algunos objetos se construyen con materiales opacos,<br />
mientras que otros son mas o menos trasparentes. Un modelo de sombreado<br />
para producir intensidades realistas sobre las superficies de un objeto debe<br />
considerar estas propiedades.<br />
Los patrones de sombra generados por un método de superficie oculta<br />
son validos en cualquier posición de visión seleccionada siempre que las<br />
posiciones de la fuente de luz no se alteren. Las superficies que son visibles<br />
desde la posición de visión se sombrean según el modelo de intensidad, con<br />
patrones de superficie y <strong>sombras</strong> anexados. Las superficies visibles que no son<br />
iluminadas por una fuente de punto se les aplica únicamente intensidad de luz<br />
ambiental. Las superficies visibles que son iluminadas por una fuente de puntos<br />
61
Colores y <strong>sombras</strong><br />
se sombrean combinando el modelo de intensidad y la lista de patrones. Las<br />
áreas de sombra proyectada se sombrean únicamente con la intensidad de la<br />
luz ambiental.<br />
Asumiendo que se puede computar vectores normales, dado un conjunto<br />
de fuentes de luz y un observador, los modelos de luz e iluminación<br />
desarrollados pueden aplicarse a cada punto de una superficie.<br />
Lamentablemente, aunque se tenga ecuaciones sencillas para determinarlos<br />
vectores normales, la cantidad de computaciones requeridas puede ser muy<br />
grande. Se han visto muchas de las ventajas de usar modelos poligonales para<br />
los objetos. Una ventaja adicional, para polígonos planos, es que se puede<br />
reducir bastante el trabajo requerido para el sombreado. La mayoría de los<br />
sistemas gráficos, incluyendo OpenGL, explota las posibles eficiencias para<br />
polígonos planos, descomponiendo superficies curvas en muchos polígonos<br />
planos pequeños, cada uno teniendo un vector normal bien definido.<br />
7.9.3 Tipos de sombreado<br />
7.9.3.1 Sombreado plano (Flat Shading)<br />
Es una técnica usada en gráficos 3D en la que se sombrea cada<br />
polígono de un objeto basándose en el ángulo que existe entre la superficie<br />
normal del polígono y la dirección de la fuente de luz, sus respectivos <strong>colores</strong> y<br />
la intensidad de la luz. Es el tipo de sombreado utilizado para el renderizado de<br />
alta velocidad donde técnicas de sombreado más avanzadas tienen un coste<br />
computacional excesivo.<br />
La desventaja del sombreado de intensidad constante es que da a los<br />
modelos con un número bajo de polígonos un aspecto poco natural, formado<br />
por múltiples caras. A veces esta apariencia puede ser ventajosa, como al<br />
modelar objetos poligonales. Los diseñadores a veces usan esta técnica para<br />
observar las diferentes caras del objeto que están creando.<br />
Bajo ciertas restricciones se puede obtener un sombreado realista en un<br />
objeto con superficies planas utilizando intensidades con superficies<br />
constantes. Si el objeto está únicamente expuesto a luz ambiental y no se<br />
aplican texturas, <strong>sombras</strong> de superficie, etc., el sombreado de intensidad<br />
constante genera representaciones exactas de la superficie del objeto. Para<br />
objetos cuya superficie se ilumina con un foco de luz puntual el modelo produce<br />
una superficie de intensidad constante siempre que el punto de referencia<br />
visual y el foco estén suficientemente alejados de la superficie del objeto. Si por<br />
el contrario el foco está alejado de la superficie no hay variación en la dirección<br />
hacia la fuente. La dirección hacia un punto de visión distinto no cambiara<br />
sobre una superficie, por lo tanto V.R = cte.<br />
Si se representa mediante un conjunto de superficies planas una<br />
superficie curva y los planos que subdividen esta superficie se hacen lo<br />
suficientemente pequeños. Se pueden sombrear con intensidades de superficie<br />
constante.<br />
62
Colores y <strong>sombras</strong><br />
Cuando la orientación entre planos adyacentes cambia en forma<br />
abrupta, la diferencia en intensidades de superficie puede producir un efecto<br />
áspero e irreal. Se pueden aliar las discontinuidades de intensidad en estos<br />
casos variando la intensidad sobre cada superficie de acuerdo con algún<br />
esquema de interpolación.<br />
Existen otro tipo de técnicas de sombreado más avanzadas como el<br />
sombreado de Gouraud y el sombreado de Phong.<br />
Figura 47 Comparación de las técnicas de sombreado<br />
7.9.3.2 Sombreado de Gouraud<br />
Creada en 1971 y llamada así en honor a Henri Gouraud, este método<br />
es usado para simular el efecto de difusión de de la luz y los <strong>colores</strong> a través<br />
de la superficie del objeto, esta técnica consigue alcanzar el sombreado de<br />
superficies con pocos polígonos sin el alto coste computacional de calcular la<br />
iluminación de cada píxel.<br />
El sombreado de Gouraud aplica el patrón de iluminación a cada<br />
vértice del polígono y entonces promedia los valores de color en toda la<br />
superficie del objeto para así alcanzar un efecto de sombreado suave<br />
que parece más realista sobre superficies curvas.<br />
Este método de sombreado se emplea para disimular los polígonos<br />
cuando éstos se emplean para aproximar una superficie curva, como una<br />
esfera o un toroide, por ejemplo.<br />
El método es el siguiente: primero calculamos las normales a la<br />
superficie en los vértices de los polígonos. Esta normal en cada punto podemos<br />
calcularla de dos maneras: 1ª-basándonos las características de la superficie<br />
que vamos a aproximar, por ejemplo si se trata de una esfera, sabemos que la<br />
normal va a ir en dirección opuesta al centro de la esfera. 2ª- Si no conocemos<br />
la superficie que estamos aproximando, podemos sumar todas las normales de<br />
los polígonos de los que forme parte ese vértice y normalizar el resultado.<br />
63
Colores y <strong>sombras</strong><br />
Una vez hecho esto, calculamos por los procedimientos de iluminación<br />
vistos anteriormente el color que correspondería a cada vértice. Después,<br />
cuando vamos a dibujar el polígono, vamos interpolando linealmente a través<br />
de cada arista entre los dos <strong>colores</strong> de los extremos de dicha arista, y por<br />
último al ir trazando las líneas horizontales (o scanlines) que forman el<br />
polígono, interpolamos de nuevo linealmente entre los dos valores que<br />
correspondan a los puntos de las dos aristas entre las que estemos trazando la<br />
línea horizontal. El resultado final de todo esto es un polígono con un suave<br />
gradiente de intensidades sobre su superficie.<br />
Se puede ver gráficamente esto con el ejemplo de<br />
la figura 48, en la que conocemos los valores de la<br />
intensidad en los puntos 1 2 y 3. Al ir dibujando el<br />
triángulo, calculamos los valores del primer y el ultimo<br />
píxel del triangulo en cada línea interpolando, a lo largo<br />
de las aristas, los valores de los vértices. Esto nos da el<br />
valor inicial y el final de cada línea horizontal, y para<br />
rellenarla solo tenemos que interpolar linealmente de<br />
nuevo los estos valores a lo largo de la línea.<br />
Un vector normal a una superficie es un vector<br />
que apunta en una dirección perpendicular a dicha<br />
superficie. Si partimos de un triángulo, con tres vértices<br />
P1, P2 y P3, el procedimiento para calcular la normal es<br />
muy sencillo; se escoge un punto como origen, digamos<br />
P2, y se calculan los vectores v1=P1-P2, y v2=P3-P2;<br />
calculamos el producto vectorial entre V1 y V2, y nos sale<br />
el vector normal.<br />
Además, puesto que el vector normal prácticamente<br />
solo se va a usar para calcular su ángulo con otros<br />
vectores, es muy útil hacer que su módulo sea uno,<br />
dividiendo cada una de las componentes (x,y,z) entre el<br />
módulo del vector.<br />
En la figura se ve un triángulo con su vector normal. Una cosa que hay<br />
que tener en cuenta al calcular un vector normal a un triangulo, es que el<br />
producto vectorial no cumple la propiedad<br />
conmutativa, o sea que hay que tener cuidado<br />
porque según en que orden se multipliquen v1 y v2<br />
el vector normal puede apuntar en una dirección o<br />
en la opuesta.<br />
La aplicación de las normales a la hora de<br />
acelerar el dibujado de polígonos es la siguiente:<br />
como normalmente los triángulos se usan para<br />
representar aproximaciones a superficies, como por<br />
ejemplo esferas, se puede considerar que tales<br />
64<br />
Figura 48 - Scanlines<br />
Figura 49 - Normal<br />
Figura 50 - Normales
Colores y <strong>sombras</strong><br />
superficies tienen una cara interior que no se ve (el interior de la esfera, p ej) y<br />
una exterior que si se ve. Entonces, podemos calcular las normales a los<br />
triángulos asegurándonos de que apunten al exterior de la superficie, y<br />
después eliminar los polígonos cuya normal no apunte en dirección a la<br />
pantalla, porque se entiende que estamos viendo su parte trasera y por tanto<br />
no se dibuja. En la figura vemos un ejemplo en 2D de este método. En este<br />
caso, hay una serie de segmentos que aproximan una circunferencia.<br />
Descartamos por medio de las normales las caras 4, 5, 6 y 7 y dibujamos las<br />
caras 1 2 y 3. A estas tres caras que vamos a dibujar hay que aplicarles otro<br />
algoritmo para verificar superficies ocultas, como el del pintor o el buffer z, ya<br />
que el método de las normales no garantiza que las caras que apuntan hacia la<br />
cámara no vayan a estar parcial o totalmente tapadas por otro objeto.<br />
Algunas veces los objetos sombreados con Gouraud muestran las zonas<br />
de unión de polígonos conocido como el efecto de la banda de Mach. Este<br />
fenómeno es una consecuencia de como se conectan los conos al nervio óptico<br />
en el ojo, y no hay nada que se pueda hacer al respecto, fuera de buscar<br />
técnicas de sombreado mas suaves que no produzcan grandes diferencias en<br />
sombreado en los bordes de los polígonos.<br />
7.9.3.3 Sombreado de Phong<br />
Figura 51 Sombreado Gouraud banda de Mach<br />
Es el método usado en los gráficos 3D para la interpolación de<br />
superficies en el pasterizado de polígonos, para obtener mejor resolución<br />
especular que en las generadas en el modelo de reflexión de Pong.<br />
Este método fue desarrollado por Bui Tuong Phong en 1973 en la<br />
universidad de Utah. El modelo de reflexión de Phong es un modelo de<br />
iluminación local que puede producir un cierto grado de realismo en los objetos<br />
3D mediante la combionación de e elementos: difusión, reflexión especular y<br />
luz ambiente para cada punto de la superficie considerada.<br />
65
Colores y <strong>sombras</strong><br />
La interpolación de Phong , como método de renderizado, se peude<br />
considerar como una mejora del sombreado de Gouraud que proporciona una<br />
mejor aproximación a la aplicación punto-por-punto de un modelo de reflexión<br />
superficial, asumiendo una suavidad variante de la superficie como vector<br />
normal.<br />
Para ello se determina el vector normal promedio en cada vértice del<br />
polígono. Se interpola linealmente los vértices normales sobre la superficie del<br />
polígono. Se aplica un modelo de iluminación sobre los puntos de la superficie<br />
utilizando las normales interpoladas.<br />
Phong propuso que, en lugar de interpolar intensidades de los vértices,<br />
según se hace en el sombreado Gouraud, se interpole normales a lo largo del<br />
polígono. Para un polígono que comparte lados y vértices con otros polígonos,<br />
Figura 52 - Esquema<br />
se pueden computar normales en los vértices interpolando sobre las normales<br />
de los polígonos que comparten el vértice. Luego, se puede usar interpolación<br />
bilineal, para interpolar las normales sobre el polígono<br />
Figura 53 - Esquema<br />
Se puede usar las normales interpoladas en los vértices A y B para<br />
interpolar a lo largo de lado entre ellas:<br />
n( ) = (1- )nA + nB<br />
Se puede hacer una interpolación similar en todos los lados. LA normal<br />
en cualquier punto interior se puede obtener de los puntos en los lados<br />
mediante<br />
n( , ) = (1- )nC + nD<br />
66
Colores y <strong>sombras</strong><br />
Una vez obtenidas las normales en cada punto, se puede hacer cálculos<br />
de sombreado independientes. Normalmente, este proceso se combinará con<br />
la rasterización del polígono, para que la línea entre C y D proyecte a una línea<br />
de rastreo en el frame buffer.<br />
7.9.3.4 Sombreado Blinn–Phong<br />
Es una variante del modelo de reflexión de Phong que intercambia la<br />
precisión visual por eficiencia computacional.<br />
En sombrado de Phong solo se recalcula el ángulo R*V entre el<br />
observador (V) y el rayo de luz de la fuente (L) reflejado (R) en una superficie.<br />
Si en vez de eso se calcula el vector intermedio entre el observador y los<br />
vectores de las fuentes de luz:<br />
Podemos reemplazar R*V con N*H, este producto de puntos representa<br />
el coseno de un ángulo que es la mitad del ángulo representado por el producto<br />
de puntos de Phong si V,L y R se encuentran en el mismo plano. Esto produce<br />
modelos empíricos más certeros para determinar la distribución de las<br />
funciones de reflexión bidireccional que el modelo de Phong. Blinn-Phong es el<br />
modelo de sombreado por defecto que utiliza OpenGL y se lleva a todos los<br />
vértices según pasan por la tubería de gráficos, mientras que los valores de los<br />
pixeles entre los vértices son interpolados por el sombreado de Gouraud<br />
(menos costoso).<br />
Figura 54 Sombreado de Phong y Blinn-Phong<br />
67
Colores y <strong>sombras</strong><br />
7.9.4 Sombreado en OpenGL<br />
Se especifica la técnica de sombreado deseada con la función<br />
glShadeModel.<br />
Void glShadeModel(Glenum mode);<br />
El parámetro mod puede tener 2 valores GL_SMOOTH (por defecto) o<br />
GL_FLAT.<br />
7.9.4.1 Sombreado Plano (Flat)<br />
Los tres vectores, l, n y v, pueden variar según se va entre puntos sobre<br />
una superficie.<br />
*Para un polígono plano, n es constante.<br />
*Si se asume un observador distante (la bandera<br />
GL_DISTANT_VIEWER en OpenGL), v es constante sobre el polígono.<br />
*Si la fuente de luz es distante, l es constante.<br />
Distante se puede interpretar como una fuente o un observador en el<br />
infinito; en particular, si los polígonos son pequeños, las distancias relativas<br />
para el infinito no tienen que ser muy grandes. Los ajustes necesarios, como<br />
cambiar la ubicación de la fuente u observador a la dirección de la fuente u<br />
observador, de forma correspondiente, puede hacerse a las ecuaciones de<br />
sombreado y a su implementación.<br />
Si los tres vectores son constantes, entonces el cálculo de sombreado<br />
se lleva a cabo una sola vez para cada polígono, y se asignará la misma<br />
sombra a cada punto en el polígono. Esta técnica se conoce como sombreado<br />
plano o constante. En OpenGL, se especifica sombreado plano mediante<br />
glShadeModel(GL_FLAT);<br />
Si se usa sombreado plano, OpenGL usará las normales asociadas con<br />
el primer vértice de un polígono<br />
Sencillo para el cálculo de sombreado. Para primitivas como un strip de<br />
triángulo, OpenGL usa la normal del tercer vértice para el primer triángulo, la<br />
normal del cuarto vértice para el segundo, etc. Reglas similares se aplican para<br />
otras primitivas, como strips cuadriláteros.<br />
Sombreado plano mostrará diferencias de sombreado entre los<br />
polígonos. Si las fuentes de luz y el observador están cerca del polígono, los<br />
vectores v y l serán diferentes para cada polígono. Sin embargo, si los<br />
polígonos se diseñaron para modelar una superficie suave, sombreado plano<br />
no será el mas apropiado, ya que se verán aunque sea diferencias de<br />
sombreado pequeñas entre polígonos adyacentes.<br />
68
Colores y <strong>sombras</strong><br />
Figura 55 Variación se sombreado<br />
El sistema visual humano tiene una sensibilidad remarcada para<br />
pequeñas diferencias de intensidad de color, causada por la propiedad de<br />
inhibición lateral. Si se ve una secuencia incremental de intensidades, se<br />
percibe los incrementos de brillantez reforzados en un lado del intervalo de<br />
intensidad y decremento de brillantez reforzado del otro lado<br />
Ejemplo de código en Open GL<br />
Figura 56 Percepción de intensidad<br />
glShadeModel(GL_FLAT);<br />
glBegin(GL_TRIANGLES);<br />
glColor3f(1.0f, 0.0f, 0.0f); // activamos el color rojo<br />
glVertex3f(-1.0f, 0.0f, 0.0f);<br />
glColor3f(0.0f, 1.0f, 0.0f); // activamos el color verde<br />
glVertex3f(1.0f, 0.0f, 0.0f);<br />
glColor3f(1.0f, 0.0f, 0.0f); // activamos el color azul<br />
glVertex3f(0.0f, 1.0f, 0.0f);<br />
glEnd();<br />
Figura 57 Sombreado G_FLAT<br />
69
Colores y <strong>sombras</strong><br />
El triángulo se rellena con el color azul, puesto que el modelo de<br />
sombreado es GL_FLAT y el color activo en la definición del último vértice es el<br />
azul.<br />
7.9.4.2 Sombreado Interpolativo y Gouraud<br />
Si se asigna el modelo de sombreado para que sea suave, mediante<br />
glShadeModel(GL_SMOOTH);<br />
OpenGL interpolará <strong>colores</strong> para las primitivas, como las líneas. Si se permite<br />
sombreado y luz suaves, y se asigna a cada vértice la normal del polígono<br />
siendo sombreado, se calcularía la luz en cada vértice, determinando el color<br />
del vértice, usando las propiedades materiales y los vectores v y l se computan<br />
para cada vértice. Si la fuente de luz es distante, y el observador es distante o<br />
no hay reflexiones especulares, entonces el sombreado interpolativo<br />
sombreara un polígono con un color constante.<br />
Desde la perspectiva de OpenGL, el sombreado Gouraud es<br />
deceptivamente sencillo. Se necesita solamente asignar correctamente las<br />
normales de vértices. La literatura a menudo no distingue entre el sombreado<br />
interpolativo y el Gouraud. Sin embargo, existe un problema, encontrar las<br />
normales para promediar. Si el programa es lineal, especificar una lista de<br />
vértices (y otras propiedades), no se tiene la información necesaria de cuales<br />
polígonos comparten un vértice. Lo que se requiere es una estructura de datos<br />
para representar un "mesh". Atravesar esta estructura de datos puede generar<br />
los vértices con las normales promediadas. Tal estructura de datos debe<br />
contener, de manera mínima, polígonos, vértices, normales, y propiedades de<br />
los materiales. Una posible estructura se muestra en al siguiente figura,<br />
teniendo como elemento clave los polígonos que se juntan en cada vértice<br />
Figura 58 Estructura de datos para facilitar sombreado<br />
70
Colores y <strong>sombras</strong><br />
Ejemplo de código OpenGL<br />
glShadeModel(GL_SMOOTH);<br />
glBegin(GL_TRIANGLES);<br />
glColor3f(1.0f, 0.0f, 0.0f); // activamos el color rojo<br />
glVertex3f(-1.0f, 0.0f, 0.0f);<br />
glColor3f(0.0f, 1.0f, 0.0f); // verde<br />
glVertex3f(1.0f, 0.0f, 0.0f);<br />
glColor3f(1.0f, 0.0f, 0.0f); // azul<br />
glVertex3f(0.0f, 0.0f, 1.0f);<br />
glEnd();<br />
7.9.4.3 Stencil Buffer<br />
Figura 59 Sombreado GL_SMOOTH<br />
Sirve para mejorar la calidad de las <strong>sombras</strong> y los reflejos.<br />
Es un test extra por píxel y un conjunto de operaciones muy parecidas al<br />
Z-Buffer.<br />
Añade planos de bits adicionales para cada píxel además de los bits de<br />
color y profundidad.<br />
Es una manera de marcar píxeles en una renderización para controlar su<br />
actualización en renderizaciones siguientes.<br />
El valor stencil de un píxel es un entero sin signo (unsigned int).<br />
Para activar y desactivar el test de stencil se utilizará la función<br />
glEnable(GL_STENCIL_TEST) y glDisable(GL_STENCIL_TEST).<br />
Para borrar el stencil buffer se usará la función glClearStencil cuya<br />
sintaxis es la siguiente:<br />
71
Colores y <strong>sombras</strong><br />
• Propósito: Especifica un valor de estarcido para el buffer de estarcido.<br />
• Fichero de inclusión: <br />
• Sintaxis: void glClearStencil(GLint valor);<br />
• Descripción: Esta función selecciona el valor de color que usaremos<br />
para borrar el buffer de estarcido con<br />
glClear(GL_STENCIL_BUFFER_BIT).<br />
• Parámetros:<br />
valor<br />
GLint: el valor de limpieza del buffer de estarcido.<br />
• Retornos: Ninguno.<br />
El stencil test compara el valor del píxel del stencil buffer con un valor de<br />
referencia. Permite las comparaciones: never, always, less than, less than or<br />
equal, greater than, greater than or equal, equal, not equal.<br />
Es más potente que el buffer de profundidad. Antes de comparar realiza<br />
una operación AND tanto del valor de referencia como del valor del buffer, con<br />
un valor que sirve como máscara.<br />
GlStencilFunc(GL_EQUAL, 0x1,0xff).<br />
El primer parámetro será la función de comparación, el segundo el valor<br />
de referencia y el tercero la máscara.<br />
Si el píxel no pasa el test de profundidad es rechazado, en cambio, si lo<br />
pasa, se reemplaza el valor del Z-Buffer. El stencil test es más complicado:<br />
- No pasa el stencil test<br />
- Pasa stencil test y no el test de profundidad<br />
- Pasa stencil test y test de profundidad<br />
Para cada caso tenemos 6 operaciones distintas: GL_KEEP,<br />
GL_REPLACE, GL_INVERT, GL_INCREMENT, GL_DECREMENT, GL_ZERO.<br />
Antes de escribir se aplica un máscara:<br />
GlStencilOp(GL_KEEP //Stencil fail<br />
GL_DECR //Pasa el stencil y falla la profundidad<br />
GL_INCR //Pasa el stencil y pasa la profundidad)<br />
GlStencilMask(0xff);<br />
72
Colores y <strong>sombras</strong><br />
State Initial Value State Update State Query Token<br />
Description<br />
Command<br />
Stencilling GL_FALSE glEnable GL_STENCIL_TEST<br />
enable<br />
glDisable<br />
Stencil<br />
function<br />
GL_ALWAYS glStencilFunc GL_STENCIL_FUNC<br />
Stencil<br />
compare<br />
mask<br />
All 1’s glStencilFunc GL_STENCIL_VALUE_MASK<br />
Stencil<br />
reference<br />
value<br />
0 glStencilFunc GL_STENCIL_REF<br />
Stencil fail GL_KEEP<br />
operation<br />
glStencilOp GL_STENCIL_FAIL<br />
Stencil GL_KEEP glStencilOp GL_STENCIL_PASS_DEPTH_PASS<br />
depth fail<br />
operation<br />
Stencil<br />
depth pass<br />
operation<br />
GL_KEEP glStencilOp GL_STENCIL_PASS_DEPTH_PASS<br />
Stencil<br />
write mask<br />
All 1’s glStencilMask GL_STENCIL_WRITEMASK<br />
Stencil<br />
buffer clear<br />
value<br />
0 glClearStencil GL_STENCIL_CLEAR_VALUE<br />
Tiene una serie de limitaciones:<br />
- El objeto reflejado sale por fuera de la superficie reflectante<br />
- Desde detrás del espejo se ve el objeto reflejado.<br />
- No permite reflejos infinitos. Está limitado a n reflejos.<br />
A continuación se muestra el algoritmo para el empleo del stencil para<br />
simular <strong>sombras</strong>:<br />
1.- Cargar la matriz de modelización.<br />
GlMatrixMode(GL_MODELVIEW);<br />
GlLoadIdentity();<br />
GlLookAt(eye[0], eye[1], eye[2], center[0], center[1], center[2], up[0],<br />
up[1], up[2]);<br />
2.- Dada la luz y la ecuación del plano donde se proyecta, asumiendo que el<br />
objeto esta entre la luz y el plano, habilitar la luz y renderizar el objeto y el<br />
plano<br />
Glfloat lightPosition[4]={LX,LY,LZ,1.0);<br />
Glfloat groundPlaneEquation[4]={A,B,C,D};<br />
73
Colores y <strong>sombras</strong><br />
GlLightfv{GL_LIGHT0, GL_POSITION,lightPosition);<br />
GlEnable(GL_LIGHT0);<br />
GlEnable(GL_LIGHTING);<br />
DibujarObjeto();<br />
DibujarPlano();<br />
3.- Meter en la pila la matriz de modelización<br />
glPushMatrix();<br />
4.- Construir la matriz de proyección, multiplicar la matriz de modelización<br />
por la matriz de proyección de la sombra.<br />
Glfloat Matriz[4][4];<br />
ShadowMatrix(&matriz[0][0], LightPosition, groundPlaneEquation);<br />
glHultMatrix(&Matriz[0][0]);<br />
5.- Asignar un valor distinto de 0 al stencil buffer<br />
glEnable(GL_STENCIL_BUFFER);<br />
glStencilFunc(GL_ALWAYS, valor, ~0);<br />
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);<br />
DibujarPlanoASombrear();<br />
GlDisable(GL_STENCIL_TEST);<br />
6.- Deshabilitar la iluminación<br />
glDisable(GL_LIGHTING);<br />
glEnable(GL_BLEND);<br />
glBlendFunc(GL_DST_COLOR,GL_ZERO);<br />
glColor3f(0.5,0.5,0.5);<br />
glDisable(GL_DEPTH_TEST);<br />
Solo debemos actualizar los pixeles marcados con valor<br />
GlEnable(GL_STENCIL_TEST);<br />
GlStencilFunc(GL_EQUAL, valor, ~0);<br />
GlStencilOp(GL_KEEP, GL_KEEP,GL_ZERO);<br />
DibujarObjeto();<br />
7.- Restaurar los valores<br />
74
Colores y <strong>sombras</strong><br />
glDisable(GL_BLEND);<br />
glDisable(GL_STENCIL_TEST);<br />
glEnable(GL_DEPTH_TEST);<br />
glPopMatrix();<br />
7.9.4.4 Buffer de Profundidad o Z buffer<br />
Este buffer se utiliza para el manejo de las coordenadas de profundidad<br />
de la imagen 3D. Esta es una solución al problema de visibilidad, para detectar<br />
que objetos de una imagen renderizada son visibles y cuales no. Cuando un<br />
objeto es renderizado por una tarjeta gráfica 3D, la profundidad de cada píxel<br />
es almacenada en un buffer (z-buffer). Este está normalmente formado por un<br />
array bidimensional con un elemento para cada píxel de la pantalla. Si otro<br />
objeto de la escena tiene q renderizarse en el mismo píxel, la tarjeta gráfica<br />
compara las dos profundidades y elige la que está más cercana al observador.<br />
Entonces la profundidad elegida es almacenada en el z-buffer, reemplazando a<br />
la anterior. Al final este buffer permite a la tarjeta gráfica reproducir fielmente la<br />
percepción de profundidad, un objeto cercano tapa a los de más lejos. La<br />
granularidad del z-buffer tiene una gran influencia en la calidad de la imagen:<br />
un buffer de 16 bits puede finalizar en conflicto cuando dos objetos están muy<br />
cercanos. Uno de 24 o 32 se comporta mucho mejor y uno de 8 casi nunca se<br />
usa porque tiene muy poca precisión.<br />
Figura 60 Buffer de profundidad<br />
75
Colores y <strong>sombras</strong><br />
7.9.5. Volúmenes de <strong>sombras</strong><br />
Para construir un volumen de <strong>sombras</strong> básicamente se proyecta un rayo<br />
de luz a través de cada vértice en la proyección de la sombra del objeto hacia<br />
algún punto (normalmente el infinito). El conjunto de estas proyecciones<br />
generan un volumen que engloba todos los puntos que pudieran posiblemente<br />
verse ensombrecidos por un objeto. Cualquier objeto dentro de este volumen<br />
debería ser ensombrecido. El volumen es presentado de tal modo que causa<br />
píxeles ensombrecidos tener valores estarcidos. que difieren de aquellos<br />
píxeles no sombreados.<br />
Para un modelo poligonal, el volumen esta formado normalmente por la<br />
clasificación de cada cara en el modelo ya sea encarándose hacia la fuente de<br />
luz o en su contra. El conjunto de todos los bordes que conectan la cara “hacia”<br />
con la cara “contra” forman la silueta con respecto a la fuente de luz. Los<br />
bordes que forman la silueta son excluidos de la luz para construir las caras del<br />
volumen de sombra. Este volumen debe extenderse sobre el rango total de la<br />
escena visible; a veces las dimensiones del volumen de sombra se extienden<br />
hasta el infinito. Para formar un volumen cerrado, el frente y la trasera de esta<br />
extrusión deben ser cubiertas. Estas cubiertas se llaman “caps”. Dependiendo<br />
del método usado para el volumen de sombra, el frente puede cubrir al objeto<br />
mismo y la parte trasera puede ser omitida.<br />
Los pasos para formar un volumen de <strong>sombras</strong> son:<br />
• Encontrar todos los bordes de siluetas.<br />
• Extender todos los bordes en dirección al foco de luz<br />
• Añadir la capa frontal y trasera a cada superficie para formar un<br />
volumen cerrado.<br />
Figura 61 Volumen de <strong>sombras</strong><br />
76
Colores y <strong>sombras</strong><br />
Determinar y visualizar el volumen ensombrecido es la parte más<br />
compleja de la técnica. Aunque se esté utilizando un método muy simple para<br />
la creación de volúmenes de <strong>sombras</strong> de geometría simple en este trabajo no<br />
sería eficiente para el caso de miles de polígonos. También puede ocurrir que<br />
el método cause algunos lugares donde los bordes de las <strong>sombras</strong> de los<br />
volúmenes se encuentren. ( Debido a que hay un único volumen sombreado<br />
para cada polígono). Esto puede solucionarse visualizando un único volumen<br />
que rodee el modelo entero en lugar de presentar los distintos volúmenes de<br />
cada polígono separados.<br />
Efectos a tener en cuenta son:<br />
• Umbría y penumbra para producir una transición gradual<br />
• La forma, tamaño y distancia de las fuentes de luz<br />
• La iluminación global<br />
Figura 62 Efecto de la fuente en la sombra<br />
Figura 63 Volumen <strong>sombras</strong> en un triángulo<br />
Existen 3 técnicas que usan el stencil buffer para renderizar las <strong>sombras</strong><br />
con volúmenes de <strong>sombras</strong> lo suficientemente rápido como para utilizarlas en<br />
aplicaciones de tiempo real, paso de profundidad, fallo en profundidad y OR<br />
exclusivo, pero todos ellos utilizan el mismo proceso:<br />
-renderizar la escena como si estuviera completamente en sombra.<br />
- para cada punto de luz:<br />
-usar la información de profundidad de la escena para construir una<br />
mascara en el stencil buffer que tiene huecos solo donde la superficie visible<br />
no es una sombra<br />
-Renderizar la escena de nuevo como si estuviera completamente<br />
iluminada, usando el stencil buffer para la máscara de las áreas sombreadas.<br />
77
Colores y <strong>sombras</strong><br />
La diferencia entre estos métodos ocurre en el segundo paso de la<br />
generación de la máscara. Unos requieren un paso, otros dos y requieren<br />
diferente nivel de precisión para el stencil buffer.<br />
7.9.5.1 Paso de profundidad (Depth pass)<br />
Heidemann propuso que si el frente de las superficies y la trasera de las<br />
<strong>sombras</strong> eran renderizadas en pasos separados, el número de caras frontales<br />
y traseras de un objeto puede ser contado usando el stencil buffer. Si la<br />
superficie de un objeto esta en sombra, habrá más superficies sombreadas<br />
frontalmente entre ella y el ojo que con las superficies traseras sombreadas. Si<br />
su número es igual, sin embargo, la superficie del objeto no es una sombra.<br />
7.9.5.2 Error de Profundidad (Depth fail)<br />
Sobre el 200 algunas personas descubrieron que el método de<br />
Heidmann puede trabajar desde cualquier punto de la cámara reinvirtiendo la<br />
profundidad. En vez de contar las caras frontales sombreadas de la superficie<br />
del objeto, las superficies traseras se pueden contar así fácilmente con el<br />
mismo resultado. Esto soluciona el problema de tener el observador en<br />
sombra, pero introduce la condición de que el extremo posterior del volumen de<br />
<strong>sombras</strong> debe ser encapsulado o las <strong>sombras</strong> terminarán perdiéndose donde<br />
los puntos del volumen van al infinito.<br />
7.9.7.3 OR exclusivo<br />
Las dos técnicas anteriores pueden aproximarse mediante la variación<br />
OR exclusivo, que no trata propiamente con la intersección de los volúmenes<br />
de <strong>sombras</strong>, pero ahorra un paso de renderización y solo requiere un bit de<br />
stencil buffer.<br />
7.10 Fusión (Dithering)<br />
Es una técnica usada para crear la ilusión de profundidad de color en<br />
imágenes con una paleta de <strong>colores</strong> limitada. En una imagen con fusión los<br />
<strong>colores</strong> no disponibles en la paleta original son aproximados por una difusión<br />
de los píxel coloreados dentro de la paleta disponible. El ojo humano percibe la<br />
difusión como una mezcla de <strong>colores</strong>.<br />
Figura 64 Ejemplo fusión<br />
78
Colores y <strong>sombras</strong><br />
Esta imagen está formada solo por rojo y azul, pero según se van<br />
haciendo mas pequeños los pixeles el ojo humano empieza a percibir un nuevo<br />
color mezcla de la aproximación de los dos presentes, con lo cual se puede<br />
percibir un color morado no presente en la paleta de <strong>colores</strong> inicial, pero la<br />
imagen sigue estando compuesta solo por rojo y azul.<br />
Figura 65 Imagen sin fusión Figura 66 Imagen con fusión<br />
Se puede obtener una buena calidad de imagen con aproximadamente 8<br />
bits de R,G,B sin utilizar fusión. Sólo porque nuestra maquina tenga 24 planos<br />
de color no significa que la fusión no sea deseable. Por ejemplo, si estamos<br />
ejecutando en modo doble buffer, los planos de color pueden ser divididos en 2<br />
conjuntos de 12, así tendremos sólo 4 bits para cada componente RGB. Sin<br />
fusión 4 bits por componente ofrecen resultados poco satisfactorios.<br />
Figura 67 Incremento de difusión<br />
79
Colores y <strong>sombras</strong><br />
Nota: La fusión al contrario que otras características está habilitada por<br />
defecto.<br />
Se puede deshabilitar con glDisable(GL_DITHER).<br />
Y habilitar con glEnable( GL_DITHER ).<br />
7.11. Creación de Paletas de Ventana<br />
Podemos crear una paleta utilizando la función CreatePalette() e<br />
identificando la paleta mediante un indicador del tipo HPALETTE:<br />
HPALETTE CreatePalette(<br />
CONST LOGPALETTE *lplgpl // puntero a la paleta<br />
lógica de color<br />
);<br />
Esta paleta utiliza una estructura lógica de paleta (LOGPALETE) que<br />
contiene 256 entradas, especificando los 8 bits para las componentes R,G,B.<br />
7.11.1 Arbitraje de paletas<br />
En la publicidad del sistema Windows se afirma que su sistema<br />
operativo es multitarea, por lo tanto se debe permitir la ejecución simultanea de<br />
varias aplicaciones. Pero el hardware solo permite 256 <strong>colores</strong> en la paleta del<br />
sistema que deben ser compartidos por todas las aplicaciones en ejecución. Si<br />
alguna de las aplicaciones modifica la paleta del sistema puede que se altere la<br />
presentación de imágenes de otras aplicaciones produciendo efectos no<br />
deseados. Windows proporciona un conjunto de mensajes para arbitrar el uso<br />
de paletas entre varias aplicaciones. Por lo tanto si una aplicación modifica la<br />
paleta del sistema se notificará este cambio al resto de las aplicaciones en<br />
ejecución.<br />
Cuando una aplicación se convierte en la aplicación activa Windows<br />
envía el mensaje WM_QUERYNEWPALETTE a la ventana principal de la<br />
aplicación, preguntándole si desea copiar las entradas de su paleta privada en<br />
las entradas del sistema. En caso afirmativo la aplicación selecciona la paleta<br />
en el contexto de dispositivo para la ventana actualizada y llama después a<br />
RealizePalette().<br />
Otro mensaje que puede enviar Windows para el arbitraje de las paletas<br />
es WM_PALETTECHANGED que indica a la ventana que puede seleccionar la<br />
paleta, incluso si no es la ventana activa.<br />
En el siguiente ejemplo mostramos la realización de este procedimiento:<br />
// Procedimiento de la ventana, gestiona todos los<br />
mensaje de este programa<br />
LRESULT CALLBACK WndProc (HWND hWnd,UINT<br />
message,WPARAM wParam,LPARAM lParam)<br />
... // Windows le dice a la aplicación que puede<br />
modificar la paleta del sistema.<br />
80
Colores y <strong>sombras</strong><br />
// Es decir, este mensaje solicita una nueva paleta a<br />
la aplicación<br />
case WM_QUERYNEWPALETTE:<br />
// Si la paleta fue creada<br />
if(hPalette)<br />
{<br />
int nRet;<br />
// Selecciona la paleta en el contexto<br />
de dispositivo actual<br />
SelectPalette(hDC, hPalette, FALSE);<br />
//Correspondencia de entradas entre la<br />
paleta actualmente<br />
// seleccionada y la paleta del<br />
sistema. El valor devuelto es<br />
// el número de entradas de la paleta<br />
modificada.<br />
nRet = RealizePalette(hDC);<br />
// Al redibujar se fuerza el<br />
replanteado de la paleta<br />
// en la ventana actual<br />
InvalidateRect(hWnd,NULL,FALSE);<br />
return nRet;<br />
}<br />
break;<br />
// Esta ventana puede seleccionar la paleta,<br />
incluso si no<br />
// es la ventana activa.<br />
case WM_PALETTECHANGED:<br />
// No hacer nada si la paleta no existe, o<br />
si esta<br />
// es la ventana que cambio la paleta<br />
if((hPalette != NULL) && ((HWND)wParam !=<br />
hWnd))<br />
{<br />
// Selecciona la paleta en el contexto<br />
de dispositivo<br />
SelectPalette(hDC,hPalette,FALSE);<br />
// Entrada en la paleta del sistema<br />
RealizePalette(hDC);<br />
// Reasigna los <strong>colores</strong> actuales a la<br />
nueva paleta realizada<br />
UpdateColors(hDC);<br />
return 0;<br />
}<br />
break;}<br />
81
Colores y <strong>sombras</strong><br />
7.11.2. Creación de una paleta.<br />
Determinamos si nuestra aplicación necesita una paleta llamando a la<br />
función DescribePixelFormat() después de haber definido el formato de píxel.<br />
Se ha de comprobar el valor del miembro dwFlags de la estructura<br />
PÍXELFORMATDESCRIPTOR devuelto por DescribePixelFormat(),<br />
comprobaremos el valor del bit PFD_NEED_PALETTE, si estuviese activo<br />
tendríamos que crear una paleta para uso de la aplicación.<br />
7.11.3 Estructura de la paleta.<br />
Para crear una paleta reservaremos memoria para la estructura<br />
LOGPALETTE.<br />
typedef struct tagLOGPALETTE { // lgpl<br />
WORD palVersion;<br />
WORD palNumEntries;<br />
PALETTEENTRY palPalEntry[1];<br />
} LOGPALETTE;<br />
La estructura se ha de completar con información sobre nuestra paleta y<br />
llamar a la función CreatePalette() pasándosela como argumento.<br />
Cada entrada en la paleta es una estructura PALETTEENTRY definida<br />
de la forma:<br />
typedef struct tagPALETTEENTRY { // pe<br />
BYTE peRed;<br />
BYTE peGreen;<br />
BYTE peBlue;<br />
BYTE peFlags;<br />
} PALETTEENTRY;<br />
- peRed, peGreen y peBlue representan las intensidades relativas para las<br />
componentes de 8 bits RGB. Así cada una de las 256 entradas de la paleta<br />
contendrá una definición de color de 24 bits.<br />
- PeFlags se utiliza para especificar opciones avanzadas de la paleta.<br />
Normalmente su valor será NULL.<br />
En el siguiente ejemplo mostramos la creación, arbitraje y estructura de<br />
una paleta:<br />
// Selecciona el formato de píxel para un contexto de<br />
dispositivo<br />
void SetDCPixelFormat(HDC hDC)<br />
{<br />
int nPixelFormat;<br />
static PIXELFORMATDESCRIPTOR pfd = {<br />
82
Colores y <strong>sombras</strong><br />
sizeof(PIXELFORMATDESCRIPTOR), // Tamaño de la<br />
estructura<br />
1,<br />
// Version of this structure<br />
PFD_DRAW_TO_WINDOW | // Dibuja en la ventana (No<br />
en el mapa de bits)<br />
PFD_SUPPORT_OPENGL | // Soporta llamada<br />
OpenGL en la ventana<br />
PFD_DOUBLEBUFFER, // Modo de doble Buffer<br />
PFD_TYPE_RGBA, // Modo de color RGBA<br />
24, // Pide<br />
24 bits de color<br />
0,0,0,0,0,0, // No se usa<br />
para seleccionar el modo<br />
0,0, // No se<br />
usa para seleccionar el modo<br />
0,0,0,0,0, // No se<br />
usa para seleccionar el modo<br />
32, // Tamaño<br />
del Buffer de Profundidad<br />
0, // No se<br />
usa para seleccionar el modo<br />
0, // No se<br />
usa para seleccionar el modo<br />
PFD_MAIN_PLANE, // Dibuja en el plano<br />
principal<br />
0, // No se<br />
usa para seleccionar el modo<br />
0,0,0 }; // No se usa<br />
para seleccionar el modo<br />
// Escoge el formato de píxel que mejor encaje en los<br />
descrito por pfd<br />
nPixelFormat = ChoosePixelFormat(hDC, &pfd);<br />
// Selecciona el formato de píxel para el contexto de<br />
dispositivo<br />
SetPixelFormat(hDC, nPixelFormat, &pfd);<br />
}<br />
// Si es necesario, crea una paleta 3-3-2 para el contexto<br />
de dispositivo listado<br />
HPALETTE GetOpenGLPalette(HDC hDC)<br />
{<br />
HPALETTE hRetPal = NULL; // Indicador a la paleta que<br />
va a crear<br />
PIXELFORMATDESCRIPTOR pfd; // Descriptor del<br />
formato de píxel<br />
LOGPALETTE *pPal; // Puntero a memoria<br />
para la paleta lógica<br />
83
Colores y <strong>sombras</strong><br />
int nPixelFormat; // índice del formato de<br />
píxel<br />
int nColors; // Numero de entradas en<br />
la paleta<br />
int i; // Variable de<br />
cuenta<br />
BYTE RedRange,GreenRange,BlueRange;<br />
// Rango para cada<br />
entrada de color (7,7,y 3)<br />
//Toma el formato de píxel y recupera la descripción<br />
del formato de píxel<br />
nPixelFormat = GetPixelFormat(hDC);<br />
DescribePixelFormat(hDC, nPixelFormat,<br />
sizeof(PIXELFORMATDESCRIPTOR), &pfd);<br />
//¿Necesita una paleta este formato de píxel? Si no,<br />
no crea una paleta<br />
// y devuelve NULL<br />
if(!(pfd.dwFlags & PFD_NEED_PALETTE))<br />
return NULL;<br />
//Numero de entradas en la paleta. 8 bits abarcan 256<br />
entradas<br />
nColors = 1 palVersion = 0x300; // Windows 3.0<br />
pPal->palNumEntries = nColors; // Dimensiones de la<br />
tabla<br />
//Crea una mascara de 1's. esto crea un numero<br />
representado por tener<br />
//activo los bits x de menor orden, donde x =<br />
pfd.cRedBits,<br />
//pfd.cGgreenBits y pfd.cBlueBits.<br />
RedRange = (1
Colores y <strong>sombras</strong><br />
pPal->palPalEntry[i].peRed = (i >> pfd.cRedShift)<br />
& RedRange;<br />
pPal->palPalEntry[i].peRed = (unsigned char)(<br />
(double) pPal->palPalEntry[i].peRed * 255.0<br />
/ RedRange);<br />
pPal->palPalEntry[i].peGreen = (i >><br />
pfd.cGreenShift) & GreenRange;<br />
pPal->palPalEntry[i].peGreen = (unsigned char)(<br />
(double)pPal->palPalEntry[i].peGreen * 255.0<br />
/ GreenRange);<br />
pPal->palPalEntry[i].peBlue = (i >><br />
pfd.cBlueShift) & BlueRange;<br />
pPal->palPalEntry[i].peBlue = (unsigned char)(<br />
(double)pPal->palPalEntry[i].peBlue * 255.0<br />
/ BlueRange);<br />
NULL;<br />
pPal->palPalEntry[i].peFlags = (unsigned char)<br />
}<br />
// Crea la paleta<br />
hRetPal = CreatePalette(pPal);<br />
// Avanza, selecciona y realiza la paleta para este<br />
contexto de dispositivo<br />
SelectPalette(hDC,hRetPal,FALSE);<br />
RealizePalette(hDC);<br />
// Libera la memoria usada para la estructura lógica<br />
de paleta<br />
free(pPal);<br />
// Devuelve el indicador a la nueva paleta<br />
return hRetPal;<br />
}<br />
7.11.4 Destrucción de una paleta.<br />
Debemos crear y realizar la paleta antes de crear o activar el contexto de<br />
dispositivo.<br />
En el siguiente ejemplo mostramos las operaciones necesarias para<br />
crear y destruir una ventana teniendo en cuenta la posible existencia de una<br />
paleta<br />
// Procedimiento de la ventana, gestiona todos los mensaje<br />
de este programa<br />
85
Colores y <strong>sombras</strong><br />
LRESULT CALLBACK WndProc( HWND hWnd,UINT message,<br />
WPARAM wParam, LPARAM lParam)<br />
{<br />
static HGLRC hRC; // Contexto de<br />
generación permanente<br />
static HDC hDC; // GDI privado del<br />
contexto de dispositivo<br />
activa<br />
switch (message)<br />
{<br />
// Creacion de ventana para OpenGL<br />
case WM_CREATE:<br />
// Almacena el contexto de dispositivo<br />
hDC = GetDC(hWnd);<br />
// Selecciona el formato de píxel<br />
SetDCPixelFormat(hDC);<br />
// Crea la paleta<br />
hPalette = GetOpenGLPalette(hDC);<br />
// Crea el contexto de generación y lo<br />
hRC = wglCreateContext(hDC);<br />
wglMakeCurrent(hDC, hRC);<br />
// Llamada a la función de iniciación de la<br />
aplicación<br />
Init();<br />
break;<br />
// Se destruye la aplicación, hay que<br />
limpiar todo!<br />
case WM_DESTROY:<br />
// Desactiva el contexto de generación<br />
actual y lo borra<br />
wglMakeCurrent(hDC,NULL);<br />
wglDeleteContext(hRC);<br />
después de que<br />
ReleaseDC(hWnd,hDC);<br />
// Borra la paleta si fue creada<br />
if(hPalette != NULL)<br />
DeleteObject(hPalette);<br />
// Le dice a la aplicación que termine<br />
// se cierre la ventana<br />
PostQuitMessage(0); break;<br />
86
7.12 Conclusión<br />
En este tema hemos aprendido qué es el color y el sombreado, cual es<br />
la naturaleza de la luz, como la percibe el ojo humano y algunos de los<br />
modelos que se utilizan para su representación.<br />
Hemos visto la necesidad de introducir el sombreado o degradado de<br />
color para obtener un resultado más realista en nuestras escenas.<br />
Se han introducido todas las funciones necesarias para establecer el<br />
color de un objeto, el color con el que se limpia la pantalla, el modelo con el<br />
que se va a realizar el sombreado, la utilización de paletas y su gestión en<br />
OpenGL. Se han proporcionado ejemplos de aplicaciones que hacen uso de<br />
todas para facilitar su comprensión y posterior utilización.<br />
7.13 Otras funciones para luces y <strong>sombras</strong><br />
glAccum<br />
• Propósito: Opera en el buffer de acumulación para establecer los valores de<br />
píxel.<br />
• Fichero de inclusión: <br />
• Sintaxis: void glAccum(GLenum func, GLfloat valor);<br />
• Descripción: Esta función opera en el buffer de acumulación. A excepción de<br />
GL_RETURN, los valores de color se escalan según el parámetro valor y<br />
se añaden o suman al buffer de acumulación. En el caso de<br />
GL_RETURN, los valores de color del buffer de acumulación se escalan<br />
según el parámetro valor y se almacenan en el buffer de color actual.<br />
• Parámetros:<br />
func<br />
GLenum: la función de acumulación aplicada. Las funciones válidas son las<br />
siguientes:<br />
GL_ACCUM: Añade valores de color escalados al buffer<br />
de acumulación.<br />
GL_LOAD: Abre valores de color escalados en el buffer<br />
de acumulación, sustituyendo a los que hubiera antes.<br />
GL_ADD: Añade un color constante a los valores del buffer<br />
de acumulación.<br />
GL_MULT: Multiplica los valores de color en el buffer
Colores y <strong>sombras</strong><br />
de acumulación por un valor constante.<br />
GL_RETURN: Copia el buffer de acumulación en el buffer<br />
de color principal.<br />
• Retornos: Ninguno.<br />
glColorMask<br />
• Propósito: Activa o desactiva la modificación de las componentes de color en<br />
los buffers de color.<br />
• Fichero de inclusión: <br />
• Sintaxis: void glColorMask(GLboolean bRojo, GLboolean bVerde, GLboolean<br />
bBlue, GLboolean bAlfa);<br />
• Descripción: Esta función permite cambios individuales en las componentes<br />
de color en el buffer de color para activarlas o desactivarlas.<br />
• Parámetros:<br />
bRojo<br />
Glboolean: especifica cuándo se puede modificar la componente roja.<br />
bVerde<br />
Glboolean: especifica cuándo se puede modificar la componente verde.<br />
bAzul<br />
Glboolean: especifica cuándo se puede modificar la componente azul.<br />
bAlfa<br />
Glboolean: especifica cuándo se puede modificar la componente alfa.<br />
• Retornos: Ninguno.<br />
glDrawBuffer<br />
• Propósito: Selecciona un buffer de color para dibujar.<br />
• Fichero de inclusión: <br />
• Sintaxis: void glDrawBuffer(GLenum modo);<br />
• Descripción: Esta función selecciona un buffer de color para las operaciones<br />
de dibujo siguientes. Normalmente la usaremos para seleccionar el buffer<br />
frontal u oculto en un contexto de dibujo con doble buffer.<br />
• Parámetros:<br />
modo<br />
Glenum: una constante que selecciona el buffer de color en el que vamos a<br />
trabajar. Puede ser un valor de la siguiente tabla.<br />
88
Colores y <strong>sombras</strong><br />
• Retornos: Ninguno.<br />
Valor de modo Descripción<br />
GL_NONE No se dibuja en ningún buffer de color.<br />
GL_FRONT Dibujamos sólo en el buffer de color frontal (visible).<br />
GL_BACK Dibujamos sólo en el buffer de color trasero (oculto).<br />
GL_FRONT_AND_BACK Dibujamos en ambos buffers de color.<br />
glFog<br />
• Propósito: Especifica los parámetros de niebla.<br />
• Fichero de inclusión: <br />
• Sintaxis:<br />
• void glFogf( GLenum pnombre, GLfloat params);<br />
• void glFogfv( GLenum pnombre, GLfloat *params);<br />
• void glFogi( GLenum pnombre, GLint params);<br />
void glFogiv( GLenum pnombre, GLint *params);<br />
• Descripción: Define los parámetros de niebla. Para dibujar usando niebla,<br />
debemos hacer una llamada a glEnable(GL_FOG).<br />
• Parámetros:<br />
pnombre<br />
Glenum: el parámetro definido. Los nombres válidos son los siguientes:<br />
GL_FOG_COLOR: Color de la niebla.<br />
GL_FOG_DENSITY: Densidad de la niebla.<br />
GL_FOG_END: Distancia más alejada a la que se aplica niebla.<br />
GL_FOG_INDEX: El índice de color usado para niebla si se está<br />
en modo indexado.<br />
GL_FOG_MODE: El tipo de niebla.<br />
GL_FOG_START: La distancia más cercana a la que se aplica la<br />
niebla.<br />
• Retornos: Ninguno.<br />
89
Colores y <strong>sombras</strong><br />
glIndexMask<br />
• Propósito: Evita la modificación de bits individuales del buffer de color.<br />
• Fichero de inclusión: <br />
• Sintaxis: void glIndexMask( GLuint mascara);<br />
• Descripción: Esta función permite enmascarar bits individuales en el buffer<br />
de color indexado. Cuando se activa el bit de máscara, los bits son<br />
modificables; cuando son cero, están protegidos. Esta función sólo se aplica<br />
al modo de color indexado.<br />
• Parámetros:<br />
mascara<br />
GLuint: especifica la máscara binaria que activa o desactiva la escritura en los<br />
bits individuales del buffer de color indexado.<br />
• Retornos: Ninguno.<br />
glIsEnabled<br />
• Propósito: Verifica si una función de OpenGL está activada.<br />
• Fichero de inclusión: <br />
• Sintaxis: Glboolean glIsEnabled(GLenum caract);<br />
• Descripción: Devuelve GL_TRUE si la función especificada ha sido activada,<br />
GL_FALSE en otro caso.<br />
• Parámetros:<br />
caract<br />
GLenum: la función a verificar (ver glEnable).<br />
• Retornos: GLboolean: GL_TRUE si la función está activada, GL_FALSE si<br />
no.<br />
glLogicOp<br />
• Propósito: Selecciona la operación lógica para el modo de color indexado.<br />
• Fichero de inclusión: <br />
• Sintaxis: void glLogicOp( GLenum opcode);<br />
• Descripción: La operación lógica de píxel define la combinación de valores<br />
de píxel. Cuando se especifica un nuevo valor de índice de color para una<br />
90
Colores y <strong>sombras</strong><br />
localización de píxel, se combina lógicamente con el valor del índice de color<br />
actual de ese píxel.<br />
• Parámetros:<br />
opcode<br />
GLenum: especifica el modo lógico de píxel que hay que usar. Son válidos:<br />
GL_CLEAR, GL_SET, GL_COPY, GL_COPY_INVERTED, GL_NOOP,<br />
GL_INVERT, GL_AND, GL_NAND, GL_OR, GL_NOR, GL_XOR, GL_ EQUIV,<br />
GL_AND_REVERSE, GL_AND_INVERTED, GL_OR_REVERSE y<br />
GL_OR_INVERTED.<br />
• Retornos: Ninguno.<br />
glPolygonMode<br />
• Propósito: Selecciona el modo en que se generan los polígonos.<br />
• Fichero de inclusión: <br />
• Sintaxis: void glPolygonMode(Glenum cara, GLenum modo);<br />
• Descripción: Esta función nos permite cambiar la forma en que se generan<br />
los polígonos. Por defecto, los polígonos se rellenan o sombrean con el color<br />
o las propiedades de material actuales. Sin embargo, podemos especificar<br />
que se dibujen sólo los perfiles o los vértices.<br />
• Parámetros:<br />
cara<br />
GLenum: especifica a qué cara de los polígonos afecta el cambio de modo:<br />
GL_FRONT, GL_BACK, GL_FRONT_AND_BACK.<br />
modo<br />
GLenum: especifica el nuevo modo de dibujo. El valor por defecto es GL_FILL,<br />
que produce polígonos sólidos. GL_LINE produce perfiles de polígonos y<br />
GL_POINT sólo traza los puntos de los vértices. La bandera de borde activada<br />
por glEdgeFlag afecta a las líneas y puntos dibujados con GL_LINE y<br />
GL_POINT.<br />
• Retornos: Ninguno.<br />
91
Colores y <strong>sombras</strong><br />
7.14 Bibliografia<br />
"Gráficas por Computador"<br />
Autor: Hearn, Baker<br />
Ed: Prentice Hall<br />
"Computer Graphics: Systems&Concepts"<br />
Autor: Salmon, Slater<br />
Ed: Addison<br />
"Introduction to the GKS"<br />
Autor: Hopgood, Duce<br />
Ed: Academic Press, 86<br />
“Introduction to Computer Graphics”<br />
Autor: Foley, Van Dam<br />
Ed: Addison-Wesley<br />
“Visual Cues”<br />
Autor: Keller<br />
Ed: IEEE, 1993<br />
"Three Dimensional Computer Graphics"<br />
Autor: Watt<br />
Ed: Addison<br />
"Mathematical Elements for Computer Graphics"<br />
Autor: Rogers, Adams<br />
Ed: McGraw<br />
"Curves and Surfaces in Computer Aided Geometric Design"<br />
Autor: Yamaguchi<br />
Ed: Springer<br />
“Interactive Computer Graphics: A Top-Down Approach with OpenGL”<br />
Autor: Angel<br />
Ed: Addison Wesley, 1997<br />
“Computer Graphics 2/e”<br />
Autor: Hearn<br />
Ed: Prentice Hall<br />
“3D Computer Graphics, 2/e”<br />
Autor: Watt<br />
Ed: Addison Wesley<br />
92
Colores y <strong>sombras</strong><br />
“Introduction to Computer Graphics”<br />
Autor: Foley<br />
Ed: Addison Wesley<br />
“OpenGL Programming Guide & Reference Manual”<br />
Autor: Varios<br />
Ed: Addison Wesley<br />
“Inventor Mentor & Toolmaker”<br />
Autor: Varios<br />
Ed: Addison Wesley<br />
“SIGGRAPH '98 Conference Proceedings”<br />
Autor: Varios<br />
Ed: Addison Wesley<br />
Opengl Architecture Review Board, “OpenGL Reference Manual, The Official<br />
Reference Document to OpenGL, Version 1.2 “<br />
Autor: Dave Shreiner<br />
“OpenGL SuperBible, Second Edition (SuperBible)”<br />
Autor: Richard S. Wright Jr., Richard S., Jr. Wright<br />
“OpenGL Programming for the X Window System”<br />
Autor: Mark J. Kilgard<br />
“Computer Graphics : Principles and Practice, Second Edition in C by”<br />
Autor: James D. Foley<br />
OpenGL Architecture Review Board, “OpenGL(r) 1.2 Programming Guide<br />
Autor: Mason Woo, Jackie Neider, Tom Davis, Dave Shreiner<br />
OpenGL Architecture Review Board, “OpenGL(r) 1.2 Programming Guide<br />
Autor: Mason Woo, Jackie Neider, Tom Davis, Dave Shreiner<br />
"COMPUTER GRAPHICS: An object-oriented approach to the art and science"<br />
Autor: Cornel Pokorny<br />
Ed: Franklin, Beedle & Associates Incorporated<br />
93
Colores y <strong>sombras</strong><br />
"COMPUTER GRAPHICS: C version" (2nd. ed. o posterior)<br />
Autores: Donald Hearn and M. Pauline Baker<br />
Ed: Prentice Hall<br />
"COMPUTER GRAPHICS: Principles and practice (C version)"<br />
Autores: J. Foley, A. van Dam, S.K. Feiner and J.F. Hughes<br />
Ed: Addison-Wesley Publishing Company<br />
"COMPUTER GRAPHICS"<br />
Autor: F.S. Hill Jr.<br />
Ed: Macmillan Publishing Co.<br />
"Interactive Computer Graphics: a top-down approach with OpenGL"<br />
Autor: E. Angel<br />
Ed: Addison-Wesley Publishing Company, 1997<br />
"Mathematical Elements for Computer Graphics"<br />
Autores: D.F.Rogers and J.A.Adams<br />
Ed: McGraw Hill, 1.976.<br />
"Principles of Interactive Computer Graphics"<br />
Autores: W. Newman and R. Sproull<br />
Ed: McGraw Hill, 1979.<br />
"Raster Graphics Handbook, Conrac Division, 2nd edition"<br />
Ed: Van Nostrand Reinhold Co., 1.984.<br />
"The Mathematical Structure of Raster Graphics"<br />
Autores: Eugene L. Fiume<br />
Ed: Academic Press, Inc., 1986.<br />
"Windows NT OpenGL: Getting Started."<br />
Autores: Crain, Dennis<br />
Ed: MSDN Library, Technical Articles<br />
OpenGL Programming Guide: The Official Guide to Learning OpenGL, Release 1<br />
Autores: Neider, Jackie, Tom Davis, and Mason Woo<br />
Ed: Addison-Wesley<br />
“Principles of Digital Image Synthesis”<br />
Autores: Glassner<br />
Ed: Morgan Kaufmann Publisher, 1995.<br />
94
Colores y <strong>sombras</strong><br />
Computer Graphics: Principles and Practice (2nd. Ed. in C)<br />
Autores: Foley, van Dam, Feiner, Hughes<br />
Ed: Addison-Wesley Publishing Company, 1993.<br />
Radiosity and Realistic Image Synthesis<br />
Autores: Cohen, Wallace<br />
Ed: Academic Press, 1993.<br />
Computer Graphics Proceedings. Annual Conference Series.<br />
Autores: Varios<br />
Ed: ACM SIGGRAPH (ACM Special Interest Group on Computer Graphics).<br />
Rendering Techniques (Proceedings del EG Workshop on Rendering)<br />
Autores: Varios<br />
Ed: Springer Verlag, años 1994 hasta 1999<br />
OpenGL Architecture Review Board. OpenGL Reference Manual: The Official<br />
Reference Document for OpenGL, Release 1. Reading, MA<br />
Autores: Varios<br />
Ed: Addison-Wesley, 1992<br />
"Advanced 3-D Graphics for Windows NT 3.5: Introducing the OpenGL Interface, Part<br />
I." Microsoft Systems Journal 9 (October 1994)<br />
Autores: Prosise, Jeff<br />
Ed: MSDN Library Archive Edition, Books and Periodicals)<br />
"Advanced 3-D Graphics for Windows NT 3.5: The OpenGL Interface, Part II."<br />
Microsoft Systems Journal 9 (November 1994)<br />
Autores: Prosise, Jeff<br />
Ed: MSDN Library Archive Edition, Books and Periodicals)<br />
"OpenGL I: Quick Start."<br />
Autores: Rogerson, Dale<br />
Ed: (MSDN Library, Technical Articles)<br />
95
Colores y <strong>sombras</strong><br />
"OpenGL II: Windows Palettes in RGBA Mode."<br />
Autores: Rogerson, Dale<br />
Ed: (MSDN Library, Technical Articles)<br />
"OpenGL III: Building an OpenGL C++ Class."<br />
Autores: Rogerson, Dale<br />
Ed: (MSDN Library, Technical Articles)<br />
Using DIBs with Palettes.<br />
Autores: Gery, Ron<br />
Ed: (MSDN Library, Technical Articles)<br />
7.15 Enlaces de interés<br />
http://cannes.itam.mx/Alfredo/Espaniol/Cursos/Grafica/Sombreado.pdf<br />
http://en.wikipedia.org/<br />
http://www.opengl.org/<br />
http://www.dsic.upv.es/users/sig/personales/ramon/esp/GrafInternet.html<br />
http://www.ii.uam.es/~pedro/graficos/teoria/index.html<br />
http://m3d.uib.es/grafica2/Ejemplos.html<br />
http://serdis.dis.ulpgc.es/~atrujill/iga/Practicas2000.htm<br />
http://sgio2.cem.itesm.mx/rudomin/graf99/curso.htm<br />
http://victoryrocio.datablocks.net/i/opengl/<br />
http://www.codexmx.com/macedonia/opengl2.htm<br />
http://www.ldc.usb.ve/~jhony/graficasII/p1/informe1.html<br />
http://www.salleurl.edu/CITeM/grafics/recursos/arxius/cap3.pdf<br />
http://www2.ing.puc.cl/~iic1222/glex<br />
http://giig.ugr.es/~cadii/Doc/Articulo<br />
http://trant.sgi.com/opengl/examples/redbook/redbook.html<br />
96
Colores y <strong>sombras</strong><br />
http://www.eecs.tulane.edu/www/graphics/doc/OpenGL-Man-Pages/index.html<br />
http://giig.ugr.es/~curena/doce/docto/<br />
http://odra.dcs.fi.uva.es/area2/opengl/colorysombra.html<br />
http://odra.dcs.fi.uva.es/area2/opengl/refgl.html<br />
http://giig.ugr.es/~curena/doce/vr/transparencias/<br />
97