TextoAnimacion en OpenGL

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 37

Animación 3D Lic.

Yony Richard Montoya Burgos

TECNICAS AVANZADAS
DE ANIMACION 3D

OPENGL

Universidad Mayor de San Simón

Facultad de Ciencias y Tecnología

Carreras de Informática y Sistemas

Lic. Yony Richard Montoya Burgos

Cochabamba Bolivia

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

1. Introducción............................................................................................................. 3
2. Puntos, líneas y polígonos (Primitivas OpenGL)...................................................... 3
Puntos......................................................................................................................... 4
Líneas ......................................................................................................................... 5
Polígonos.................................................................................................................... 6
3. Transformaciones en OpenGL................................................................................. 8
4. Iluminación y Color .................................................................................................. 8
Color ........................................................................................................................... 8
Iluminación.................................................................................................................. 9
Definición de los vectores normales............................................................................ 9
Creación de las fuentes de luz .................................................................................. 10
Propiedades del material........................................................................................... 13
Cambio de las propiedades del material ................................................................... 13
5. Conceptos de Control Avanzados ......................................................................... 15
Listas ........................................................................................................................ 15
Vistas ........................................................................................................................ 17
gluLookAt() ............................................................................................................... 17
glOrtho().................................................................................................................... 18
glFrustum() ............................................................................................................... 19
gluPerpespective() .................................................................................................... 19
Matrices .................................................................................................................... 20
Manipulación de la pila de matrices .......................................................................... 21
Blending.................................................................................................................... 22
Transparencias ......................................................................................................... 23
Antialiasing ............................................................................................................... 23
6. Texturas ................................................................................................................ 26
Texturas multiples ..................................................................................................... 28

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

1. Introducción

OpenGL significa Graphic Library. No es por lo tanto ningún lenguaje de programación,


sino tan sólo un conjunto de librerías que son utilizadas a través de lenguajes de
programación (en este caso VisualC++) para conseguir una interfaz software entre las
aplicaciones y el hardware gráfico. La librería esta formada por unas 150 instrucciones
diferentes que se utilizan para especificar los objetos y las operaciones necesarias para
desarrollar aplicaciones interactivas tridimensionales. Los modelos se deben construir
partiendo de un pequeño conjunto de "primitivas geométricas" como puntos, líneas y
polígonos.
A cambio, OpenGL, ofrece algo muy valioso: “La independencia con respecto a la
plataforma de hardware y el sistema operativo en que se trabaje, brindando con ello
una enorme portabilidad a sus productos”. Así, OpenGL, permite:

• Construir formas geométricas a partir de primitivas.


• Ubicar los objetos en el espacio tridimensional y seleccionar el punto de vista de la
escena.
• Aplicar el color a los objetos, ya sea mediante una asignación explícita de la
aplicación, a partir de las condiciones de iluminación o mediante la utilización de
texturas.
• Convertir la descripción matemática de los objetos y la información sobre el color
en pixels de la pantalla, proceso que se llama pasterización.

Aunque OpenGL está esta concebido para diseñar aplicaciones interactivas y facilita al
usuario herramientas como la selección sus capacidades resultan insuficientes para, entre
otras cosas, crear interfaces gráficas con un grado mayor de interactividad. Estas
limitaciones condujeron al desarrollo de las librerías AUX y GLUT. Las librerías AUX
presentan numerosas insuficiencias, y su aplicación se limita a programas de simple
enseñanza.
La librería GLUT en cambio, tiene mayor funcionalidad para la manipulación interactiva de
objetos 3D.
GLUT es una interfaz de programación con "C" ANSI y Fortran para escribir programas en
OpenGL que sean independientes del sistema operativo de ventanas. Las librerías GLUT
ofrecen, entre otras cosas, las siguientes prestaciones:
• Ventanas múltiples para render
• Procesamiento de eventos de entrada iniciados por el usuario (callbacks).
• Variados dispositivos de entrada.
• Menús desplegables.
• Rutinas para generar objetos estándares.

2. Puntos, líneas y polígonos (Primitivas OpenGL)

En OpenGL, las primitivas geométricas son usadas para realizar los dibujos que se
desean. Las primitivas son: puntos, líneas y polígonos. Estas primitivas se describen
básicamente a partir de sus vértices (coordenadas que definen al punto, los extremos de
los segmentos de línea y las esquinas de los polígonos).
En un sentido matemático, la definición de las primitivas mencionadas es relativamente
simple, y en OpenGL se trabaja en un contexto similar, siendo diferente en sólo lo relativo
a la implementación como tal.

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

Las diferencias incluyen la precisión de los valores y error de redondeo, factores que
influyen en las coordenadas en OpenGL, y las limitaciones del raster graphics display,
cuya unidad mínima (píxel) es mucho mayor del concepto de matemático de infinitamente
pequeño (para un punto) o infinitamente delgado (para una línea).
OpenGL se refiere a los puntos como un vector, manejado como un número de punto
flotante, pero ello no implica que la precisión sea de un 100% en el momento de dibujar.

Puntos
Un punto se define mediante la función glVertex, esta función especifica las coordenadas
del punto dentro de la ventana de visualización. Con esta función se pueden definir puntos
en dos y tres dimensiones, dependiendo del número de coordenadas que se detallan.
OpenGL trabaja normalmente en coordenadas homogéneas representadas por cuatro
componentes, (x, y, z, h), por lo tanto cuando se está definiendo puntos en dos
dimensiones el valor z coge el valor cero y h el valor 1, en tres dimensiones h coge el
valor 1.

glVertex{23}{sifd}[v](TYPE coords)

Tipo de Datos Definición de tipo


Sufijo Tipo de datos
en C OpenGL
b Entero 8 bits signed char GLbyte
s Entero 16 bits Short GLshort
i Entero 32 bits Long GLint, GLsizei
f Real 32 bits Float GLfloat, GLclampf
d Real 64 bits Double GLdouble, GLclampd
Entero sin signo 8
ub unsigned char GLubyte,GLboolean
bits
Entero sin signo 16
us unsigned short GLushort
bits
Entero sin signo 32
ui unsigned long GLuint,GLenum,GLbitfield
bits

El tipo especificado de coordenadas viene determinado a partir de los sufijos que siguen a
la función glvertex. Los sufijos que pueden seguir a la función serán, d (double), indica
que las coordenadas deben especificarse en valores double, f (float), i (integer) y
finalmente s (short), por lo tanto las coordenadas deberán indicarse con valores que
correspondan al sufijo. Existe la posibilidad de definir un punto mediante un vector que
contenga las coordenadas utilizando el sufijo v lo que indica que es un vector de
coordenadas.

Gldouble v[3]= {4.5, 6.7, 23.8}


glVertex(v);

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

Para definir un punto o conjuntos de puntos se debe especificar las siguientes cláusulas
glBegin(GL_POINTS) y la cláusula glEnd(), detallando entre ambas las posiciones de
cada punto:

glBegin(GL_POINTS)
glVertex2f(50.4,34.6); //Punto 2D,en punto flotante
glVertex3i(10,20 34); //Punto 3D, en enteros
glEnd();

El tamaño (o ancho de un punto) se modifica empleando la sentencia glPointSize(valor),


donde valor representa el tamaño con el que desea dibujar el punto.

Líneas
De la misma forma que se definen puntos se puede definir líneas. Para definir una línea
se precisan dos puntos, estos dos puntos se definen con la función glVertex.
Existen diversas formas de definir líneas dependiendo del modo en que se describa en la
cláusula glBegin(modo), donde modo puede ser: deseamos.

Modo Descripción

Genera una serie de líneas que no se conectan entre sí. Las líneas se definen
GL_LINES mediante los pares de puntos sucesivos, por lo tanto el número de vértices debe
ser par, en el caso de que fuera impar se ignoraría

Genera una serie de líneas pero que se conectan entre sí, es decir el punto final
GL_LINE_STRIP de una línea es el punto inicial de la siguiente. Con este modo se pueden generar
figuras cerradas si el punto inicial coincide con el final.

Genera una serie de líneas conectadas entre sí, es parecido al modo anterior
GL_LINE_LOOP
pero este modo conecta automáticamente el punto inicial con el punto final.

El siguiente código muestra como quedan todas estas formas de líneas:

glBegin (MODO);
glVertex2f(0.0, 0.0);
glVertex2f(1.0, 0.0);
glVertex2f(1.0, 1.0);
glVertex2f(0.0, 1.0);
glEnd;

Gráficamente quedará de la siguiente forma, según el valor de MODO.

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

GL_LINES GL_LINE_STRIP GL_LINE_LOOP

(0,1) (1,1) (0,1) (1,1) (0,1) (1,1)

(0,0) (1,0) (0,0) (1,0) (0,0) (1,0)

El aspecto de las líneas también pueden modificarse, pudiendo crear líneas más gruesas
y con formato punteado, para ello se utilizará los comandos:

glEnable(GL_LINE_STIPPLE);
glLineStipple( factor, mascara);
glDisable(GL_LINE_STIPPLE);

Con estos comandos se puede conseguir líneas punteadas, la primera instrucción activa
el modo de línea punteada, mientras que el segundo define el estilo de la línea, donde
factor es un valor que esta comprendido entre 1 y 255, este valor define la separación
entre los trozos de la línea, mientras que máscara, es un valor de 16 bits que se describe
en hexadecimal, cada máscara define un formato de línea, los valores van comprendidos
entre 0x0000 hasta 0xAAAA.
Otra posibilidad que se tiene es modificar el grosor de la línea con la instrucción:

glLineWidth(tamaño);

Por defecto OpenGL define las líneas con tamaño 1.0, hay que tener en cuenta que una
vez activado el tamaño hay que volver a establecerlo si se desea líneas con el tamaño por
defecto.

Polígonos
OpenGL define los polígonos como secuencia de aristas, por lo tanto sigue con el mismo
formato especificado en los puntos anteriores.
Para generar polígonos se tienen los siguientes modos para la sentencia
glBegin(modo), estos son:

Modo Descripción
Genera un simple polígono relleno con los vértices especificados. Para
generar un polígono se deben garantizar tres cosas:
• Como mínimo se precisan 3 vértices.
GL_POLYGON
• Las líneas no deben cruzarse.
• Los vértices deben formar un polígono convexo, en caso
contrario OpenGL ignorará el vértice.
Genera una serie de triángulos rellenos que no se conectan entre sí. El
GL_TRIANGLES número de vértices debe ser múltiplo de 3, si el total de vértices es menor
de tres, OpenGL ignora los vértices que no forma un triángulo.
Genera una serie de triángulos rellenos conectados entre sí, es decir dos de
GL_TRIANGLE_STRIP
los vértices de un triángulo son los vértices del siguiente triángulo. Se tiene

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

que saber que con N vértices se pueden crear N-2 triángulos. De igual
forma el número de vértices debe ser múltiplo de tres, si no lo es se ignora
aquellos que sobran.
Genera un conjunto de triángulos rellenos conectados entre sí, con la
característica de que todos los triángulos tiene un vértice en común. El
GL_TRIANGLE_FAN primer triángulo define el vértice común a todos los triángulos. De igual
forma que los anteriores el número de vértices debe ser múltiplo de 3, si no
lo es se ignora aquellos vértices que sobran.
Genera un conjunto de cuadriláteros rellenos sin conectar entre ellos. El
número de vértices que se requiere es múltiplo de cuatro, si no se verifica
GL_QUADS
entonces OpenGL ignora los vértices que sobran. Cada cuatro vértices se
describe un cuadrilátero.
Genera un conjunto de cuadriláteros rellenos que se conectan entre sí, es
decir dos vértices de un cuadrado se utilizan para generar el siguiente
cuadrilátero. Hay que tener en cuenta que con un total de N vértices se
GL_QUAD_STRIP
obtiene un total de N/2-1 cuadrados. El número de vértices debe ser
múltiplo de cuatro, si no se verifica entonces los vértices que sobran son
ignorados.

Gráficamente los modos son:


v2
v0 v1 v1
v1

v4 v3
v5 v2 v5 v0
vo
v3 v2
v4 GL_TRIANGLE_STRIP
GL_TRIANGLES
GL_POLYGON

v1
v1 v1
v0 v0
v2 v2 v2
v0 v3 v4 v3
v7
v3
v5
v4
v5
v6 GL_QUAD_STRIP
v4
GL_QUADS
GL_TRIANGLE_FAN

Como por lo general se trabaja con vértices en 3D, es necesario tener cuidado ya que
después de algunas operaciones, si algún vértice no está en el mismo plano, puede
llegarse a resultados inesperados. El usar triángulos garantiza que siempre se trabaja en
un mismo plano.

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

3. Transformaciones en OpenGL
OpenGL soporta tres tipos de transformaciones:

• Traslación
• Rotación
• Escalamiento

Por lo general el escalamiento no es muy utilizado porque este comando es


MUY lento y el uso continuo del mismo hace descender el rendimiento de una animación.
Para las transformaciones geométricas, OpenGL utiliza matrices de 4x4.

Traslación
void glTranslate{fd}(TYPE x, TYPE y, TYPE z);

Multiplica la matriz actual por una matriz de traslación que mueve el objeto.

Rotación
void glRotate{fd}(TYPE angle,TYPE x, TYPE y, TYPE z);

Multiplica la matriz actual por una matriz de rotación que rota el objeto en la dirección de
las agujas del reloj sobre el radio de origen en el punto x,y,z.

Escalado
void glScale{fd}(TYPE x, TYPE y, TYPE z);

Multiplica la matriz actual por una matriz que cambia el tamaño del objeto a lo largo de los
ejes. Las coordenadas x, y, z de cada objeto se multiplican por los parámetros x, y, z.

4. Iluminación y Color

Hacer una escena lo mas real posible requiere no solo de mostrar la información en 3D
sino también se requiere de simular el color, así como los efectos de iluminación lo que
permitirá construir escenas mas elaboradas y por lo tanto que mas se asemejen a la
realidad.

Color
En una pantalla de computadora, el hardware causa que cada pixel en la pantalla emita
cantidades diferentes de luz roja, verde, y azul. Éstos se llaman los valores R, G y B. Ellos
se juntan (a veces con un cuarto valor, el llamado alfa A), y el valor condensado se llama
el RGB (o RGBA). La información colorida a cada pixel en modo de RGBA en que el R, G,
B, y posiblemente valores A se guardan para cada pixel, o en un índice de color o en un
solo número (llamó el índice colorimétrico). Cada índice colorimétrico indica una entrada
en una tabla que define un juego particular de R, G, y B.

Los valores R, G, y B pueden ir de 0.0 (ninguno) a 1.0 (intensidad llena) por ejemplo, R =
0.0, G = 0.0, y B = 1.0 representan el azul más luminoso posible. Si R, G, y B son todos
0.0, el pixel es negro; si todos son 1.0, el pixel es el más luminoso blanco que se pueda

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

desplegarse en la pantalla. Mezclando verde y azul crean sombras de cian, mezclando


azul y roja para la magenta. Rojo y verde crea amarillo.

Los órdenes para especificar el color para un objeto (en este caso, un punto) puede ser
tan simple como:

glColor3f (1.0, 0.0, 0.0);

Indicando los componente RGB o:

glColor3f (1.0, 0.0, 0.0,1);

Indicando los componentes RGBA

Iluminación
Con OpenGL se pueden crear muchos efectos de luz. Se pueden crear luces puntuales,
direccionales y focos.
Una luz puntual es como una bombilla. La luz surge de un punto, y se dispersa en todas
direcciones. La intensidad de la luz en un punto del espacio depende de la distancia de
este punto al origen de la luz.
Una luz direccional es una luz parecida a la luz del sol. La luz se dirige en una posición, y
no parece que venga de un punto en concreto.

En el modelo de iluminación en OpenGL, la luz de una escena proviene de varias fuentes


de luz que pueden apagarse o encenderse individualmente. Las luces pueden iluminar
desde una dirección o posición particular, o de forma general toda la escena (luz
ambiente).
En OpenGL, las fuentes de luz sólo tienen efecto cuando hay superficies que absorben o
reflejan luz. Cada superficie se asume que está compuesta de un material con distintas
propiedades. Un material puede emitir su propia luz (como los faros de un coche), puede
reflejar la luz que le llega en todas las direcciones (reflexión difusa) o parte de esa luz en
una dirección preferente generando un brillo (reflexión especular).
De esta forma, OpenGL divide la iluminación en cuatro componentes independientes:
emitida, ambiente, difusa y especular.
En general, y a manera de 'receta', los pasos para añadir iluminación a un escena son los
siguientes:

• Definir los vectores normales para cada vértice de todos los objetos
• Crear, seleccionar y colocar una o más fuentes de luz
• Crear y seleccionar el modelo de iluminación
• Definir las propiedades del material de todos los objetos de la escena

Definición de los vectores normales


Para aplicar un modelo de iluminación es necesario definir los vectores normales de los
objetos que forman parte de la escena, para determinar su orientación con respecto a las
fuentes de luz.
La librería GLUT define un conjunto de funciones para la definición de primitivas básicas
mediante polígonos, que ya incorporan las normales de sus vértices. Entre estas

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

funciones se encuentran las siguientes: glutSolidSPhere, glutSolidTorus,


glutSolidCube, etc.
Sin embargo, si no se utilizan estas primitivas 3D básicas, sería necesario especificar las
normales a la vez que se construye el objeto. En este caso es necesario utilizar la función
glNormal para definir la normal de cada vértice, y posteriormente llamar a la función
glVertex para asignar la función a dicho vértice. Debido a que a menudo cada vértice
tiene una normal diferente, sería necesario realizar llamadas alternativas de esta forma:

• glBegin (GL_POLYGON);
glNormal3fv(n0);
glVertex3fv(v0);
glNormal3fv(n1);
glVertex3fv(v1);
glNormal3fv(n2);
glVertex3fv(v2);
glNormal3fv(n3);
glVertex3fv(v3);
glEnd();

Creación de las fuentes de luz


Las fuentes de luz tienen una serie de propiedades tales como: color, posición, dirección.
La función que se usa para especificarlas es glLight*.
La sintaxis es:

• void glLight{if}[v](GLenum light, GLenum pname, TYPEparam);

De esta forma se crea la fuente de luz que indica el parámetro light, el cual puede recibir
los valores GL: LIGHT0, GL_LIGHT1, ... , GL_LIGHT7 (8 fuentes de luz como máximo
en la definición estándar de la librería, la implementación específica puede permitir más).

Para especificar la iluminación de una escena hay que decidir como serán las luces, y
cuales serán los materiales de los objetos de las escenas. Por defecto la iluminación esta
deshabilitada. Lo primero que se debe hacer es habilitar el modelo de iluminación, con el
siguiente código:

glEnable(GL_LIGHTING);

Una vez habilitado el modelo de iluminación se debe decidir cuantas luces se van a
insertar en la escena. Cada implementación de OpenGL tiene un número máximo de
luces que se pueden manejar, en general se cuentan con 8 puntos de luz que se pueden
definir. Para habilitar cada una de las luces se ejecuta lo siguiente :

glEnable(GL_LIGHTi);

donde 0<=i<=GL_MAX_LIGHTS (donde GL_MAX_LIGHTS es una constante con valor de


8). Este identificador GL_LIGHTi es el que habitualmente se utiliza para referenciar a una
luz.
Una vez habilitadas las luces, hay que indicar los parámetros de las mismas. Para hacerlo
se utilizan la siguiente función:

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

• glLight{if}[v](GLenum light, GLenum pname, TYPEparam);

De esta forma se crea la fuente de luz que indica el parámetro light, el cual puede recibir
los valores GL: LIGHT0, GL_LIGHT1, ... , GL_LIGHT7 (8 fuentes de luz como máximo
en la definición estándar de la librería, la implementación específica puede permitir más).
Las características de la luz se especifican por pname utilizando las constantes que se
muestran en la tabla que sigue. Finalmente, el argumento param indica los valores de la
característica fijada en pname.

Nombre del parámetro Valor por Significado


defecto
GL_AMBIENT (0.0, 0.0, 0.0, Intensidad Ambiente de luz
1.0) RGBA
GL_DIFFUSE (1.0, 1.0, 1.0, Intensidad Difusa de luz
1.0) RGBA
GL_SPECULAR (1.0, 1.0, 1.0, Intensidad especular de luz
1.0) RGBA
GL_POSITION (0.0, 0.0, 1.0, Posición de la luz (x, y, z, w)
0.0)
GL_SPOT_DIRECTION (0.0, 0.0, -1.0) Dirección del foco de luz (x,
y, z)
GL_SPOT_EXPONENT 0.0 Exponente de la luz dirigida
GL_SPOT_CUTOFF 180.0 Angulo de luz dirigida
GL_CONSTANT_ATTENUATION 1.0 Factor de atenuación
GL_LINEAR_ATTENUATION 0.0 Factor de atenuación lineal
GL_QUADRATIC_ATTENUATION 0.0 Factor de atenuación
cuadrática

Para los valores por defecto de GL_DIFFUSE y GL_SPECULAR se aplican sólo a GL_LIGHT0.
Para otras fuentes de luz, los valores por defecto son (0.0, 0.0, 0.0, 0.1) para ambos
casos.
A continuación se verá algunos de los parámetros más importantes de las luces, y como
modificarlos:

• Posición y tipo de luz


Si hay una luz, hay que indicar en que posición de la escena esta. Esto se consigue
llamando a la siguiente función:

void glLightfv(GLenum light, GLenum pname, const GLfloat *params);


donde light es el identificador de la luz (GL_LIGHTi)
pname = GL_POSITION
params es un vector del tipo GLfloat position[4];

Con esta llamada se indican dos cosas.

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

• Si params[3] tiene un valor igual a 0.0, entonces es una luz direccional. En


este caso el vector (params[0], params[1], params[2]), da el vector de la
dirección de la luz.
• Si params[3] tiene un valor igual a 1.0, entonces es una luz puntual. El vector
(params[0], params[1], params[2]) indica la posición de la luz

• Color de la luz
Los colores de las luces en OpenGL tienen tres componentes :
• Ambiente
Esta componente afecta a todos los objetos, independientemente de la
posición u orientación de estos. Viene a emular la luz que en el mundo real
viene dada por la reflexión difusa en las paredes, la luz solar indirecta, etc.
• Difusa
Se puede pensar en ella como en el verdadero color de la luz. Su influencia
sobre una superficie de un objeto depende de su orientación y su distancia.
• Especular
Influye en el brillo que va a tener el objeto.

Estas componentes se pueden modificar con la siguiente función :

void glLightfv(GLenum light, GLenum pname, const GLfloat *params);

donde light es el identificador de la luz (GL_LIGHTi)


pname = GL_AMBIENT, GL_DIFFUSE o GL_SPECULAR, dependiendo de que
componente se quiere modificar.
params es un vector del tipo GLfloat color[4];

El formato de params debe ser el siguiente :


• color[3] debe valer 1.0
• (color[0], color[1], color[2]) da el vector RGB del color.

• Focos de luz
Las fuentes de luz posicionales en principio irradian luz en todas direcciones. Sin
embargo, estas luces pueden convertirse en focos o luces de teatro restringiendo la forma
de la luz emitida a un cono. Los spotlights requieren indicar la posición a la que apunta el
foco (GL_SPOT_DIRECTION), el ángulo sobre el eje del cono (GL_SPOT_CUTOFF) y el
grado de concentración de la luz (GL_SPOT_EXPONENT).

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

Propiedades del material


La forma en que la luz incide sobre las superficies de los objetos depende de las
propiedades del material de los mismos.
En OpenGL la forma de definir estas propiedades es con la función glMaterial*. Su
sintaxis es la siguiente:

• void glMaterial{if}[v](GLenum face, GLenum pname, TYPEparam);

El primer argumento determina la cara del objeto donde se aplica el material, puede tomar
los valores GL_FRONT, GL_BACK, o GL_FRONT_AND_BACK.
El siguiente argumento indica la propiedad del material que va a fijarse (sus posibles
valores se muestran en la tabla). Finalmente, el argumento param permite asignar los
valores a la propiedad pname.
Nombre del parámetro Valor por defecto Significado
GL_AMBIENT (0.2, 0.2, 0.2, 1.0) Color ambiente del material
GL_DIFFUSE (0.8, 0.8, 0.8, 1.0) Color difuso del material
GL_AMBIENT_AND_DIFFUSE Color ambiente y Difuso
GL_SPECULAR (0.0, 0.0, 0.0, 1.0) Color Especular del material
GL_SHININESS 0.0 Exponente Especular
GL_EMISSION (0.0, 0.0, 0.0, 1.0) Emisión del color
GL_COLOR_INDEXES (0,1,1) Índices ambiente, difuso, y
especular

Reflexión ambiente y difusa


La reflexión difusa determina el color de un objeto, y la reflexión ambiente la forma en que
el objeto redistribuye la luz ambiente que recibe. Los objetos del mundo real suelen tener
el mismo color de reflexión ambiente y difusa.

Reflexión especular
La componente especular define el color de los brillos del objeto, cuya forma se controla
con el parámetro GL_SHININESS, de modo que cuanto mayor sea este parámetro el brillo
aparecerá más concentrado.

Emisión
OpenGL permite asignar a los objetos un color de emisión para que parezca que dichos
objetos emiten luz de un color, lo que permite simular lámparas y objetos luminosos. Se
pueden conseguir mejores efectos situando fuentes de luz en la misma posición que los
objetos para los que se define un color de emisión.

Cambio de las propiedades del material


Para minimizar el coste asociado a la realización de cambios en las propiedades del
material se usa la función glColorMaterial.
Sintaxis:

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

• void glColorMaterial (Glenum face, Glenum mode);

donde face puede tomar los valores GL_FRONT_AND_BACK, GL_FRONT o GL_BACK y mode
GL_AMBIENT_AND_DIFFUSE, GL_DIFFUSE, GL_SPECULAR o GL_EMISIÓN.
Una vez que se realiza la llamada a la función, se puede cambiar el color de la propiedad
que indica el parámetro mode, para la cara definida en face usando glColor.
Después de llamar a la función glColorMaterial, es necesario realizar una llamada a
glEnable con el argumento GL_COLOR_MATERIAL.

• glColorMaterial(GL_FRONT, GL_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
glColor3f(0.2, 0.5, 0.8);
......../* dibujamos algo aquí */
glColor3f(0.9, 0.0, 0.2);
......... /*y otros */
glDisable(GL_COLOR_MATERIAL);

Los materiales de los objetos tienen las mismas componentes que la de los colores de la
luz. Vienen a indicar la reflectancia del material a cada una de las componentes de la luz.
Para indicar el material de los objetos que se van a renderizar a continuación se debe
utilizar la siguiente función :

void glMaterialfv( GLenum face,GLenum pname,const GLfloat *param);


Donde :
• face indica a que caras se van a modificar. Puede valer GL_FRONT,
GL_BACK o GL_FRONT_AND_BACK, pero casi siempre trabajaremos con
GL_FRONT.
• pname indica que componente se va a modificar. Puede valer GL_AMBIENT,
GL_DIFFUSE o GL_SPECULAR.
• param es un vector de cuatro componentes que indica el nuevo valor del
color. (params [0], params [1], params [2]) da el vector RGB del color. params
[3] debe valer 1.0.

A continuación se muestra un ejemplo, donde se tiene una bola roja con una luz
direccional :

GLfloat mat_difuso[] = {1.0,0.0,0.0,1.0};


GLfloat posicion_luz[] = {1.0,1.0,1.0,0.0}; // Luz
direccional!
// Provar despues con una luz puntual del tipo siguiente.
// Se nota un poco que la luz se va degradando cuanto
mayor
// es la distancia entre la luz y el objeto
// GLfloat posicion_luz[] = {5.0,5.0,5.0,1.0};

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);

glMaterialfv(GL_FRONT,GL_DIFFUSE ,mat_difuso);
glLightfv(GL_LIGHT0,GL_POSITION,posicion_luz);

DibuajrEsfera();

5. Conceptos de Control Avanzados

Listas
Una lista de OpenGL es un grupo de comandos que han sido guardados para una
posterior ejecución. Cuando una lista es invocada, los comandos en ella son ejecutados
en el orden en los cuales fueron introducidos.
Utilizar listas tiene dos ventajas. La primera es la eficiencia y la segunda la claridad.
Suponga que se tiene el siguiente código que dibuja tres círculos en pantalla:

Procedure DrawCircle()
begin
glBegin(GL_POLYGON);
for(i=0;i<100;i++)
{
cosine = cos(i*2*PI/100.0);
sine = sin(i*2*PI/100.0);
glVertex2f(cosine,sine);
}
glEnd();
end;

glPushMatrix();
DrawCircle();
glTranslatef(2.0,0.0,0.0);
DrawCircle();
glTranslatef(2.0,0.0,0.0);
DrawCircle();
glPopMatrix();

En este caso, para dibujar los tres círculos, Se tuvieron que calcular 300 veces los valores
de un seno y un coseno. Hacer este tipo de cálculos es muy costoso. Si se utilizara listas,
entonces solo se tendría que calcular una vez los puntos del circulo, con lo que sólo se
calcularía 100 senos y cosenos, y despues se llamaría a la lista tres veces, una vez por
cada dibujo.

Por ejemplo, se puede tener lo siguiente:

glNewList(LISTA_CIRCULO,GL_COMPILE);
glBegin(GL_POLYGON);
for(i=0;i<100;i++)
{

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

cosine = cos(i*2*PI/100.0);
sine = sin(i*2*PI/100.0);
glVertex2f(cosine,sine);
}
glEnd();
glEndList();

Y después, cuando se quiera dibujar el círculo utilizar:

glPushMatrix();
glCallList(LISTA_CIRCULO);
glTranslatef(2.0,0.0,0.0);
glCallList(LISTA_CIRCULO);
glTranslatef(2.0,0.0,0.0);
glCallList(LISTA_CIRCULO);
glPopMatrix();
}

Hay que tener en cuenta que se pueden crear listas jerarquicas. Así por ejemplo, la
función DrawScene anterior se podría ejecutar con un solo glCallList, si antes se hubiese
definido una lista del tipo siguiente :

glNewList(LISTA_ESCENA,GL_EXECUTE);
glPushMatrix();
glCallList(LISTA_CIRCULO);
glTranslatef(2.0,0.0,0.0);
glCallList(LISTA_CIRCULO);
glTranslatef(2.0,0.0,0.0);
glCallList(LISTA_CIRCULO);
glPopMatrix();
glEndList();

Cuando se crea una lista, OpenGL se encarga de guardar cuales son las operaciones que
se realizan y posteriormente se pueden ejecutar con un costo en calculo mucho menor. La
desventaja es que una lista requiere mucho espacio en memoria. Por ejemplo, para la
lista del circulo, se necesita espacio de al menos para 200 puntos en coma flotante.
Además, las listas una vez realizadas no se pueden cambiar, solo se pueden ejecutar.
Las listas pueden guardar las siguientes operaciones :
• Operaciones con matrices
• pasterización de bitmaps y imágenes
• Luces, propiedades de materiales y modelos de luces.
• Texturas
• Primitivas de dibujo : polígonos, mallas de triángulos, líneas,...

Las operaciones básicas con listas son las siguientes :

void glNewList( GLuint list, GLenum mode );


Crea o reemplaza una lista. list es el identificador de la lista. mode puede ser
GL_COMPILE. En este caso, todos los comandos que se encuentren en la lista se
guardan en la lista, pero no se ejecutan. En caso de ser GL_COMPILE_AND_EXECUTE
se guardan en la lista y se ejecutan.

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

void glEndList( void );


Indica el final de los comandos de la lista.

void glCallList( GLuint list );


Ejecuta la lista indicada.

GLboolean glIsList( GLuint list );


Devuelve TRUE si existe alguna lista con el identificador dado.

Vistas
OpenGl permite utilizar diferentes expresiones para definir la posición de la cámara y
hacía donde mira dicha cámara.
En OpenGl la representación de los ejes e coordenadas se describe en el siguiente
gráfico.

Existe la posibilidad de manipular estos ejes cambiando la posición relativa de cada uno
de ellos, para ello OpenGl utiliza una serie de sentencias que definen como se va a ver
los ejes de coordenadas y en consecuencia como se visualizará el objeto tridimensional.

gluLookAt()
Esta sentencia permite definir de forma especifica donde se situará la cámara, hacía
donde mirara está y cual va a ser el orden de los ejes de coordenadas.

gluLookAt(x0,y0,z0,xc,yc,zc,Vx,Vy,Vz);

Esta sentencia tiene nueve argumentos que describen tres puntos, los valores de x0, y0,
z0, representa el punto hacia donde mira la cámara virtual, este punto normalmente se
identifica en el origen de coordenadas (0,0,0).
Los siguientes tres argumentos representan el punto donde se situará la cámara de
visualización, estas coordenadas no deben coincidir con el punto al cual se está mirando.
Las últimas tres coordenadas representa el vector de vista hacía arriba, es decir indica
cual será el vector cuya dirección será hacia arriba, “apuntará hacia la parte superior del
monitor”.

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

Para entender este caso se puede ver una serie de ejemplos donde se especifica cual es
el vector y como quedan definidos los ejes de coordenadas:
y
y
x

z z
(Vx,Vy,Vz) = (Vx,Vy,Vz) =
(0,1,0) (1,1,0)

En los ejemplos anteriores según sea el valor del vector de vista hacia arriba el objeto que
se visualizará tendrá un aspecto u otro. Normalmente para simplificar la visualización el
vector de vista hacia arriba se hace coincidir con uno de los ejes de coordenadas, como
es el caso del primer gráfico.

glOrtho()
Se utiliza para especificar una proyección ortográfica. Este tipo de proyección define un
volumen de vista rectangular, concretamente define un paralelepípedo de tamaño infinito,
este hecho nos lleva a definir una serie de planos de corte para detallar con exactitud el
volumen de vista.

Plano de corte lejano plejos

pcerca

Plano de corte cercano (xwmax, ywmax)

(xwmin, ywmin)

OpenGl define la sentencia como:

glOrtho(xwmin, xwmax, ywmin, ywmax, pcerca, plejos);

Estos seis argumentos definen la ventana de visualización y los planos de corte tanto
cercano como lejano.
Para definir la ventana de visualización es suficiente definir las coordenadas de dos
esquinas de la ventana, con estos dos valores queda totalmente definida.
Los valores de pcerca y plejos representan el plano cercano y el plano lejano. Hay que
tener en cuenta que el objeto a visualizar debe encontrarse dentro de ambos planos, si
sobrepasan estos dos planos el objeto se recortará automáticamente.

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

El objeto se visualizará entre los dos planos de recorte, en el caso que sobrepase estos
planos se recortará, y si el objeto es tan grande que la ventana de visualización esta
dentro de él, no se visualizará nada quedando la pantalla en negro.

glFrustum()
Este comando se utiliza para definir una proyección perspectiva, se define de forma
similar a la proyección ortográfica pero con la diferencia que la proyección perspectiva
define como volumen de vista una pirámide, en consecuencia el objeto a visualizar tiene
un aspecto mucho más realista.
La sentencia que utiliza OpenGl es:

glFrustum(xwmin, xwmax, ywmin, ywmax, pcerca,plejos);

Esta sentencia se define de forma similar a la utilizada para definir proyecciones


paralelas, de igual forma que en el anterior caso se definen los planos de corte para
limitar el volumen de vista, que en este caso al ser una proyección perspectiva definirá un
tronco piramidal.

plejos
Plano de corte lejano

(xwmax, ywmax)

Plano de corte cercano


pcerca
(xwmin, ywmin)

Punto de vista

gluPerpespective()
Esta sentencia es una alternativa a la función glFrustum, la diferencia entre ambas está
en la forma de definir la ventana de visualización. Si en la sentencia glFrustum se definen
los dos vértices necesarios de la ventana, en la sentencia glPerpective solamente se
define el ángulo de apertura de la cámara y la relación entre el largo y ancho del plano
cercano de corte.
La sentencia en OpenGl será de la forma:

gluPerspective(apertura, aspect, pcerca, plejos);

Apertura corresponde al ángulo de apertura de la cámara virtual, este ángulo puede tomar
valores comprendidos entre 0º y 180º. El valor de aspect, vendrá dado por la relación

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

entre el alto y ancho del plano de corte, por lo tanto aspect toma el valor de alto plano
dividido entre largo plano.
Los valores de pcerca y plejos corresponden a los planos de corte cercano y lejano, de
forma similar que en los casos anteriores.

plejos
Plano de corte lejano

Plano de corte cercano


pcerca

Apertura

Punto de vista

Matrices
Para poder manipular los objetos de la escena se debe tener definida una matriz de
visualización, esta matriz será de cuatro por cuatro, es decir coordenadas normalizadas.
Esta matriz se utiliza tanto en dos como en tres dimensiones, la diferencia esta en la
coordenada z, en el caso de dos dimensiones z siempre tomará el valor cero, mientras
que en tres dimensiones podrá tomar diferentes valores.
OpenGl, facilita maneras para poder manipular la matriz de visualización. Antes de
manipular la matriz directamente se debe inicializar el modo para la matriz de
operaciones, esto se consigue con la función:
glMatrixMode(GL_MODELVIEW);

Una vez definido el modo de la matriz se puede asignarle un valor con las siguientes
funciones:
glLoadIdentity()

Inicializada la matriz de transformaciones con la identidad.


glLoadMatrix(M)

Esta sentencia permite inicializar la matriz con un valor dado, especificado por el valor de
M. M puede ser definido como una matriz de cuatro por cuatro o bien por un vector de
dieciséis elementos, (m1, m2, m3,...). Hay que tener en cuenta que los valores de la

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

matriz se especifica por columnas, es decir la primera columna corresponde a los valores
del vector m1, m2, m3, m4, la segunda columna corresponderá a los valores m5, m6, m7,
m8, y así sucesivamente.
Estas dos sentencias permiten inicializar la matriz de transformaciones, para poder
realizar operaciones se puede utilizar la siguiente instrucción:
glMultMatrix(M)

Esta sentencia permite multiplicar matrices, teniendo en cuenta que multiplicará la matriz
definida con una de las sentencias anteriores por la matriz M.

Manipulación de la pila de matrices


Se ha visto que las matrices de vista de modelo y proyección han sido utilizadas en
distintas operaciones, pero en términos de pila de matrices, cada una de ellas es la matriz
más alta en una pila (stack) de matrices.
Un arreglo de matrices en pila resulta de utilidad para la construcción de modelos
jerárquicos, en el que objetos complejos pueden dibujarse a partir de modelos sencillos.
Un ejemplo clásico es el de dibujar un automóvil, con cuatro ruedas, cada una de las
cuales está sujeta con cinco pernos. Lo que buscamos es tener una rutina sencilla que
dibuje un perno, y otra que dibuje un perno, ya que los pernos y las ruedas son todos
iguales entre sí.
Si la rutina se elige para dibujar el objeto con una orientación conveniente (por ejemplo
centrado en el origen, con ejes coincidentes con el eje z), lo único que se necesita es
dibujar mediante un llamado para cada objeto, y cada uno con diferentes
transformaciones que posicionen en el lugar correcto.
Es decir se necesita tener un punto de referencia, moverse al punto deseado y dibujar una
rueda, recordar dónde está el punto de referencia para después moverse y dibujar la
siguiente, etc... Lo mismo se aplica para los pernos y para toda la escena.
Como las transformaciones están almacenadas como matrices, una pila es el mecanismo
ideal para manejar este efecto de "memoria" de las posiciones y transformaciones
anteriores a una matriz específica.
El manejo de la pila de matrices, se maneja con las instrucciones de glPushMatrix() y
glPopMatrix(), que delimitan el área de trabajo. El objetivo es controlar la matriz que
está en la parte superior de la pila.
La instrucción glPushMatrix(), se encarga de copiar la matriz actual y colocar la
copia en la parte superior de la pila, mientras que glPopMatrix() se encarga de quitar
la matriz superior en la pila. (la matriz actual siempre es la que está en la parte superior).

En otros términos glPushMatrix() significa "recuerda dónde estás", y


glPopMatrix() "regresa donde estabas".

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

Blending

El blending de OpenGL proporciona un control a nivel de píxel del almacenamiento de


valores RGBA en el buffer de color. Para activar blending en ventanas RGBA, primero se
debe habilitar la opción con glEnable(GL_BLEND). Una vez habilitadas las transparencias
se debe indicar la función a utilizarse para la misma mediante el comando glBlendFunc
con dos argumentos: las funciones origen y las de destino para la mezcla de color.
Por defecto, estos argumentos son GL_ONE y GL_ZERO, respectivamente, lo que
equivale a glDisable(GL_BLEND). El formato de la instrucción será:

GlBlendFunc(origen, destino)

Donde origen y destino pueden ser:

Función origen Descripción


GL_ZERO Color fuente = 0,0,0,0.
GL_ONE Color fuente.
El color de origen se multiplica por el color del píxel de
GL_DST_COLOR
destino.
El color de origen se multiplica por (1,1,1,1; color de
GL_ONE_MINUS_DST_COLOR
destino).
El color de origen se multiplica por el valor alfa de
GL_SRC_ALPHA
origen.
El color de origen se multiplica por (1, valor alfa de
GL_ONE_MINUS_SRC_ALPHA
origen).
El color de origen se multiplica por el valor alfa de
GL_DST_ALPHA
destino. Microsoft OpenGL no lo soporta.
El color de origen se multiplica por (1, valor alfa de
GL_ONE_MINUS_DST_ALPHA
destino). Microsoft OpenGL no lo soporta.
El color de origen se multiplica por el mínimo de los
GL_SRC_ALPHA_SATURATE valores alfa de origen y (1, valor de destino). Microsoft
OpenGL no lo soporta.

Función destino Descripción


GL_ZERO Color destino = 0,0,0,0.
GL_ONE Color destino.
El color de destino se multiplica por el color del píxel de
GL_DST_COLOR
origen.
El color de destino se multiplica por (1,1,1,1; color de
GL_ONE_MINUS_DST_COLOR
origen).
El color de destino se multiplica por el valor alfa de
GL_SRC_ALPHA
origen.
GL_ONE_MINUS_SRC_ALPHA El color de destino se multiplica por (1, valor alfa de

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

origen).
El color de destino se multiplica por el valor alfa de
GL_DST_ALPHA
destino. Microsoft OpenGL no lo soporta.
El color de destino se multiplica por (1, valor alfa de
GL_ONE_MINUS_DST_ALPHA
destino). Microsoft OpenGL no lo soporta.
El color de destino se multiplica por el mínimo de los
GL_SRC_ALPHA_SATURATE valores alfa de origen y (1, valor de destino). Microsoft
OpenGL no lo soporta.

Transparencias

La transparencia es quizás el uso más típico de blending, se utiliza a menudo en


ventanas, botellas y otros objetos 3D a través de los cuales se puede ver. Estas son las
funciones de mezcla para estas aplicaciones:

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, Gl_ONE_MINUS_SRC_ALPHA);

Esta combinación toma el color de origen y lo escala basándose en la componente alfa,


para sumarle luego el color de destino escalado en 1 menos el valor alfa. De otra manera,
esta función de mezcla toma una fracción del color de dibujo actual y cubre con ella el
píxel que hay en pantalla. La componente alfa del color puede valer de 0 (totalmente
transparente) a 1 (totalmente opaco), como sigue:

Rd = Rs * As + Rd * (1 - As)
Gd = Gs * As + Gd * (1 - As)
Bd = Bs * As + Bd * (1 - As)

Como sólo se emplea la componente alfa del color de origen, no se necesita una tarjeta
gráfica que soporte planos de color alfa en el buffer de color. Algo que se debe recordar
con las transparencias por mezcla alfa es que la verificación normal de profundidad puede
interferir con el efecto que se trata de conseguir. Entonces es necesario asegurarse que
las líneas y polígonos transparentes se dibujen apropiadamente, siempre se debe dibujar
de atrás a adelante.

Antialiasing

La apariencia que tienen puntos, líneas y polígonos en algunas ocasiones no son


completamente ALPHA. En sistemas que tengan antialiasing asistido por hardware y
mezclas, la mezcla producirá un resultado similar a la de las escenas con antialiasing a
pantalla completa generadas con el buffer de acumulación. Al mismo tiempo, la mezcla es
varias veces más rápida que la acumulación ya que sólo hay que dibujar la escena una
vez.
Para dibujar una escena usando las primitivas de antialiasing, se debe llamar a las
siguientes funciones, para líneas, puntos y polígonos respectivamente:

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

glEnable(GL_LINE_SMOOTH);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_POLYGON_SMOOTH);

NIEBLA
  
  
          


   
    
 
   
  
      !
 
     

 
"  #     
   
        $

• GL_LINEAR, para indicios de profundidad,


• GL_EXP, para niebla espesa o nubes,
• GL_EXP2, para neblina y humo.

%

          $




 



 



 



& !'(          


    
  '!
 #
 
    
  
  $

 

!"#$%&!'
(
 
) 

!

  

!"#$%&!'

 
) 

!
)    
      
      
    ( #'  
    !
*

 *  + 
   + #+   
#  

    


  ' 
       
      
  ' 
  #     +  + 

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

    
   

        
  



)              
  
 

 '   
    , # 
       -.)
-.)/  #    
 $


 
*+, -
 #    
 ' 0   '11 
       +  12      
 

          
  
  



  
 
 3         
4" 
 3#
    11 21

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

  0 '# 
       
 
        '
 !
 
    
)  
     
     
1121 
 # --%5,65--78       
    
#
       !     
  

        
  #    


     #
  

6. Texturas

Ya se vio como pintar, trasladar y rotar un objeto en una escena, ahora seguro que se
desearía darle más realismo a la misma. Para ello se utilizan texturas, que no son más
que imágenes 2D "pegadas" a los polígonos.

Antes de nada, es importante saber que a la hora de trabajar con texturas lo primero que
se debe hacer es habilitar el mapeado de texturas. Para esto se utiliza la instrucción
glEnable(GL_TEXTURE_2D); OpenGL trata cada textura como si fuera un objeto. Le
asigna un nombre distintivo, que es el identificador (TextureID) por lo que cada ID
referencia a una textura diferente. Así se puede acceder de manera más fácil a las
mismas. Por ejemplo si se tienen dos texturas cargadas en un programa y estas
corresponden con los índices de textura (TexturaID), 1 y 2 respectivamente, para usarlas
solamente se debe utilizar:
glBindTexture(GL_TEXTURE_2D, 1); Para la primera textura y
glBindTexture(GL_TEXTURE_2D,2) para la segunda.

La función glBindTexture enlaza el nombre de la textura (ID) con los datos en sí de la


textura. Para ello se pasa como parámetro el tipo de textura que se desea asignar, en
este caso es una textura 2D (Con ancho y alto). En resumen lo que glBindTExture hace
es enlazar él ID de la textura con los datos de la misma. Una vez que se crea la textura,
esta estará almacenada en la posición de memoria referenciada por el identificador
indicado El siguiente paso es determinar las características que tendrá la textura. Para
ello se hace uso del comando glTexParameteri (El sufijo i indica que los parámetros
pasados son de tipo entero). Lo que se quiere decir a OpenGL con este comando es el
tipo de filtrado que se debe de hacer cuando la textura se agranda
(GL_TEXTURE_MAG_FILTER) o cuando esta textura se estrecha
(GL_TEXTURE_MIN_FILTER) con respecto al tamaño original de la textura. El filtrado
seleccionado para ambos casos puede ser lineal (GL_LINEAR) lo que produce un efecto
de suavizado en ambos casos o GL_NEAREST que produce un efecto peor, pudiendo
llegar a mostrar cuadros muy desagradables.
Evidentemente GL_LINEAR es más lenta que GL_NEAREST.

Una vez que ya se ha definido un textura, se ha habilitado el uso de texturas y además se


ha identificado sus características sólo falta abrir el archivo de la imagen misma, una
restricción que se debe tomar en cuenta con los archivos es el tamaño de estos, Opengl

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

sólo acepta archivo con tamaños múltiplos de 2. Para poder enlazar en memoria el
archivo se utiliza el comando glTexImage2D de la siguiente manera:

glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels)

donde:

target  Especifica el tipo de textura fuente. Debe ser GL_TEXTURE_2D o


GL_PROXY_TEXTURE_2D. 
level  Especifica el nivel de detalle de la imagen. Nivel 0 es el por defecto.
Nivel n es la nth reducción mipmap. 
internalformat  Especifica el número de componentes de color de la textura. Debe ser
1, 2, 3, o 4, o uno de las siguientes constantes simbólicas: GL_ALPHA,
GL_ALPHA4, GL_ALPHA8, GL_ALPHA12, GL_ALPHA16,
GL_LUMINANCE, GL_LUMINANCE4, GL_LUMINANCE8,
GL_LUMINANCE12, GL_LUMINANCE16, GL_LUMINANCE_ALPHA,
GL_LUMINANCE4_ALPHA4, GL_LUMINANCE6_ALPHA2,
GL_LUMINANCE8_ALPHA8, GL_LUMINANCE12_ALPHA4,
GL_LUMINANCE12_ALPHA12, GL_LUMINANCE16_ALPHA16,
GL_INTENSITY, GL_INTENSITY4, GL_INTENSITY8,
GL_INTENSITY12, GL_INTENSITY16, GL_R3_G3_B2, GL_RGB,
GL_RGB4, GL_RGB5, GL_RGB8, GL_RGB10, GL_RGB12,
GL_RGB16, GL_RGBA, GL_RGBA2, GL_RGBA4, GL_RGB5_A1,
GL_RGBA8, GL_RGB10_A2, GL_RGBA12, or GL_RGBA16. 
width  Especifica el ancho de la imagen debe ser 2n + 2 * por algún entero n. 
height  Especifica el alto de la imagen. Debe ser 2m + 2 * por algún entero m 
border  Especifica el ancho del borde. Debe ser 0 o 1. 
format  El formato de los datos pixels. Los valores permitidos son
GL_COLOR_INDEX, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA,
GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA,
GL_BGR_EXT, GL_BGRA_EXT, GL_ARGB_I3D, GL_422_EXT,
GL_422_REV_EXT, GL_422_AVERAGE_EXT, y
GL_422_REV_AVERAGE_EXT. 
type  Especifica los tipos de datos para la información de pixels. Los valores
permitidos son GL_BITMAP, GL_UNSIGNED_BYTE, GL_BYTE,
GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_INT, GL_INT,
GL_FLOAT, GL_UNSIGNED_BYTE_3_3_2_EXT,
GL_UNSIGNED_BYTE_2_3_3_REV_EXT,
GL_UNSIGNED_SHORT_5_6_5_EXT,
GL_UNSIGNED_SHORT_5_6_5_REV_EXT,
GL_UNSIGNED_SHORT_4_4_4_4_EXT,
GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT,
GL_UNSIGNED_SHORT_5_5_5_1_EXT,
GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT,
GL_UNSIGNED_INT_8_8_8_8_EXT,
GL_UNSIGNED_INT_8_8_8_8_REV_EXT,
GL_UNSIGNED_INT_10_10_10_2_EXT, y
GL_UNSIGNED_INT_2_10_10_10_REV_EXT. 

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

pixels  Puntero al vector con los datos de la imagen. 

Ahora que ya se tiene la Textura creada se debe especificar las coordenadas de la textura
con respecto al objeto que se va a dibujar. Al igual que las coordenadas de un vértice le
dicen a OpenGL donde dibujar cada punto de un objeto, las coordenadas de textura
especifican donde se debe dibujar cada textura.
Para comprender mejor como se especifican estas coordenadas piense que se tiene un
tablón de madera y que sobre este se desea pegar una fotografía que se tiene impresa en
una tela elástica. Lo que se hace es coger la esquina superior derecha de la fotografía y
unirla con una grapa a la esquina superior derecha del tablón y así con las demás
esquinas. Pues bien, ahora se debe pensar en la fotografía como si fuera la textura y el
tablón como el cuadrado. Lo que se tiene que hacer entonces es decirle a OpenGL donde
"colocar las grapas" y eso es básicamente especificar las coordenadas de textura. Para
ello se utiliza la función glTexCoord2f(u,v). El primer valor es la coordenada X de la
textura, 0 es la parte izquierda de la misma, 0.5 es la mitad y 1 es la parte derecha. El
segundo valor es la coordenada Y, 0 es la parte inferior, 0.5 es la mitad y 1 es la parte
superior. De este modo, las coordenadas de la textura de un cuadrado serán:
- Vértice 1: glTexCoord2f(0,0);
- Vértice 2: glTexCoord2f(0,1);
- Vértice 3: glTexCoord2f(1,1);
- Vértice 4: glTexCoord2f(1,0);

Texturas multiples

El proceso de crear texturas con la instrucción glBindTexture para asignarle un


identificador, no solo permite enlazar una imagen con su respectivo ID, sino que también
permite seleccionar una textura que ya ha sido almacenada.
El comando glBindTexture entonces tiene dos funciones, la primera es crear una nueva
textura, si el identificador pasado como parámetro no esta todavía creado entonces
Opengl crea una nueva textura y le asocia al ID pasado como parámetro.
La segunda función de este comando es seleccionar una textura ya creada, si es la
segunda vez que se usa el comando glBindTexture con un mismo identificador, entonces
se le esta indicando a Opengl que se desea utilizar una textura ya creada.

De esta manera se pueden utilizar un conjunto grande de texturas para una misma
escena.

Una textura, desde el punto de vista de su almacenamiento en memoria es un array de


datos. Cada uno de los valores de este array se llama 'textel'. Este array de datos
representa una imagen, que se usa para mapearla sobre un polígono.
Se puede rellenar el arreglo ya sea cargando una imagen desde un fichero, o bien
colocando los valores de color a cada texel.
La información de cada uno de los componente puede ser:

• Las componentes RGB del color.


• Índices de color.
• Niveles de luminancia (grises).

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

Además, se puede tener texturas unidimensionales (un solo pixel de alto o de ancho)
bidimensionales (imagen de tamaño mxn) o tridimensionales (con volumen), aunque lo
habitual será utilizar las bidimensionales.
En OpenGl las dimensiones de una textura deben ser siempre potencia de 2=
64,128,256...
Los pasos necesarios para mapear texturas sobre polígonos son los siguientes:
• Indicar los parámetros de aplicación de la textura y activar el mapeado de texturas.
• Especificar la textura
• Dibujar la escena.

Definición de los parámetros de texturado.


Una vez cargada la imagen en memoria se debe definir una serie de parámetros que
servirán para idnicar cómo se aplica la textura sobre el polígono. Esto se hará con la
función glTexParameter, su prototipo es:

5")  9 :9: +      ;


5")  9 :9: +      ;

Donde: objetivo= GL_TEXTURE_2D ,y pnombre y param pueden tomar los siguientes


valores:
pnombre Param

GL_TEXTURE_WRAP_S GL_CLAMP, GL_REPEAT

GL_TEXTURE_WRAP_T GL_CLAMP, GL_REPEAT

GL_TEXTURE_MAG_FILTER GL_NEAREST,GL_LINEAR

GL_TEXTURE_MIN_FILTER GL_NEAREST,GL_LINEAR,
GL_NEAREST_MIPMAP_NEAREST,
GL_NEAREST_MIPMAP_LINEAR,
GL_LINEAR_MIPMAP_NEAREST,
GL_LINEAR_MIPMAP_LINEAR

Habrá que llamar a la función glTexParameter cuatro veces, para dar los valores que se
deseen a cada uno de los parámetros.
Con GL_TEXTURE_WRAP se especifica el tratamiento de las coordenadas S y T de la
textura, fuera del rango [0.0,1.0]. Y Con GL_MAG_FILTER y GL_MIN_FILTER se indican
los filtros de ampliación o reducción de la textura.
También se puede especificar cómo aplicar la textura sobre los píxels. Esto se hara con la
función:
5"9 :9: +      ;
5"9 :9: +      ;

donde objetivo=GL_TEXTURE_2D y

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

 
    
  
 

-5.5&6-74-<8 -8=, "  ! 


 
  


   " 
->78-<8&,5

-5.5&6-74-=6 puntero a un valor de color RGBA



'
   
!
 

Para poder ver las texturas se tiene que activarlas con la función:

 -5.5&6-/8;
 -5.5&6-/8;

Especificar la textura.
Normalmente se partirá de una imagen almacenada en algún formato standard (bmp, jpg,
gif, rgb, etc). Para poder cargar esta imagen se necesita de algún programa o biblioteca
que lea este tipo de ficheros. Se debe asegurar, utilizando algún editor de imágenes, que
el ancho y el alto de la imagen sea potencia de dos.
Si la imagen se la tiene en formato bmp se puede utilizar también una función de la
biblioteca glaux para cargarla:

,&.-6>? 6
@ "8?>?    ;
,&.-6>? 6
@ "8?>?    ;

Esta función devolverá una estructura de la cual se podrá leer la información de tamaño y
datos:

 
-,&.-6>? 6
9
 
-,&.-6>? 6
9

9
  !. !A;
  !. !A;
  
( @  ;
  
( @  ;
:,&.-6>? 6
;
:,&.-6>? 6
;

Una vez cargado el fichero de la textura deseada, se define la textura en OpenGl,


utilizando la función glTextImage2D:
5"? /8 +     
  !  
( 
5"? /8 +     
  !  
( 
 !           
 @ ";
 !           
 @ ";
Donde:

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

Parámetro valores
Objetivo GL_TEXTURE_2D (para texturas bidimensionales)

nivel 0,1,2.. es el nivel de detalle de la textura. Si sólo hay una textura nivel=0

componentes Número de componentes de color. Color indexado=1, RGB=3, RGBA=4

ancho Ancho de la textura: potencia de 2

alto Alto de la textura: potencia de 2

borde Ancho del borde= 0,1, ó 2.

formato formato de la información de píxel. Pueden ser: GL_COLOR_INDEX, GL_RGB,


GL_RGBA, etc.

tipo Tipo de datos de cada píxel: GL_UNSIGNED_BYTE, GL_INT, etc.

pixels Puntero al array donde se almacenan los valores de la textura.


Esta función deberemos llamarla antes de dibujar los polígonos sobre los que queremos
aplicar la textura.

Dibujar la escena y asignar coordenadas de textura.


El último paso del proceso será dibujar los objetos. Para que la textura se visualice
correctamente sobre ellos deberemos asignarle a cada uno de los vértices las
coordenadas de textura. Estas coordenadas determinan qué texsel en el mapa de
texturas es asignado a cada vértice. Para ello, llamaremos, antes de cada glVertex, a la
función:

5"=  /9 :
 -
 -;
5"=  /9 :
 -
 -;

Ejemplo.
Un ejemplo del código necesario para dibujar un objeto con texturas.

AUX_RGBImageRec *imagen[1]; //En este caso solo se carga una textura

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

En la función de inicialización de valores definiremos los parámetros de pegado de la


textura, y leeremos las imágenes de fichero
//Pegado sobre el polígono
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
//Filtros
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
//Cargar un fichero bmp en el array
imagen[0]= auxDIBImageLoad("file.bmp");
//Activar las texturas
glEnable(GL_TEXTURE_2D);

Por último, en la función de dibujado, cargar la textura antes de dibujar el polígono:

glTexImage2D(GL_TEXTURE_2D,0,3,imagen[0]->sizeX, imagen[0]->sizeY,
0,GL_RGB,GL_UNSIGNED_BYTE,imagen[0]->data);

glBegin(GL_POLYGON);
glNormal3f(0,0,1);
glTexCoord2i(0,0); //Asignr las coordenadas de textura del siguiente vértice.
glVertex3f(-ancho/2,-alto/2,0);
glTexCoord2i(0,1);
glVertex3f(-ancho/2,alto/2,0);
glTexCoord2i(1,1);
glVertex3f(ancho/2,alto/2,0);
glTexCoord2i(1,0);
glVertex3f(ancho/2,-alto/2,0);
glEnd();

7. SOMBRAS

Añadir sombras a nuestras escenas puede mejorar notablemente su realismo y


efectividad visual. Se puede producir una sombra proyectando el objeto original en el
plano de la superficie sobre la que descansa el objeto. Entonces el objeto se dibuja en
negro, o en algún color oscuro, quizás con algo de transparencia.
Se necesita proyectar la matriz del modelador de manera que la totalidad de los objetos
dibujados en ella se encuentren ahora en este mundo bidimensional proyectado. Hay que
considerar la dirección y distancia de la fuente de luz.
La dirección de la fuente determina la forma de la sombra y su tamaño. La siguiente
función toma tres puntos que descansan en el plano en el que se quiere que aparezca la
sombra, la posición de la fuente de luz y, finalmente, un puntero a una matriz de
transformación que construirá esta función. Lo que hace esta función es deducir los
coeficientes de la ecuación del plano en el que aparecerá la sombra, y usarla con la
posición de la luz para construir una matriz de transformación. Si se multiplica esta matriz
por la del modelador actual, todo el dibujo será proyectado sobre este plano.

..)/ 012-2(-0!-2/3 2 
..42-3 /15((/-0  - "$"$

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

( 1*0! 2/ -"6$"6$ 7-"#$ - "#$"#$


 &
  2 )"#$
  

 ..!/-- -/3 2 
 ..8/---20- -0--/  0
 02/ -2 )

 ..8/-90 2-/-/3 
 2 )"6$%:2 )";$<2/ -"$";$=2 )">$<2/ -"$">$=
  2 )"$<2/ -"$"$


 ../0?2 42-3 /1
 %2 )";$<7-";$=
   2 )">$<7-">$=
   2 )"$<7-"$=
   2 )"6$<7-"6$

 ..1243 
 ..0/0 
 - ";$";$%:7-";$<2 )";$
 - ">$";$%;5;:7-";$<2 )">$
 - "$";$%;5;:7-";$<2 )"$
 - "6$";$%;5;:7-";$<2 )"6$

 ..*/ /0 
 - ";$">$%;5;:7-">$<2 )";$
 - ">$">$%:7-">$<2 )">$
 - "$">$%;5;:7-">$<2 )"$
 - "6$">$%;5;:7-">$<2 )"6$

 ..+)/0 
 - ";$"$%;5;:7-"$<2 )";$
 - ">$"$%;5;:7-"$<2 )">$
 - "$"$%:7-"$<2 )"$

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

 - "6$"$%;5;:7-"$<2 )"6$



 ..)/)/0 
 - ";$"6$%;5;:7-"6$<2 )";$
 - ">$"6$%;5;:7-"6$<2 )">$
 - "$"6$%;5;:7-"6$<2 )"$
 - "6$"6$%:7-"6$<2 )"6$
 '
Una vez realizada la matriz de transformación se debe dibujar la escena dos veces la
primera en su posición original y luego dibujar nuevamente la escena realizado la
transformación, los pasos a seguir para crear sombras seran:
• Crea la matriz de sombreado (en destMat en el código de ejemplo)
• Dibujar la escena
• Modificar la matriz del modelador (glMultMatrix(destMat) con la matriz del código
anterior)
• Cambiar el color al color de sombreado o de reflexión (glColor3f(0.1,0.1,0.1))
• Dibujar la escena nuevamente.

8. Enmascaramiento

Esta técnica consiste básicamente en "recotar" parte de un gráfico, ya sea según un color
o siguiendo un patrón, para darle aspecto de transparencia a ese trozo que se ha
recortado.
Tiene mucha utilidad dentro del mundo de los videojuegos, por ejemplo si se tiene un
dibujo del personaje y se quiere mostrarlo en la pantalla, no seria nada agradable que
apareciera un cuadrado de fondo negro con nuestro personaje dentro, y que todo tapara
el fondo tan bonito que se ha creado. También es útil para crear interfaces de usuario,
cabinas de aviones (para simuladores), efecto billboarding, etc.

Masking usando dos imagenes

Para usar esta técnica se deben tener dos imágenes diferentes, una llamada imagen
fuente y la otra imagen máscara. En la imagen fuente se almacena la imagen que se
desea mostrar (y recortar) con un fondo por ejemplo negro. En la imagen máscara se
pinta de negro las partes de la imagen fuente que se quiere ver y de blanco las que se
quiere recortar. Por ejemplo:

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

Para ello en el ejemplo se ha creado un cubo que tiene cinco caras con una misma
textura (opaca) y la cara anterior contiene una textura a la que se le ha aplicado el efecto
de máscara, consiguiendo un efecto de transparencia que permite ver el interior del cubo.

Para poder utilizar transparencias (con enmascaramiento) se procede de la siguiente


manera:
• Cargar las transparencias (la original y la máscara)
• Activar el efecto de blending para la máscara con
glBlendFunc(GL_DST_COLOR,GL_ZERO) que permite pintar en el destino
(pantalla) de negro los pixeles que aparezcan también de negro en el origen
(imagen máscara), los demás (los blancos en la máscara) los deja igual.
• Dibujar la escena con la textura de la máscara.
• Activar blending con la función glBlendFunc(GL_ONE, GL_ONE) que le indica a
• OpenGL que debe de copiar todos los pixeles de nuestra imagen fuente a la
pantalla,
• ignorando los de color negro.
• Dibujar la escena con la textura fuente.

9. EL BUFFER DE ESTARCIDO

El buffer de estarcido proporciona muchas funciones para restringir el dibujo en pantalla y
tiene muchas aplicaciones que el buffer de profundidad no puede realizar. Al nivel más
simple, el buffer de estarcido puede usarse para cerrar ciertas áreas de la pantalla.
Quizás la aplicación más interesante del buffer de estarcido sea el sombreado.
Dependiendo del hardware gráfico, se puede generar sombras por hardware y por
software de múltiples fuentes de luz, haciendo que las escenas sean mucho más
realistas.
Para usar el buffer de estarcido, primero se debe activar con una llamada a:

 !
*+)
+*+
Sin esta llamada, todas las operaciones del buffer de estarcido están desactivadas.


Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

FUNCIONES DEL BUFFER DE ESTARCIDO


Hay cuatro funciones de estarcido en OpenGL:

void glClearStencil( GLint s);


void glStencilFunc( GLenum func, GLint ref, GLuint mascara);
void glStencilMask( GLuint mascara);
void glStencilOp( GLenum fallo, GLenum zfallo, GLenum zpass);

La primera función es similar a glClearColor, glClearDepth y glClearIndex; proporciona el


valor inicial almacenado en el buffer de estarcido (inicializa el valor del buffer) cuando se
llama a glClear(GL_STENCIL_BIT). Por defecto, se almacena un valor de estarcido 0 en
el buffer de estarcido. A diferencia de los buffers de color y profundidad, no siempre
borramos el buffer de estarcido cada vez que actualizamos la escena.

DIBUJANDO EN EL BUFFER DE ESTARCIDO


Una vez activado el buffer de estarcido, es necesario definir cómo trabaja. Por defecto, no
hace nada, permitiendo que las operaciones de dibujo se ejecuten en cualquier parte de la
pantalla hasta que se actualice el buffer de estarcido. Las funciones glStencilFunc y
glStencilOp gestionan esta interacción.
La función glStencilFunc define una función de comparación, valor de referencia y
máscara para todas las operaciones del buffer de estarcido. La siguiente tabla recoge las
funciones válidas:

Nombre Función
GL_NEVER La verificación de estarcido siempre falla (no se dibuja).
GL_LESS Pasa si el valor de referencia es menor que el valor de estarcido.
GL_EQUAL Pasa si el valor de referencia es igual que el valor de estarcido.
GL_LEQUAL Pasa si el valor de referencia es menor o igual que el valor de estarcido.
GL_GREATER Pasa si el valor de referencia es mayor que el valor de estarcido.
GL_NOTEQUAL Pasa si el valor de referencia no es igual que el valor de estarcido.
GL_GEQUAL Pasa si el valor de referencia es mayor o igual que el valor de estarcido.
Por defecto. La verificación de estarcido siempre pasa (siempre se
GL_ALWAYS
realiza una operación de dibujo).

Emparejada con la función de estarcido, está la operación de estarcido, definida con


glStencilOp. Las operaciones de estarcido válidas están recogidas en la siguiente tabla:

Operación Descripción
GL_KEEP Mantiene los contenidos actuales del buffer de estarcido.
GL_ZERO Establece el valor cero en el buffer de estarcido.
GL_REPLACE Establece el valor de la función de referencia en el buffer de estarcido.
GL_INCR Incrementa el valor actual del buffer de estarcido.
GL_DECR Decrementa el valor actual del buffer de estarcido.

Cochabamba - Bolivia
Animación 3D Lic. Yony Richard Montoya Burgos

GL_INVERT Invierte el orden binario del valor actual del buffer de estarcido.

Normalmente se utiliza una máscara para perfilar el área en la que tiene lugar el dibujo.
Aquí tenemos un ejemplo de cómo dibujar una máscara en el buffer de estarcido:

* / 
 @,*>>
*  2
 )
 )
 )

Entonces se puede lanzar comandos de dibujo que almacenen el valor 1 en el buffer de


estarcido. Para dibujar usando la máscara del buffer de estarcido, primero se lleva a cabo
lo siguiente:

* / 


AB >>
*  2
C
C
C

Dado que tiene efecto con todas las funciones de dibujo de OpenGL, incluido glBitMap,
podemos usar el buffer de estarcido para crear efectos especiales de agujero en
animaciones.

Cochabamba - Bolivia

También podría gustarte