SlideShare una empresa de Scribd logo
5º Ingeniería Informática

Informática Gráfica

Capitulo 2:

Introducción a OpenGL

Montserrat Mateos Sánchez
Introducción OpenGL
2.1. INTRODUCCIÓN ...................................................................................................................... 3
2.2 RESEÑA HISTÓRICA ............................................................................................................... 4
2.3. ¿QUÉ ES OPENGL? .................................................................................................................. 5
2.3.1. CARACTERÍSTICAS DE OPEN GL .............................................................................................. 5
2.4. APLICACIONES ........................................................................................................................ 8
2.5. LIBRERÍAS RELACIONADAS CON OPENGL ................................................................. 11
2.5.1 GLUT (O PENGL UTILITY TOOLKIT) ..................................................................................... 12
2.5.1.1. Características .............................................................................................................. 12
2.5.1.2. Funciones de GLUT...................................................................................................... 12
2.5.2 LIBRERÍA AUX ...................................................................................................................... 23
2.5.2.1. Características .............................................................................................................. 23
2.5.2.2. Funciones ...................................................................................................................... 24
2.6. PROGRAMACIÓN CON OPENGL PARA WINDOWS. WIGGLE ................................. 27
2.6.1. FUNCIÓN W INMAIN .............................................................................................................. 28
2.6.2. FUNCIÓN W NDPROC ............................................................................................................. 30
2.6.3. DIBUJAR EN UNA VENTANA DE WINDOWS............................................................................. 32
2.7. USAR OPENGL ........................................................................................................................ 38
2.7.1. DIBUJAR EN 3D..................................................................................................................... 38
2.7.1.1. Dibujar Objetos ............................................................................................................ 38
2.7.2. TRANSFORMACIÓN DE COORDENADAS ................................................................................. 43
2.7.3. COLOR Y SOMBRAS............................................................................................................... 46
2.7.4. LUCES Y LÁMPARAS ............................................................................................................. 48
2.7.5. GRÁFICOS P LANOS EN OPENGL ............................................................................................. 51
2.7.5.1. Mapas de bits ................................................................................................................ 51
2.7.5.2. Mapas de píxeles ........................................................................................................... 53
2.7.6. TEXTURAS............................................................................................................................. 54
2.8. CONCLUSIONES ..................................................................................................................... 54
2.9. BIBLIOGRAFÍA....................................................................................................................... 55

2
2. Introducción OpenGL
2.1. Introducción
Utilizar información gráfica se ha convertido en el mundo de la computación en un recurso
habitual para la comunicación entre los ordenadores y los usuarios. Este tipo de información no solo
se usa para la gestión de las aplicaciones a través de la utilización de menús y ventanas, sino que
cada vez se usa más para la representación gráfica de imágenes reales.
Las imágenes reales o con efectos realistas se consiguen aproximando al máximo la
representación gráfica que se genera en la pantalla del ordenador a las imágenes que percibe el ser
humano con la vista. Para dar realismo a las imágenes por ordenador se utilizan técnicas de
sombreado, brillo, nieblas, transparencias etc.

El empleo de imágenes tridimensionales o con realismo gráfico es un recurso más, dentro de
los que se dispone para el desarrollo de cualquier aplicación informática.

El uso de manera eficiente de todos estos recursos, así como, la estandarización de los
procedimientos de generación de gráficos por computador, se abordaron por primera vez con las
librerías de gráficos OpenGL.

El que todas las aplicaciones que presentan gráficos por computador sigan los mismos
patrones, representa una importante ventaja en cuanto a la portabilidad entre sistemas diferentes. Si
además esos patrones se ajustan a modelos y métodos avanzados y eficientes para la representación
gráfica por ordenador, entonces se tiene la herramienta ideal.

Todo esto lo cumple la librería OpenGL, compatibilidad y versatilidad. Pocos efectos
gráficos quedan fuera de las capacidades que tienen las OpenGL y cada vez más sistemas permiten
la ejecución de aplicaciones basadas en OpenGL.

En éste capitulo de introducción a OpenGL, primero se explicará que es OpenGL, junto sus
características más destacadas, posteriormente se explicarán de forma muy rápida algunas de las
librerías relacionadas con ésta y por último y de forma rápida se mostrarán algunas de las funciones
de OpenGL.
3
2.2 Reseña Histórica
OpenGL, se puede considerar como una norma industrial. Su antecesora fue GL (Graphics
Library) desarrollada por Silicon Graphics, Inc. (líder mundial en gráficos y animaciones por
ordenador) en 1982.
Iris GL

fue la primera API (Aplication Programing Interface) de programación para las

estaciones gráficas IRIS de alto rendimiento de la compañía.
Estas máquinas, contaban con un hardware optimizado para la visualización de gráficos.
Con éste hardware, se podía entre otras cosas, realizar transformaciones matriciales muy rápidas,
además proporcionaban soporte grafico para el buffer de profundidad y otras prestaciones.

Las subrutinas de GL hacen uso directo de las tarjetas gráficas instaladas en las estaciones
de trabajo; los gráficos GL normalmente se refieren a gráficos hardware, en oposición a gráficos X
Windows, que se refieren a gráficos software. Cuando se realiza renderización software, la imagen
gráfica es creada vía el software que está corriendo en la máquina. La imagen renderizada es
entonces visualizada en una ventana llamada X. Con el renderizado por hardware, la mayor parte
del trabajo de crear la imagen la hace la tarjeta gráfica.

GL incluye soporte para conseguir desde dispositivos la entrada de datos, crear y dibujar en
ventanas, configuración y control del buffer y renderizado 3D básico y avanzado.

GL fue elegido por IBM como el API para soportar los adaptadores gráficos que fueron
instalados en las estaciones de trabajo de la serie

RS/6000, y fue usado por mas de 1500

aplicaciones incluyendo IBM Data Explorer, AVS, Grass, (www.ats.ucla.edu)

Pero, IRIS GL no era portable a otras plataformas hardware con lo que se trabajó sobre ello
y apareció OpenGL.

Este nuevo lenguaje, debía ofrecer la potencia de GL y a la vez, ser más abierto para su
adaptación tanto a otras plataformas hardware así como a otros sistemas operativos.

El 1 de Julio de 1992 se presentó la versión 1.0 de la especificación de OpenGL. Poco
después, en la sala de exhibición de empresas se expuso la proyección de secuencias de películas
4
como Terminator 2, El juicio final y algunas aplicaciones médicas gráficas creadas con OpenGL, y
esto tuvo un gran impacto.

En 1995 se aprobó la especificación final de la versión 1.1 de OpenGL. (Sweet, M. et all)

Actualmente, existe la Plataforma para Revisiones de la Arquitectura OpenGL (ARB), está
formada por SGI, DEC , IBM, Intel, Microsoft, se reúne dos veces al año y es la que decide las
mejoras de OpenGL.
Estas reuniones o encuentros, son de carácter público y puede asistir cualquier compañía
aunque solo tienen derecho a voto las anteriores.

2.3. ¿Qué es OpenGL?
OpenGL, es una interfaz software para gráficos por hardware. Es una biblioteca de trazado
de gráficos de alto rendimiento, fácil de usar, intuitivo, portable, en el que el programador describe
las llamadas necesarias a funciones y comandos para conseguir una escena, apariencia o efecto.
Consta de 120 comandos o funciones distintos que tienen la misma sintaxis; e
stas funciones,
se pueden usar para especificar objetos y las operaciones necesarias para desarrollar aplicaciones
gráficas interactivas 2D y 3D; Los algoritmos que utiliza

fueron desarrollados y optimizados por

Silicon Graphics. (Neider, J. et all).

2.3.1. Características de OpenGL
OpenGL es por diseño independiente del hardware, sistema operativo o sistema de ventanas.
Las funciones de OpenGL trabajan de la misma forma en cualquier plataforma, es decir, se pueden
llamar a las funciones de OpenGL desde un programa escrito y obtener los mismos resultados
independientemente del lugar donde el programa se este ejecutando. Esto hace que sea portable y la
programación sea más fácil con OpenGL que con un API integrado en el sistema de ventanas.
Para conseguir la independencia del hardware, OpenGL no incluye ninguna función para la
gestión de ventanas, interactividad con el usuario ni manejo de ficheros. Cada sistema operativo
tiene sus propias funciones para realizar estas tareas, por lo que, los programas creados con
OpenGL deben interactuar con el sistema de ventanas de la plataforma donde os gráficos serán
l
visualizados ya que los gráficos, son normalmente visualizados en una ventana. Hay varias
5
herramientas y librerías para el manejo de ventanas que han sido desarrolladas para trabajar con
OpenGL. (www.linuxfocus.org)

Está diseñado para trabajar eficientemente en un entorno cliente/servidor; Existe un
protocolo para mover por la red los comandos de OpenGL entre el servidor y el cliente. De esta
forma el ordenador que visualiza los gráficos no es el mismo que ejecuta el programa de gráficos, es
decir, el programa o aplicación que produce los gráficos puede correr en otra maquina distinta en la
que se están visualizando los gráficos, e incluso el cliente y el servidor no tienen porque ejecutarse
en el mismo tipo de plataforma o sistema operativo. (www.ats.ucla.edu)

Las funciones de OpenGL como ya se comentó anteriormente, están diseñadas para permitir
crear gráficos 2D y 3D con especial énfasis en 3D. OpenGL tiene funciones o primitivas con las que
se podrá realizar modelado 3D, transformaciones, utilización de color e iluminación, sombras,
mapeado de texturas, animación, movimiento borroso....

Para conseguir rendimiento no tiene comandos para describir modelos complejos (mapas,
pájaros, moléculas, etc) sino que tiene primitivas que permiten dibujar puntos, líneas y polígonos, y
es el programador el que tendrá que construir objetos más complejos.

Con OpenGL cualquier comando es ejecutado inmediatamente. Cuando en un programa se
especifica que dibuje algo, lo hace inmediatamente. Pero existe la opción de poner comandos en
Display Lists. Una display list es una lista no editable de comandos almacenados para una ejecución
posterior y se puede ejecutar más de una vez. Por ejemplo, se pueden usar para redibujar el grafico
cuando el usuario cambia el tamaño de la ventana, también se puede utilizar para dibujar la misma
forma mas de una vez si esta se repite como un elemento de un grafico.

Todos los comandos de OpenGL utilizan la misma sintaxis. Todos ellos usan el prefijo gl y
después la palabra que forma el comando con la primera letra en mayúscula. También en algunos
comandos va seguido como sufijo un numero y una letra, que indican el número de parámetros del
comando y el tipo de sus argumentos. Así por ejemplo,
glColor3f(1.0,1.0,1.0)
Éste comando es de OpenGL y permite cambiar el color activo (Color) y tendrá 3
parámetros de tipo float.

6
Además, algunos comandos pueden llevar la letra v al final que indica que el parámetro de la
función es un puntero a un array o vector.

OpenGL se puede considerar como una máquina de estados. Las aplicaciones se pueden poner
en varios estados que permanecen en efecto hasta que se cambian. Por ejemplo el color, se puede
poner un color y dibujar un objeto, y ese color seguirá activo hasta que se ponga otro color. Igual
que ocurre con el color, OpenGL tiene otra variables de estado para otros controles tales como la
vista actual y transformación de proyecciones, posiciones y características de luces y propiedades
del material que los objetos están siendo dibujados.
Algunas de estas variables de estado se pueden habilitar o deshabilitar con los comandos
glEnable() o glDisable().
Cada variable de estado tiene un valor por defecto y el programador podrá preguntar el valor
actual de cada una de estas variables.
Además, también se podrá almacenar el valor de estas variables de estado para posteriormente
recuperarlo. Las funciones que permiten hacer esto son glPushAttrib() y glPopAttrib().

OpenGL ha sido diseñado para ser llamado por C, C++, Fortran, Ada, Java. Aunque todos los
manuales y documentación de opengl vienen con C. Otros lenguajes de programación como Visual
Basic que pueden invocar a funciones de C, también podrán hacer uso de OpenGL.

Con OpenGL se debe seguir un o
rden para la realización de las operaciones graficas necesarias
para renderizar una imagen en la pantalla, lo primero que se debe hacer es construir formas desde la
primitivas geométricas, después disponer los objetos en el espacio tridimensional y seleccionar la
posición deseada para ver la composición, posteriormente calcular el color para todos los objetos y
por último convertir la descripción matemática de los objetos y su información de color asociada a
píxeles en la pantalla (rasterización).

OpenGL tene sus propios tipos de datos para así hacer el código mas fácilmente portable,
i
aunque estos tipos de datos corresponden con los tipos de datos de C, y por tanto se podrán utilizar
unos u otros indistintamente. Pero si es importante tener en cuenta que si se utilizan los tipos de
datos de C, dependiendo del compilador y entorno habrá unas reglas para planificar el espacio de
memoria de varias variables. Así que, para evitar esto se deben utilizar los tipos de Opengl.

7
Todos los tipos de opengl tienen el sufijo gl y a continuación el tipo de C correspondiente.
La siguiente tabla nos lo muestra:

Tipo de dato en

Definición como tipo C

Representación interna

Glbyte

Char con signo

Entero de 8 bits

Glshort

Short

Entero de 16 bits

GLint, Glsizei

Long

Entero de 32 bits

GLfloat, GLclampf

Float

Coma flotante de 32 bits

Gldouble, GLclampd

Double

Coma flotante de 64 bits

GLubyte, GLboolean

Unsigned char

Entero de 8 bits sin signo

Glushort

Unsigned short

Entero de 16 bits sin signo

GLuint, GLenum,

Unsigned long

Entero de 32 bits sin signo

OpenGL

Glbitfield
Tabla 2.1: Tipos de OpenGL

(Huescar M. et all)

2.4. Aplicaciones
OpenGL es la API para gráficos 3D más utilizada para aplicaciones gráficas, tanto profesionales
como de consumo, así como para juegos y se usa para una amplia variedad de fines. Se pueden
distinguir las siguientes categorías:

-

Software para modelado, rendering y efectos animados. Algunas aplicaciones podrían ser:
? Carrara, modelado, rendering, construcción de escenas y animaciones
?
? Inferno, crear efectos visuales 3d para películas
?
? 3Space Publisher, para crear gráficos y animaciones 3D para la web
?

-

Aplicaciones CAD para diseño, ingeniería y arquitectura:
? SoftCAD
?
? Kinetix
?
? Actify
?

-

Herramientas y librerias para el desarrollo de aplicaciones y juegos.
8
? 3D Charting Toolkit
?
? 3D MasterSuite
?
? AllegroGL
?
? 3D game engine scene composer & player
?
? Surrender
?

-

Juegos
? Azteroids
?
? Diablo II
?
? Quake II
?
? Star Trek Voyager – Elite Force
?
? Ultimate Golf
?

-

Realidad virtual
? VRWave
?
? V-Realm Builder
?
? Envision
?

-

Salvapantallas
? Physical Toy screen saber
?
? Screensaver fighter game
?

-

Aplicaciones de simulación y visualización
? Amira, visualización 3D para medicina
?
? HiQ, visualización de datos de laboratorio
?
? SimFUSION, Simulador y generador de imágenes
?

-

Aplicaciones científicas, médicas y de análisis de datos
? Momol, modelado molecular
?
? Functor, análisis gráficos de funciones algebraicas
?
? MapRender3D
?
? Solar System Simulation
?

(www.opengl.org)
9
Algunos ejemplos sencillos de escenas que se pueden hacer con OpenGL podrían ser los
siguientes:

Figura 2.2: Figuras geométicas
Figura 2.1: Animación

10
Figura 2.5: Perspectiva
Figura 2.6: Perspectiva

Figura 2.7: Sombras

Figura 2.8: Texturas

2.5. Librerías relacionadas con OpenGL
Hay que destacar que la API de OpenGL está divida en tres librerías distintas:
-

AUX, (denominada también librería de recursos, glaux.lib, glaux.h) . Es una librería que
proporciona una estructura de trabajo independiente de la plataforma para invocar a las
funciones de opengl. Todas las funciones comienzan con el sufijo aux.

-

Funciones que definen OPENGL (es la propia librería, opengl32.dll, gl.h).

-

La librería glu32.dll, y su cabecera glu.h. Esta librería contiene funciones útiles que hacen el
trabajo diario más sencillo, como el dibujo de esferas, discos, cilindros. Esta escrita usando
funciones y comandos de opengl.
11
Otro aspecto a tener en cuenta a la hora de hablar de las librerías relacionadas con OpenGL, es
que la especificación de OpenGL se aisló de cualquier dependencia de un sistema de ventanas
concreto, y por tanto, es el sistema de ventanas nativo el encargado de abrir y trazar ventanas. Por
eso OpenGL debe comunicarse con el sistema nativo a través de librerias adicionales auxiliares,
como por ejemplo GLX (interacción entre OpenGL y el sistema Windows), GLUT, y otras.

2.5.1 GLUT (OpenGL Utility Toolkit)
2.5.1.1. Características
-

GLUT ofrece una interfaz común para múltiples plataformas para el manejo de ventanas,
buffers, renderización de texto, entrada por teclado y menús, por lo que, los desarrolladores
podrán usar un interface común para el sistema de ventanas independiente de la plataforma, es
decir, las aplicaciones de OpenGl que usan GLUT se pueden portar entre plataformas sin tener
que introducir muchos cambios en el código fuente.

-

Es un interfaz de programación con enlaces para ANSI C y FORTRAN que, permitirá e
scribir
programas OpenGL independientes del sistema de ventanas.

-

Al igual que OpenGL, utiliza una serie de variables de estado que duran toda la ejecución de la
aplicación, y luego el programador podrá modificar el valor de dichas variables para ajustarlas.

-

Es pequeño y fácil de aprender. Las funciones de GLUT son simples, tienen pocos parámetros
y no manejan punteros excepto los punteros a cadenas de caracteres y manejadores de fuentes
que se le pasan a algunas funciones.

2.5.1.2. Funciones de GLUT
Las funciones de GLUT se pueden dividir o clasificar según su funcionalidad:
??
Inicialización

12
Antes de empezar a

trabajar

hay que inicializar el estado de la máquina de estados de

GLUT.
Todas las funciones de inicialización comienzan por glutInit

Dentro de este grupo de funciones tendríamos las siguientes:

glutInit (int **argcp, char **argv )
Modifica las variables de estado de Glut y negocia una sesión con el sistema de
ventanas. Los parámetros que se le pasan son las variables argc y argv de la función
main de C respectivamente.

glutInitWindowPosition(int x, int **y)
Indica mediante x e y la posición en la pantalla en píxeles de la ventana.

glutInitWindowsSize(int width, int **height)
Indica mediante width, height

el ancho y alto respectivamente en pixeles de la

ventana

glutInitDisplayMode(unsigned int mode)
Indica mediante mode

el modo de display, este valor puede ser entre otros

GLUT_RGBA, GLUT_RGB, GLUT_INDEX, GLUT_SINGLE, GLUT DOUBLE
GLUT_LUMINANCE…..

El siguiente trozo de código nos muestra como inicializar la máquina de estados,

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE| GLUT_RGBA);
glutInitWindowPosition(0,0);
glutInitWindowSize(500,500);
Listado 2.1: Inicialización con Glut el sistema de ventanas

13
En este ejemplo se utiliza doble buffer. El doble buffer se utiliza para animaciones, porque
así se puede eliminar el parpadeo cuando cambia la imagen en la secuencia de animación.

??
Gestión de ventanas
Para abrir una ventana, o enviar la orden de abrir una ventana para la aplicación al sistema
de ventanas subyacente se hace con,

int glutCreateWindow(char **name)
donde name es el nombre de la ventana, nos devolverá el identificador de la ventana

Además de ésta función existen otras funciones para el manejo de ventanas, a
lgunas de ellas
son las siguientes:

glutSetWindow(int winId)
Establece la ventana con el identificador winId como ventana actual

glutGetWindow(void)
Solicita el identificador de la ventana actual

glutDestroyWindow(int winId)
Cierra la ventana especificada por winId

glutPostRedisplay(void)
Solicita que la ventana sea redibujada

glutPositionWindow(int x, int y)
Solicita un cambio de posición de la ventana a la posición indicada por x e y

glutReshapeWindow(int width, int height)
Solicita un cambio en el tamaño de la ventana, el nuevo tamaño vendrá dado por
width y height

glutFullScreen()
14
Solicita que la ventana actual sea cambia a tamaño completo

glutShowWindows(void)
Solicita que la ventana sea mostrada

glutHideWindows(void)
Solicita que la ventana se oculte

glutIconifyWindow(void)
Solicita que la ventana se minimice

glutSetWindowTitle(char *name)
Pone la barra de título en la ventana.

glutSetIconTitle(char *name)
Pone el título en la ventana. Minimizada.

15
El listado 2.1 nos muestra como crear una ventana y como crear un dibujo en ella.

#include <GL/glut.h>
void pintar(void)
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(50);
glBegin(GL_POINTS);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex2f(-0.25,-0.25);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex2f(0.25,0.25);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex2f(-0.25,0.25);
glColor3f(0.5f, 0.5f, 0.5f);
glVertex2f(0.25,-0.25);
glEnd();
glFlush();
};

int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
glutInitWindowPosition(0,0);
glutInitWindowSize(500,500);
glutCreateWindow("Mi primera ventana");
glutDisplayFunc(pintar);
glutMainLoop();
return 0;
}

Listado 2.2: Creación y dibujado de ventanas

16
La ejecución de éste pequeño programa nos mostrará una ventana como la siguiente,

Figura 2.9: Ventana creada con Glut.

??
Usar subventanas

A la hora de crear subventanas tenemos que tener en cuenta los siguientes aspectos:

-

Cuando se crea una ventana, hay que guardar el identificador de la ventana; el
identificador es un entero devuelto por la función glutCreateWindow

-

Solo puede haber una función callback idle() en una aplicación, y esta función es
global para todas las ventanas de la aplicación, por lo tanto, a la hora de implementar
esta función tendrá que estar implementado el refresco para todas las ventanas.

-

Para crear una subventana, hay que proporcionar el identificador de la ventana
superior y las coordenadas para la subventana y el ancho y el alto para la subventana.

17
-

Cuando Glut abre una subventana, le proporciona un contexto completo, con lo que
hay una perdida de rendimiento porque el driver de la tarjeta de video tiene que
refrescar la memoria para cada una de las ventanas.

Para la creación de una subventana se utiliza la siguiente función,
int glutCreateSubWindow(int winId, int x, int y, int width, int height)

??
Procesado de Eventos

GLUT esta dirigido por eventos, es decir, hay un bucle continuo que comienza después de la
inicialización y va procesando todos los eventos. Los eventos pueden ser por ejemplo un botón
del ratón que se pulsa, una ventana que se abre, se redimensiona, se cierra, una tecla del teclado
que se ha pulsado...

Los eventos se registran como rutinas de registro callback.

Después de registrar todos los eventos en el programa hay que llamar a la función de
procesado de eventos que es
glutMainLoop()

Funciones de registro de callback:

glutDisplayFunc(void * void)
Registra la función de display para la ventana actual, como parámetro se le pasa la
función que se ejecutará cuando se produzca el evento de visualizar la ventana.

glutReshapeFunc(void *void( int width, int height))
Registra la función de cambio de tamaño para la ventana actual, como parámetro se
le pasa la función que llamara cuando se cambie de tamaño y el nuevo tamaño.

glutIdleFunc(void * void)
Registra la función idle, esta función es llamada cuando no hay entradas de usuario,
como parámetro se le pasa la función que se ejecutará.
18
glutKeyboardFunc(void *void, unsigned charkey, int x, int y)
Registra la función de pulsado de teclado para la ventana actual.

Otra rutina útil en animaciones es:
glutSwapBuffers()
Intercambia los buffers, mostrando en la ventana de golpe todo lo que se ha dibujado.
??
Uso de teclado

En el momento de pulsar una tecla en el teclado, el driver de proceso de eventos de GLUT
registra un evento de teclado. Estos eventos son manejados por las funciones callback de
teclado. La función asociada de callback toma como argumentos el código ASCII asociado con
la tecla y la posición x,y del cursor.
La

generación

de

callbacks

de

teclado

se

puede

deshabilitar

con

la

función

glutKeyBoardFunc() y pasándole el valor NULL.
??
Trazar texto en una ventana OpenGL

La librería OpenGL no tiene funciones para manejar el trazado de texto, solo tiene unas
directivas muy primitivas para el trazado de bitmaps, por lo que cada uno tiene que hacerse su
propia librería de bitmaps para cada carácter.
GLUT proporciona unas funciones que permiten dibujar un carácter en una posición
especificada:
GlutBitmapCharacter
GlRasterPos

Con el siguiente programa se puede ver gran parte de estas funciones como son crear una
subventana, trazar texto, dibujar en una ventana, tratar el evento de pulsación de teclado o
cambiar el tamaño de la ventana.

19
#include <string.h>
#include <stdio.h>
#include <GL/glut.h>
#include <GL/gl.h>
int IdMain;
int IdSub;

static double tiempo = 0.0;
static double angulo = 0.0;
static char label[100];
void pintarcadena (char *s)
{
unsigned int i;
for (i = 0; i < strlen (s); i++)
glutBitmapCharacter (GLUT_BITMAP_TIMES_ROMAN_24, s[i]);
};

void pintarventana(void)
{
glutSetWindow (IdMain);
glClearColor(1.0F, 1.0F, 1.0F,1.0F);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity ();
glPushMatrix ();
glRotatef (angulo, 0.0, 0.0, 1.0);
glBegin (GL_POLYGON);
glColor3f (1.0F, 0.0F, 0.0F);
glVertex2f(0.0F, 0.5F);
glColor3f (0.0F, 1.0F, 0.0F);
glVertex2f(0.5F,0.5F);
glColor3f (0.0F, 0.0F, 1.0F);
glVertex2f(0.5F,0.0F);
glColor3f (1.0F, 0.0F, 0.0F);
glVertex2f(0.0F,0.0F);
glEnd ();
glPopMatrix ();
glutSwapBuffers ();
};

void pintarsubventana ()
{
glutSetWindow (IdSub);
glClearColor (1.0, 1.0, 1.0, 0.0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f (0.0F, 0.0F, 0.0F);
glBegin (GL_LINE_LOOP);
glVertex2f (0.0F, 0.0F);
glVertex2f (0.0F, 0.99F);
glVertex2f (0.999F, 0.99F);
glVertex2f (0.999F, 0.0F);
glEnd ();

20
glColor3f (1.0F, 0.0F, 1.0F);
sprintf (label, " Subventana ");
glRasterPos2f (0.40F, 0.70F);
pintarcadena (label);
sprintf (label, " de OpenGL creada con GLUT ");
glRasterPos2f (0.33F, 0.35F);
pintarcadena ( label);
glutSwapBuffers ();
};

void tamanoventana (int w, int h)
{
glViewport (0, 0, w, h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluOrtho2D (-1.0F, 1.0F, -1.0F, 1.0F);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glutSetWindow (IdSub);
glutReshapeWindow (w - 10, h / 10);
glutPositionWindow (5, 5);
glutSetWindow (IdMain);
};
void tamanosubventana (int w, int h)
{
glViewport (0, 0, w, h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluOrtho2D (0.0F, 1.0F, 0.0F, 1.0F);
};
void teclado (unsigned char key, int x, int y)
{
static int info_banner = 1;
switch (key)
{
case 'i':
case 'I':
if (info_banner)
{
glutSetWindow (IdSub);
glutHideWindow ();
}
else
{
glutSetWindow (IdSub);
glutShowWindow ();
};
info_banner = !info_banner;
break;
case 'q':
case 'Q':
exit (0);
break;
};

21
};
void idle (void)
{
angulo += 5.0;
tiempo += 0.1;
glutSetWindow (IdMain);
glutPostRedisplay ();
glutSetWindow (IdSub);
glutPostRedisplay ();
};
int main (int argc, char **argv)
{
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowPosition (20, 20);
glutInitWindowSize (600, 600);
IdMain = glutCreateWindow ("Ventana con subventanas");
glutDisplayFunc (pintarventana);
glutReshapeFunc (tamanoventana);
glutKeyboardFunc (teclado);
glutIdleFunc (idle);
IdSub = glutCreateSubWindow (IdMain, 20, 20, 600 - 10, 600 / 10);
glutDisplayFunc (pintarsubventana);
glutReshapeFunc (tamanosubventana);
glutMainLoop ();
return 0;
};
Listado 2.3: Crear ventanas y subventanas con Glut

El ejemplo anterior nos daría la siguiente salida,

Figura 2.10: Ventana que contiene una subventana
creada con Glut.

22
??
Menús

Una forma más de comunicación entre el usuario y una aplicación es el uso de menús, por lo
tanto, es una cuestión importante a tener en cuenta cuando se realizan aplicaciones.
GLUT también dispone una serie de funciones para la creación de menús. Algunas de ellas
serían:

int glutCreateMenu(void (f*) (int))
mainMenu(int)
subMenu(int)
glutAddMenuEntry(char *s, int nr)
glutAddSubMenu(char *s, int nr)
glutAttachMenu()

(www.linuxfocus.org, 1998), (Kilgard, M., 1996)

2.5.2 Librería AUX
2.5.2.1. Características
-

Esta librería no forma parte de la especificación de OpenGL, pero aparece en todas las
plataformas a las que se porta opengl.

-

Fue creada principalmente para facilitar el aprendizaje de OpenGL, olvidándose de los detalles
de la plataforma y sistema operativo.

-

Se utiliza para probar cosas programadas en OpenGL, pero no para escribir aplicaciones serias,
por lo tanto no se debe utilizar demasiado.

-

Las funciones de la librería son rudimentarias y permiten gestionar la creación y manipulación
de ventanas, las entradas de usuario, dibujar figuras 3D completas....

-

AUX, también tiene funciones para operaciones especificas del sistema, como pueden ser
intercambio de buffers y apertura de imágenes, entre otras.

-

Internamente la librería AUX hace uso de la API nativa del entorno para estas funciones.

-

Las funciones de la librería son iguales en todas las plataformas.

(Sweet, M.)

23
Al igual que la librería GLUT tiene funciones para la inicialización, el manejo de ventanas, el
procesado de eventos, aunque la librería AUX es menos completa que GLUT.

2.5.2.2. Funciones
??
Inicialización
Las funciones utilizadas para la inicialización son:
auxInitDisplayMode(Glbitfield mascara)
Inicializa el modo de visualización en la ventana. Es la primera función a la que hay que
llamar. El parámetro indicará las características de la ventana.

auxInitPosition(GLint x, GLint y, Glsizei ancho, Glsizei alto)
Especifica la posición en la pantalla y el tamaño de la ventana.
??
Gestión de ventanas
Para crear e inicializar la ventana de dibujo se utiliza la función auxInitWindow

auxInitWindow(Glbyte *cadenatitulo)
Inicializa y muestra la ventana de generación de OpenGL. El parámetro será el título que
aparecerá en la barra de la ventana.

El siguiente ejemplo muestra como inicializar el sistema y la creación de una ventana.
#include <glglaux.h>
#include <glgl.h>
void CALLBACK nada()
{
};
void main(void)
{
auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);
auxInitPosition(0,0,350,350);
auxInitWindow("Mi ventana creada con la librería AUX");
glClearColor(1.0F, 1.0F, 1.0F, 1.0F);
glClear(GL_COLOR_BUFFER_BIT);
glFlush();
auxMainLoop(nada);
}
Listado 2.4: Crear ventanas con la librería Aux

24
??
Rellamada
Estás funciones, son muy similares a las que tiene GLUT para el procesado de eventos, es decir,
son funciones que se propia librería llamará cuando se necesite, por ejemplo, cuando se cambie de
tamaño una ventana, cuando se pulse una tecla o un botón del ratón, cuando se necesite redibujar la
ventana....
Para declarar e implementar funciones que son llamadas por estas funciones de rellamada se
debe poner delante la sentencia CALLBACK.

Las principales son las siguientes:
auxMainLoop(AUXMAINPROC func)
Permite especificar la función que debe usarse para actualizar la ventana OpenGL. El
parámetro será la función que se llamará cuando hay que refrescar la ventana.

auxReshapeFunc(AUXRESHAPEPROC func)
Permite especificar la función que debe llamarse cuando se cambie de tamaño la ventana.

auxIdleFuncion(AUXIDLEPROC func)
Permite especificar la función de rellamada que debe llamarse cuando no hay otra actividad
pendiente.

auxKeyFunc(GLint tecla, void (*funcion(void))
Permite especificar la función de rellamada cuando se pulse la tecla tecla que se le pasa
como parámetro.

auxMouseFunc(int boton, int modo, AUXMOUSEPROC func)
Permite especificar la función de rellamada con la actividad de los botones del ratón.
??
Otras funciones
Hay otras funciones útiles que se pueden utilizar como son,
auxSwapBuffers(void)
Ocasiona el intercambio del buffer empleado para dibujar con el de pantalla.

auxWireTeapot(Gldouble tamaño)
Dibuja una tetera alámbrica. El parámetro especificar el tamaño de la tetera.
25
auxSolidTeapot(Gldouble tamaño)
Dibuja una tetera sólida. El parámetro especificar el tamaño de la tetera.

El siguiente código nos muestra como crear y dibujar en una ventana.

#include <windows.h>
#include <glgl.h>
#include <glglaux.h>
void CALLBACK tamanoventana(GLsizei w, GLsizei h)
{
if(h == 0)
h = 1;
glViewport(0, 0, w, h);
glLoadIdentity();
if (w <= h)
glOrtho (-100.0f, 100.0f, -100.0f, 100.0f*h/w, -100.0, 100.0);
else
glOrtho (-100.0f, 100*w/h, -100.0f, 100.0f, -100.0, 100.00);
}
void CALLBACK pintarventana(void)
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glRotatef(1.0f,0.0f,0.0f,1.0f);
glBegin (GL_POLYGON);
glColor3f (1.0F, 0.0F, 0.0F);
glVertex2f(30.0F, 75.0F);
glColor3f (0.0F, 1.0F, 0.0F);
glVertex2f(75.0F,75.0F);
glColor3f (0.0F, 0.0F, 1.0F);
glVertex2f(75.0F,30.0F);
glColor3f (1.0F, 0.0F, 0.0F);
glVertex2f(30.0F,30.0F);
glEnd ();
glFlush();
auxSwapBuffers();
}

void CALLBACK idle (void)
{
pintarventana();
};
void CALLBACK teclado (void)
{
exit (0);
};

26
void main(void)
{
auxInitDisplayMode(AUX_DOUBLE|AUX_RGBA);
auxInitPosition(50,50,300,300);
auxInitWindow("Ventana creada con la librería AUX");
auxReshapeFunc(tamanoventana);
auxKeyFunc(81, teclado);
auxKeyFunc(113, teclado);
auxIdleFunc(idle);
auxMainLoop(pintarventana);
}

Listado 2.5: Crear y dibujar una ventana con la librería
Aux

Como se puede observar en la siguiente figura la ejecución del programa produce casi la
misma salida que el ejemplo creado con la librería Glut.

Figura 2.11: Ventana creada con la librería Aux, que
contiene un dibujo geométrico.

(Neider, J.) (Sweet, M.)

2.6. Programación con OpenGL para Windows. WIGGLE
Como ya se ha dicho anteriormente, OpenGL no tiene funciones para la interacción con el
usuario, la gestión de la pantalla, la asociación de comandos de dibujo de OpenGL a una ventana,
selección del modo de buffer, etc. Para todas estas tareas se pueden utilizar algunas librerias que son
independientes de la plataforma como las explicadas en el apartado anterior, o bien, utilizar las

27
propias funciones que nos da el sistema, es decir, el lenguaje de programación anfitrión es el que
tiene que asumir, y por lo tanto tener funciones para todas esas tareas. Microsoft Windows ofrece
seis funciones que son añadidas a OpenGL para realizar estas tareas, estas funciones son las
llamadas funciones wiggle; además de estas seis hay otras cinco añadidas al GDI de Windows.

Por lo tanto es importante ver como se trabaja en un entorno Windows.

Para la creación y gestión de las ventanas Windows el programador deberá realizar algunas
tareas, como son, describir la ventana WinMain, el registro de las clases de windows, crear la
ventana y gestionar o controlar la ventana con WndProc.

Para esto se utilizaran dos funciones WinMain y WndProc.

2.6.1. Función WinMain
El prototipo de ésta función es:

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
lpszCmdLine, int nCmdShow)
Esta función es igual que la función main, pero en un entorno Windows. Los
parámetros que se le pasan serán:
hInstance, para es el handle del programa en uso.
hPrevInstance, indica el número de veces que se activa el mismo programa
lpszCmdLine, es una cadena para indicar todos los parámetros de la línea de
comandos que se pasan al programa.
nCmdShow, permite especificar como se mostrara la ventana inicial (normal,
maximizada, minimizada).

Las características de una ventana Windows se indican mediante la estructura WNDCLASS,
y será dentro de la función winMain donde se le darán valores a todos los atributos de la estructura
WNDCLASS.

Typedef struct_WNDCLASSW{
UINT style;
WNDPROC lpfnWndProc;
28
int
cbClsExtra;
int
cbWndExtra;
HISTANCE hInstance;
HICON
hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCWSTR lpszMenuName;
LPCWSTR lpszClassName;
} WNDCLASS
Los campos o atributos de esta estructura son:
style: permite especificar las características de redibujado de la ventana.
ipfnWndProc: puntero a una función que está relacionada con la clase ventana.
CbClsExtra , cbWndExtra: estos dos valores definen la clase y las extensiones de la
ventana.
hInstance: permite asociar la clase ventana al programa asociada.
hIcon: permite especificar el icono asociado a la aplicación
hCursor: permite especificar el cursor asociado a la aplicación
hbrBackground: para determinar el pincel de colores que se utilizara para el fondo
de la ventana de aplicación.
lpszMenuName: para indicar la clase de menú que se va a utilizar con la ventana.
LpszClassName: para asignar nombre a la ventana.

Después de dados los valores a la estructura tenemos que registrar la ventana con la función:
RegisterClass(&wc)
donde wc es de tipo WNDCLASS

Posteriormente se crea la ventana con la función CreateWindow:
hWnd CreateWindow(
LPCTSTR lpszClassName,
LPCTSTR lpzWindowName,
DWORD dwStyle,
int nX,
int nY,
int nWidth,
int nHeight,
HWND hwndParent,
HMENU hmenu,
HANDLE hinst,
LPVOID lpvParam
);
29
Los parámetros que se le pasan a ésta función serían los siguientes:
lpszClassName: es el nombre que se utilizó en la clase anterior para registrar la clase
de ventana.
lpzWindowName: es el título de la ventana
dwStyle: permite especificar detalles de la ventana. (Si se puede minimizar,
maximizar, si tiene scroll..)
nX , nY: permite especificar la posición inicial de la ventana.
nWidth , nHeight: permite especificar el tamaño de la ventana.
hwndParent: para indicar el handler de la ventana padre.
menú: para indicar el handler del menú
inst: para indicar el handler de la aplicación en uso.
LpvParam: siempre a NULL

2.6.2. Función WndProc
El prototipo de la función es:

LONG WINAPI WndProc( HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam);
Con esta función, se pueden controlar y gestionar los eventos que se produzcan en el
programa, es donde se especifica como debe actuar el programa según el tipo de evento que se
produzca.

Hay muchos eventos o mensajes que se pueden controlar, como pueden ser: WM_PAINT
(para dibujar la ventana), WM_DESTROY (cuando se cierra la ventana), WM_CREATE (cuando se
crea la ventana), WM_SIZE (Cuando se cambia de tamaño), etc.

El siguiente código mostrará el esqueleto para crear una ventana para una aplicación:

30
#include <windows.h>
#include <glgl.h>
#define WIDTH
#define HEIGHT

600
500

HDC ghDC;
HGLRC ghRC;
HINSTANCE hInst;
LONG WINAPI WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
LONG lRet = 1;
RECT rect;
PAINTSTRUCT ps;
HDC hdc;
static HINSTANCE hInstance;
switch (msg){
case WM_PAINT:
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
if (ghRC) wglDeleteContext(ghRC);
if (ghDC) ReleaseDC(hWnd, ghDC);
PostQuitMessage (0);
break;
default:
lRet=DefWindowProc(hWnd,msg,wParam,lParam);
break;
}
return lRet;
}
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
lpszCmdLine, int nCmdShow)
{
static char szAppName[] = "W1";
static char szTitle[]="Ventana creada con GDI de Windows";
WNDCLASS wc;
MSG msg;
HWND hWnd;
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon (hInstance,IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = szAppName;
if (!RegisterClass(&wc ))
return (FALSE);

31
hWnd = CreateWindow(
szAppName,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
WIDTH,
HEIGHT,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd) return(FALSE);
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
while (GetMessage(&msg,NULL,0,0))
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return( msg.wParam );
}

Listado 2.5: Esqueleto de un programa para con el sistema de ventanas propio de Windows

2.6.3. Dibujar en una ventana de Windows
Hasta ahora se ha visto como crear una ventana Windows, pero ahora debemos
aprender a dibujar en ella.
Para dibujar en una ventana se puede hacer sin usar OpenGL y por lo tanto se utilizarían las
funciones del GDI (Interfaz Gráfica de Dispositivos) de Windows, en cuyo caso, habría que tener
en cuenta el concepto de Contexto de Dispositivo, o bien,

utilizar OpenGL y entonces hay que

tener en cuenta el concepto de Contexto de Generación.

32
Contexto de Dispositivo
Cada ventana, tiene un contexto de dispositivo que recibe la salida de gráficos, y cada
función GDI toma un contexto de dispositivo como argumento para indicar a que ventana queremos
que afecte la función. Podemos tener múltiples contextos de dispositivo, pero sólo uno para cada
ventana.

Contexto de Generación
El concepto de contexto de generación no es de OpenGL sino de la API de Windows para
soportar OpenGL. Antes de ejecutar ningún comando de OpenGL hay que indicar la ventana de
generación, es decir, en que ventana se va dibujar. Puede haber varios contextos de generación, pero
solo uno puede ser el actual. Al activar un contexto de generación, se asocia con una ventana
particular.
Para poder trabajar con el contexto de generación tenemos las funciones WIGGLE, que no
son funciones propias de la especificación de OpenGL, sino que se añadieron para soportar todo
este tipo de cosas propias de Windows.

Algunas de las funciones relacionadas con el contexto de generación que más se utilizan
son:
HGLRC wglCreateContext(HDC hDC)
Crea un contexto de generación adecuado para dibujar en el contexto de dispositivo
especificado en el parámetro hDC

BOOL wglDeleteContext(HGLRC hrc)
Borra un contexto de generación. El contexto de generación se debe borrar después
que la aplicación no lo necesita

BOOL wglMakeCurrent(HDC hDC, HGLRC hrc)
Activa el contexto de generación que se le pasa como parámetro hrc y lo asocia con
el contexto de dispositivo especificado también como parámetro hDC

Para la creación de un contexto de generación debemos crear primero un contexto de
dispositivo con la función GetDc(HWND hwnd), esta función devuelve el contexto de dispositivo
para la ventana que se e pasa como parámetro, y posteriormente crear el contexto de generación
l
con la función HGLRC wglCreateContext(HDC hDC)

anteriormente expuesta, pasándole como
33
parámetro el contexto de dispositivo creado y por último asignar el contexto de dispositivo con el
contexto de generación mediante la función

BOOL wglMakeCurrent(HDC hDC, HGLRC hrc).

Estas operaciones normalmente se harán con el evento o mensaje WM_CREATE, que es el
momento de creación de la ventana.

El contexto de generación debe borrarse y normalmente se borrará cuando se cierre la
ventana, es decir, cuando se produzca el mensaje WM_DESTROY. Para borrarlo se hará con la
función anterior BOOL wglDeleteContext(HGLRC hrc)

Para poder dibujar con OpenGL en una ventana hay que tener en cuenta otros dos aspectos,
uno de ellos es el estilo de la ventana y el otro es el formato de Píxel.
Para que OpenGL pueda dibujar en una ventana, la ventana no podrá tener el estilo
CS_PARENTDC y deberá crearse con los estilos WS_CHIPCHILDREN y WS_CLIPSIBLINGS.
El formato de Píxel también hay que especificarlo a la hora de dibujar en una ventana con
OpenGL. El formato de píxel no viene con la especificación de OpenGL, si no que es una extensión
a la API Win32 para soportar la funcionalidad de OpenGL.
El formato de píxel debe seleccionarse para un contexto de dispositivo antes de que este se
use en un contexto de generación. En el formato de píxel se seleccionan características tales como si
la ventana tiene doble buffer, color, profundidad, etc.

Para

seleccionar

el

formato

de

píxel

utilizaremos

la

estructura

PIXELFORMATDESCRIPTOR, en el que le daremos valor a los campos de esta estructura
dependiendo del tipo de ventana que se quiera, y las funciones:

int ChoosePixelFormat(HDC hDC, PIXELFORMATDESCRIPTOR *ppfd)
Esta función se usa para determinar el mejor formato de píxel disponible para el
contexto de dispositivo hDC basado en las características deseadas descritas en la
estructura ppfd.

BOOL SetPixelFormat(HDC hDC, int iPixelFormat, PIXELFORMATDESCRIPTOR
*ppfd)
Selecciona el formato de píxel para un contexto de dispositivo.

34
Ahora que ya se ha visto como crear ventanas y como dibujar en ellas, veamos un ejemplo:
void tamanoventana(GLsizei w, GLsizei h)
{
if(h == 0)
h = 1;
glViewport(0, 0, w, h);
glLoadIdentity();
if (w <= h)
glOrtho (-100.0f, 100.0f, -100.0f, 100.0f*h/w, -100.0, 100.0);
else
glOrtho (-100.0f, 100*w/h, -100.0f, 100.0f, -100.0, 100.00);
}
void pintarventana(void)
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glRotatef(1.0f,0.0f,0.0f,1.0f);
glBegin (GL_POLYGON);
glColor3f (1.0F, 0.0F, 0.0F);
glVertex2f(30.0F, 75.0F);
glColor3f (0.0F, 1.0F, 0.0F);
glVertex2f(75.0F,75.0F);
glColor3f (0.0F, 0.0F, 1.0F);
glVertex2f(75.0F,30.0F);
glColor3f (1.0F, 0.0F, 0.0F);
glVertex2f(30.0F,30.0F);
glEnd ();
glFlush();
}
void IdleFunction(void)
{
pintarventana();
}
void SetDCPixelFormat(HDC hDC)
{
int nPixelFormat;
static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
8,
0,0,0,0,0,0,
0,0,
0,0,0,0,0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0,0,0 };

35
int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int
nCmdShow)
{
MSG
msg;
WNDCLASS
wc;
HWND
hWnd;
wc.style
= CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc
= (WNDPROC) WndProc;
wc.cbClsExtra
= 0;
wc.cbWndExtra
= 0;
wc.hInstance
= hInstance;
wc.hIcon
= NULL;
wc.hCursor
= LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground
= NULL;
wc.lpszMenuName
= NULL;
wc.lpszClassName
= lpszAppName;
if(RegisterClass(&wc) == 0)
return FALSE;
hWnd = CreateWindow( lpszAppName,
lpszAppName,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
WS_CLIPSIBLINGS,
0, 0,
300, 300,
NULL,
NULL,
hInstance,
NULL);
if(hWnd == NULL)
return FALSE;
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
while( GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HGLRC hRC;
static HDC hDC;
switch (message)
{
case WM_CREATE:
hDC = GetDC(hWnd);
SetDCPixelFormat(hDC);
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
SetTimer(hWnd,101,1,NULL);
break;

36
case WM_DESTROY:
KillTimer(hWnd,101);
wglMakeCurrent(hDC,NULL);
wglDeleteContext(hRC);
if(hPalette != NULL)
DeleteObject(hPalette);
PostQuitMessage(0);
break;
case WM_SIZE:
tamanoventana(LOWORD(lParam), HIWORD(lParam));
break;
case WM_TIMER:
{
IdleFunction();
InvalidateRect(hWnd,NULL,FALSE);
}
break;
case WM_PAINT:
{
pintarventana();
SwapBuffers(hDC);
ValidateRect(hWnd,NULL);
}
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (0L);
}

Listado 2.6: Dibujar ventanas con el sistema de ventanas propio de Windows

Lo que nos muestra este pequeño programa es el mismo objeto o dibujo que nos mostraba en
los ejemplos anteriores con la librería Glut y Aux, pero la forma de crear, dibujar en la ventana y el
procesado de eventos o mensajes es diferente como se puede apreciar en el código.
(Huescar, J.M., 1999)

37
2.7. Usar OPENGL
Hasta este momento se ha visto para que sirve OpenGL, que aplicaciones la utilizan, que se
puede hacer con esta librería y como trabajar y preparar las ventanas dependiendo del sistema y
plataforma para visualizar escenas hechas con OpenGL.
Ahora y de una forma rápida, ya que posteriormente se hará más hincapié en cada uno de las
cuestiones, se expondrá como usar OpenGL.

2.7.1. Dibujar en 3D
Antes de enumerar las diferentes primitivas para la creación de objetos hay que tener en cuenta
como se comporta OpenGL a la hora de dibujar.
Dibujar con OpenGL es distinto a trabajar con otras librerías o funciones; con OpenGL lo que se
hace es definir un volumen de visualización y para dibujar objetos las c
oordenadas no se indican en
pixeles, ni en coordenadas físicas si no con lo que se denomina coordenadas posiciónales en el
volumen de visualización.
Por lo que para poder trabajar con OpenGL después de crear la ventana de la

aplicación,

debemos definir la ventana de visualización o volumen de visualización donde dibujaremos los
objetos geométricos, tomando como referencia coordenadas posiciónales.

2.7.1.1. Dibujar Objetos
Después de definir el área de visualización, se pueden comenzar a dibujar objetos.
Para dibujar objetos las funciones que se utilizan son las siguientes:

glVertexXX()
Se usa para especificar las coordenadas de un vértice.
Se pueden definir vértices en dos y tres dimensiones, dependiendo del número de
coordenadas que se pasen como parámetros a la función. OpenGL trabaja
normalmente en coordenadas homogéneas representadas por cuatro componentes, (x,
y, z, h), por lo tanto cuando estamos definiendo puntos en dos dimensiones el valor z
coge el valor 0 y h el valor 1, en tres dimensiones h coge el valor 1.
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),
38
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, para ello deberemos utilizar el sufijo v
indicando que es un vector de coordenadas.

glBegin(GLenum modo)
glEnd()
Estas funciones se utilizan juntas, y permiten delimitar los vértices de la primitiva
pasada como parámetro. El valor de modo indicará la primitiva a dibujar y podrá
tomar distinto valores como puede ser GL_POINTS, GL_LINES, GL_POLYGON...

El formato para utilizar estas funciones será el siguiente:
glBegin(modo);
glVertex(x,y,z);
glVertex(x,y,z);
...
glEnd();

donde modo es el identificador del tipo a dibujar en la pantalla y glVertex es la descripción
de un punto de la pantalla.

??
Dibujar Puntos

La primitiva para dibujar puntos es GL_POINTS. Este es el parámetro que llevará la
función glBegin() y posteriormente se indicarán los puntos mediante la función glVertex().

El tamaño de los puntos a dibujar se puede cambiar utilizando la función,
glPointSize(GLfloat tamano)
??
Dibujar Líneas

Para poder dibujar una línea hay que definir dos puntos en el área de visualización. Por lo
que, entre los comandos glBegin y glEnd hay que especificar al menos dos vértices con glVertex.
39
A la hora de dibujar líneas tenemos varias opciones dependiendo de la primitiva indicada en
la función glBegin
Las primitivas disponibles para dibujar líneas son las siguientes:

GL_LINES
Genera una serie de líneas que no se conectan entre sí. Las líneas se definen
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

GL_LINE_STRIP
Genera una serie de líneas pero que se conectan entre sí, es decir el punto final 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.

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

También se le podría cambiar el tipo de línea o patrón, para que sea punteada, a rayas, con
puntos

y

rayas,

etc..

Para

glEnable(GL_LINE_STIPPLE)

ello,
y

habría

que

posteriormente

habilitar
especificar

el

patronaje
el

con

la

función

patrón

con

la

función

glLineStipple(patron).
??
Dibujar Polígonos

El dibujado de polígonos es la base de composición de objetos de OpenGL. Con lo visto
hasta ahora se pueden dibujar, puntos, líneas e incluso formas cerradas, pero no superficies sólidas.
Para ello hay un conjunto de primitivas especificas.
Las primitivas para polígonos serían las siguientes:

GL_POLYGON
Genera un simple polígono relleno con los vértices especificados

40
GL_TRIANGLES
Genera una serie de triángulos rellenos que no se conectan entre sí. El 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.

GL_TRIANGLE_STRIP
Genera una serie de triángulos rellenos conectados entre sí, y dos de los vértices de
un triángulo son los vértices del siguiente triángulo. Debemos saber que con N
vértices se pueden crear N-2 triángulos. De igual forma que anteriormente el número
de vértices debe ser múltiplo de tres, si no lo es se ignora aquellos que sobran.

GL_TRIANGLE_FAN
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 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.

GL_QUADS
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 esto entonces OpenGL
ignora los vértices que sobran. Cada cuatro vértices se describe un cuadrilátero.

GL_QUAD_STRIP
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 si tenemos un total de N vértices podremos obtener 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.

A la hora de dibujar polígonos debemos tener en cuenta dos reglas:
-

Todos los polígonos deben ser planares.

-

Los polígonos deben ser convexos.

41
El siguiente código es un ejemplo muy sencillo que muestra como utilizar estas primitivas para
crear dibujos u objetos.

void RenderScene(void)
{
GLfloat y;
GLint factor = 1;
GLushort pattern = 0x5555;
GLfloat x,z, angle;
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
glBegin(GL_POLYGON);
glVertex2f(-80.0, -80.0);
glVertex2f(-55.0, -80.0);
glVertex2f(-55.0, -55.0);
glVertex2f(-80.0, -55.0);
glEnd();
glEnable(GL_LINE_STIPPLE);
for(y = 20.0f; y < 60.0f; y += 5.0f)
{
glLineStipple(factor,pattern);
glBegin(GL_LINES);
glVertex2f(40.0f, y);
glVertex2f(80.0f, y);
glEnd();
factor++;
}
glBegin(GL_POINTS);
z = 10.0f;
for(angle = 0.0f; angle <= (2.0f*GL_PI)*3.0f; angle += 0.1f)
{
x = 15.0f*sin(angle);
y = 15.0f*cos(angle);
glVertex3f(-x, -y, z);
z += 0.5f;
}
glEnd();

glPopMatrix();
glFlush();
}
Listado 2.7: Uso de primitivas para crear objetos geométricos

42
El código anterior producirá la siguiente salida,

Figura 2.12: Puntos, lineas y polígonos

2.7.2. Transformación de Coordenadas
Los dibujos o gráficos están compuestos de las formas explicadas anteriormente, pero, para
que todas estas formas se conviertan en una escena coherente hay que colocarlas con relación a
otras formas y al observador, por esta razón habrá que saber m
over, rotar o cambiar de tamaño los
objetos, o mejor dicho, el sistema de coordenadas.
Cuando se mueve el sistema de coordenadas el efecto que produce es que se mueve el
objeto, es decir, se vuelve a redibujar con el nuevo sistema de coordenadas. Esto es lo que se
denomina transformación.

Hay varios tipos de transformación:
-

Transformación del observador: especifica la localización del observador o de la cámara.
Ésta transformación debe ser la primera en especificarse ya que será la que cambie el
sistema de coordenadas oculares.

43
-

Transformación del modelado: permite manipular tanto el modelo como los objetos que
contiene. Es decir, permitirá trasladar, rotar o escalar un objeto.

-

Transformación del modelador: describe la dualidad de las transformaciones de m
odelado y
vista.

Entre las dos transformaciones anteriores en realidad no hay ninguna diferencia ya
que da igual que se mueva el objeto hacia arriba o que se desplace el eje de coordenadas
hacia abajo.
Las funciones que nos permitirán este tipo de transformación serán:
glTranslate(GLdouble x, GLdouble y, GLdouble z)
glRotatef(Gldouble angulo, GLdouble x, GLdouble y, GLdouble z)
glScale(GLdouble x, GLdouble y, GLdouble z)
que permitirán respectivamente trasladar, rotar y escalar objetos.

-

Transformaciones de la vista: esta transformación se refiere al mapeado de la escena a
coordenadas físicas de la ventana. La función que nos permite definir este tipo de
transformación es:
gluLookAt(GLdouble ojos, GLdouble ojoy, GLdouble ojoz, GLdouble centrox,
GLdouble centroy, GLdouble centroz, GLdouble arribax, GLdouble arribay,
GLdouble arribaz)

-

Transformación de la proyección: define y dimensiona el volumen de visualización. Hay
dos tipos:
- Ortogonal. Con este tipo de perspectiva los objetos se dibujan con las dimensiones
especificadas.
- Perspectiva. Con este tipo de perspectiva la imagen parece más real, ya que se
tienen en cuenta las distancias de los objetos.

Las funciones que permiten definir estas perspectivas son,

void glOrtho(GLdouble izquierda, GLdouble derecha, GLdouble abajo, GL arriba,
GLdouble cerca, GLdouble lejos)

44
Esta función se utiliza para especificar una proyección ortográfica. Este tipo
de proyección define un volumen de vista rectangular, es decir, define un
paralelepípedo de tamaño infinito, por lo que se debe definir una serie de
planos de corte para detallar con exactitud el volumen de visualización.
Los 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.

void glFrustum(GLdouble izquierda, GLdouble derecha, GLdouble abajo, GLdouble
arriba, GLdouble cerca, GLdouble lejos)
Esta función se utiliza para definir una proyección perspectiva,

y por tanto

define como volumen de visualizacion una pirámide; el objeto a visualizar
tiene un aspecto mucho más realista.
Igual que en la proyección ortogonal 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.

gluPerpespective

(GLdouble

angulo,

GLdouble

aspecto,

GLdouble

zCerca,

GLdouble zlejos)
Esta función es muy parecida a la función glFrustum, la diferencia entre
ambas está en la forma de definir la ventana de visualización. La función
glFrustum define los dos vértices necesarios de la ventana y en la sentencia
glPerpestive solamente se definirá el ángulo de apertura de la cámara y la
relación entre el largo y ancho del plano cercano de corte.

45
Cada una de las transformaciones explicadas puede describirse como la multiplicación de dos o
más matrices.

Todos los cambios de perspectiva que se realicen son acumulativos, es decir, si por ejemplo se
rota un objeto y posteriormente se traslada, ésta traslación se hace sobre la posición que tomo
después de la rotación. Pero habrá ocasiones que necesitemos hacer operaciones sobre la situación
anterior, o bien, poder volver a la situación anterior. Para ello se pueden utilizar las siguientes
funciones:
glMatrixMode
glLoadIdentity
glPushMatrix
glPopMatrix

2.7.3. Color y Sombras
El aspecto de las aplicaciones gráficas tiene gran influencia a la hora de evaluar y decidirse
por una aplicación concreta. Por lo que el color es muy importante a la hora de realizar este tipo de
aplicaciones.

El color en los ordenadores se genera especificando intensidades separadas de las
componentes roja, verde y azul. Por esta razón los monitores se fabrican para producir estos tres
tipos de luz.
Para especificar un color utilizamos tres valores positivos (que serían las tres componentes).
Por lo que, sí un ordenador utiliza 24 bits para el almacenamiento de este tipo de información,
entonces tendríamos ocho bits para cada componente y por tanto cada componente de color se
podría especificar con valores entre 0 y 255.

De ésta forma se podría modelar los colores disponibles como un volumen llamado espacio
de color.
Si se forma un cubo a partir del espacio anterior, se obtiene un cubo con todos los colores
posibles.

46
OpenGL soporta dos modos de color:
-

RGBA, se expresa un color de forma precisa con sus tres componentes (roja, verde y
azul)

-

Modo de color indexado, se elige un color especificando un índice en una matriz de
colores (paleta). En la paleta se especifica el color exacto que se quiere seleccionando las
intensidades de las componentes roja, verde y azul.

??
Selección de un Color

La función de selección de un color es:
void glColorXT(GLX rojo, GLX verde, GLX azul)

Cuando se utiliza este comando, todos los objetos dibujados a partir de ese m
omento tendrán
el mismo color hasta que se especifique otro color.
??
Sombreado

Otro aspecto importante a la hora de dibujar es lo que se denomina sombreado, que sería la
transición suave entre un color y el siguiente, es decir, si al dibujar una línea especificamos en un
vértice un color y en el otro vértice otro color, el color de la línea que se dibujará irá variando.

El sombreado puede ser de dos tipos:
- Suave, se produce una transición suave.
- Plano, no se produce ninguna transición, normalmente con este d
egradado el color
es el del último vértice especificado.

Para cambiar el sombreado se hará con ,
void glShadeModel (Glenum modo)
donde modo puede tomar los valores GL_SMOOTH (suave) o GL_FLAT (plano).

Dentro de Color y Sombras otra cuestión importante sería la definición y creación de paletas
de colores para ajustar o elegir los colores necesarios en un momento dado para una aplicación.

47
??
Cambiar el Color de Fondo

Cuando se habla de color es importante explicar como se puede cambiar el color de fondo de
una ventana.

Según el tipo de aplicación que se quiera crear habrá que modificar el color de fondo de la
ventana.

Para modificar el color de fondo de la ventana se utiliza la siguiente función:

void glClearColor (GLclampf rojo, GLclampf verde, GLclampf azul, GLclampf alfa)
Define el color de fondo que se aplicará, utiliza los valores de RGB; Cada argumento
corresponde a la intensidad del color, Rojo, Verde y Azul, el rango de estos valores
debe ir comprendido entre el valor 0.0; El cuarto p
arámetro corresponde al valor alpha
del color que se utiliza para determinar información referente a la transparencia del
color.

Después de definido el color de fondo hay que utilizar la función glClear para borrar la
pantalla con el color que se había definido

2.7.4. Luces y Lámparas
Los objetos en el mundo real no aparecen como un color sólido y OpenGL permite hacer
una aproximación de los objetos dibujados al mundo real utilizando las funciones de iluminación.
Anteriormente, se ha visto como darle color a los objetos, pero el color de un objeto puede
variar dependiendo de la luz que incida sobre él, por lo que hay que tener en cuenta este aspecto a la
hora de seleccionar el color.

Un objeto, excepto que emita su propia luz, está iluminado por tres tipos de luz diferentes:
-

Luz ambiente, es la luz que no viene de ninguna dirección particular.

-

Luz difusa, esta luz viene de alguna dirección particular, pero es suavemente reflejada
por una superficie (como ejemplo puede ser un fluorescente)

48
-

Luz especular, es direccional, pero no se refleja nítidamente es una dirección particular
(como ejemplo se puede decir el sol)

Al igual que un color esta compuesto por tres componentes, una fuente de luz está compuesta
por tres componentes de luz también: ambiente, difusa y especular. Y así será la forma de
especificar la luz.

Para implementar y especificar la iluminación en los objetos hay que tener en cuentas
aspectos tales como que propiedades reflectivas tienen los materiales de los objetos, calcular los
efectos de la luz ambiente y los efectos de difusión y reflexión.
Por lo tanto par añadir luz a la escena lo primero que hay que hacer es activar la iluminación
con,
glEnable (GL_LIGHTTING)

Posteriormente, hay que configurar y seleccionar el modelo de iluminación.
glfloat luzambiente[]={1.0f, 1.0f, 1.0f, 1.0f}
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, luzambiente)

Y por último especificar o definir las propiedades de los materiales mediante las funciones,
glEnable(GL_COLOR_MATERIAL)
glColorMaterialfv(GLenum, cara, GLenum modo)

El uso de la luz ambiente es sencillo y tiene sus aplicaciones, pero para darle más realidad a
una escena se deben especificar varias fuentes de luz.

A la hora de especificar fuentes de luz habrá que definir además de la intensidad y color, la
localización de la fuente y la dirección.
Para indicar la posición y el color de la luz se utiliza la misma función y se cambiará el valor
de los parámetros. La función es la siguiente:
glLight(GLenum luz, GLenum pnombre, GLfloat param)

En el siguiente ejemplo se ve el efecto que produce la luz que incide sobre el cilindro
dibujado.

49
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>
void inicializar(void)
// Inicializacion de los parametros de OpenGL
{
GLfloat mat_difuso[] = {1.0,.0,1.0,1.0};
GLfloat posicion_luz[] = {1.0,1.0,1.0,0.0}; // Luz direccional
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glMaterialfv(GL_FRONT,GL_DIFFUSE ,mat_difuso);
glLightfv(GL_LIGHT0,GL_POSITION,posicion_luz);
}
void CALLBACK cambiartamano(GLsizei w, GLsizei h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0,1.0*(GLfloat)w/(GLfloat)h,1.0,200.0);
gluLookAt(0.0,0.0,5.0,0.0,0.0,0.0,0.0,1.0,0.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void CALLBACK dibujar(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
auxSolidCylinder(1.0,1.0);
glFlush();
auxSwapBuffers();
}
int main(int argc, char* argv[])
{
auxInitDisplayMode(AUX_DOUBLE|AUX_RGBA|AUX_DEPTH);
auxInitPosition(0,0,500,500);
auxInitWindow("LUCES");
inicializar();
auxReshapeFunc(cambiartamano);
auxMainLoop(dibujar);
return 0;
}

Listado 2.8: Efecto que produce una luz difusa sobre un objeto

50
La imagen que se produce con el código anterior es la siguiente,

Figura 2.5: Luces

2.7.5. Gráficos Planos en Opengl
Hasta ahora se ha visto que se pueden y como dibujar puntos, líneas, formas geométricas,
etc., pero también es importante hablar de los mapas de bits y mapas de píxeles.

2.7.5.1. Mapas de bits
Los mapas de bits son imágenes bicolor y se representan mediante arrays de dos
dimensiones rellenado con ceros y unos que permitirá crear la imagen deseada.
Los mapas de bits se suelen utilizar para crear fuentes.
Para crear mapas de bits se utilizará la función,

glBitmap(GLsizei ancho, GLsizei alto, GLfloat xorig, GLfloat yorig, GLfloat xmov,
GLfloat ymov, const GLubyte *bits)
Permite dibujar el mapa de bits que vendrá dado por *bits, que será la matriz que
contiene el mapa de bits.
51
Antes de dibujar la imagen con glBitmap hay que indicar la posición donde colocarlo
(posición raster) con la función glRasterPos()
El siguiente trozo de código nos muestra como mostrar la letra E utilizando bitmaps.
#include <windows.h>
#include <GL/gl.h>
#include <GL/glaux.h>
GLubyte ees[24]=
{
0xff, 0xc0, 0xff, 0xc0, 0xc0, 0x00, 0xc0, 0x00,
0xc0, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc0, 0x00,
0xc0, 0x00, 0xc0, 0x00, 0xff, 0xc0, 0xff, 0xc0
};

void init(void)
{
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glClearColor(1.0, 1.0, 1.0, 1.0);
}
void CALLBACK dibujar(void)
{
int i;
float pos=0.0;
float pos1=500.0;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 0.0, 1.0);
for (i = 0; i < 10; i ++)
{
glRasterPos2i(pos+i*50, pos+i*50);
glBitmap(10, 12, 0.0, 0.0, 12.0, 0.0, ees);
glRasterPos2i(pos+i*50, pos1-i*50);
glBitmap(10, 12, 0.0, 0.0, 12.0, 0.0, ees);
};
glFlush();
}
void CALLBACK cambiotamano(GLsizei w, GLsizei h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, w, 0, h, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
void main(int arg, char** argv)
{
auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);
auxInitPosition(0, 0, 500, 500);
auxInitWindow("Mapa de bits");
init();
auxReshapeFunc(cambiotamano);
auxMainLoop(dibujar);
}

52
Listado 2.9: Uso de producirá la siguiente salida,
El código anterior bitmaps

Figura 2.6: Bitmaps

2.7.5.2. Mapas de píxeles
Los mapas de píxeles son como los mapa de bits, pero la imagen tendrá mas de dos colores.
Estos se utilizan como imágenes de fondo.
En OpenGL los mapas de píxeles pueden ser imágenes de 8 bits indexadas, o bien, imágenes
RGB de 24 bits.
La función utilizada para dibujar mapas de píxeles es:
glDrawPixels(GLsizei ancho, GLsizei alto, GLenum formato, GLenum tipo, const GLvoid
*píxeles)

A la hora de trabajar con mapas de bits y de píxeles se puede hablar de los ficheros .BMP de
Windows. Trabajar con estos ficheros desde programas OpenGL es muy sencillo. Para ello se
utilizarán las estructuras BITMAPFILEHEADER y BITMAPINFOHEADER, que se encuentran
dentro de cualquier fichero .BMP al comienzo de éste. Después de estas dos estructuras vendran ya
los datos de la imagen.

53
2.7.6. Texturas
Poner texturas en los gráficos es uno de los avances más importantes en los gráficos 3D. El
mapeado de texturas es como poner papel pintado en una pared. Es decir, permite cubrir los
polígonos que forman el dibujo con imágenes.
El mapeado de texturas se utiliza para conseguir imágenes más reales.
Se pueden mapear texturas en una, dos y tres dimensiones.
Los pasos para utilizar el mapeado de texturas son,

-

Definir una imagen para textura antes de que se puedan dibujar con polígonos con
textura.
glTextImage?d(GLenum objetivo, GLint nivel, GLint componentes, GLsizei ancho,
GLint borde, GLenum formato, GLenum tipo, cons GLvoid *píxeles)

-

Después hay que habilitar el mapeado de texturas con la función,
glEnable(GL_TEXTURE_?D)

-

Por último, habrá que mapear la textura, es decir, cuando se dibuja el objeto, hay que
indicar que posición de la textura la corresponde en cada vértice,
glTextCoord??(Type *s)

2.8. Conclusiones
Depués de ver en ésta introducción las características de OpenGL y algunas de la
operaciones que se pueden realizar con ésta librería, se puede observar que es muy potente y fácil
de usar, además de tener las ventajas de portabilidad y estandarización, y por tanto OpenGL es una
buena elección para producir efectos visuales y escenas e imágenes realistas. De hecho está librería
se esta utilizando en gran cantidad de aplicaciones como ya se comento anteriormente y es muy
probable que se siga utilizando en muchas otras.

54
2.9. Bibliografía
Neider J., Davis T., Woo M. (1993) OpenGL Programming Guide. The official guide to
learning OpenGL, Release 1. Addison-Wesley Publising Company.

Richard S. Wright Jr., Sweet M. Programación en OpenGL. Anaya Multimedia

Kilgard M. (1996) The OpenGL Utility Toolkit (GLUT). Programing Interface. API Version 3.
Silicon Graphics, Inc.

Segal M., Akely K (1999). The OpenGL Graphcis System: A Specification (Version 1.2.1).
Silicon Graphics, Inc.

Segal M., Akely K (1994). The Design of the OpenGL Graphcis Interface. Silicon Graphics, Inc.

Using OpenGl to Create 2D and 3D Graphics. UCLA Academic Technology Services.
(http://www.ats.ucla.edu/at/software/scivis/Scientific

Visualization

Software

-

Using

OpenGL to Create 2D and 3D Graphics.htm)

Huescar J.M., Serra J.C., Bennasar A.F. (1999/2000). Manual de OpenGL

Sepúlveda M.A. (1988) ¿Qué es OpenGL?.
http://www.linuxfocus.org/Castellano/January1998/article15.html

Sepúlveda M.A. (1988) Programando OpenGL: Trazado de Polígonos Simples.
http://www.linuxfocus.org/Castellano/January1998/article17.html

Sepúlveda M.A. (1988) Programando OpenGL: Más sobre líneas
http://www.linuxfocus.org/Castellano/March1998/article28.html

Sepúlveda M.A. (1988) Programación OpenGL: Escenas 3D.
http://www.linuxfocus.org/Castellano/May1998/article46.html

55

Más contenido relacionado

Similar a Buenooo opengl

Gpu Lorena[1]
Gpu Lorena[1]Gpu Lorena[1]
Gpu Lorena[1]
lorena200925
 
Open gl. endcynthia
Open gl. endcynthiaOpen gl. endcynthia
Open gl. endcynthiacynthitap
 
Open gl. endcynthia
Open gl. endcynthiaOpen gl. endcynthia
Open gl. endcynthia
cynthitap
 
Open gl endcynthia
Open gl endcynthiaOpen gl endcynthia
Open gl endcynthiacynthitap
 
Manual de practicas segundo parcial
Manual de practicas segundo parcialManual de practicas segundo parcial
Manual de practicas segundo parcial
Guillermo Mendoza
 
Artec alternativas moviles
Artec alternativas movilesArtec alternativas moviles
Artec alternativas movilespmorillo
 
Análisis de Alternativas para el Desarrollo de Aplicaciones Gráficas 3D
Análisis de Alternativas para el Desarrollo de Aplicaciones Gráficas 3DAnálisis de Alternativas para el Desarrollo de Aplicaciones Gráficas 3D
Análisis de Alternativas para el Desarrollo de Aplicaciones Gráficas 3DRubén Talón Argente
 
Análisis de alternativas para el desarrollo de aplicaciones gráficas 3D sobre...
Análisis de alternativas para el desarrollo de aplicaciones gráficas 3D sobre...Análisis de alternativas para el desarrollo de aplicaciones gráficas 3D sobre...
Análisis de alternativas para el desarrollo de aplicaciones gráficas 3D sobre...Rubén Talón Argente
 
Simuladores
SimuladoresSimuladores
Simuladores
Aleex Hermosillo
 
NSCoder - Metal
NSCoder - MetalNSCoder - Metal
NSCoder - Metal
NSCoder Mexico
 
Andrid studio
Andrid studioAndrid studio
Andrid studio
jorgerodriguezsaavedra
 
Informe
InformeInforme
Informe
carokeys
 
2-CapaPercepción.pdf
2-CapaPercepción.pdf2-CapaPercepción.pdf
2-CapaPercepción.pdf
LUISROSALESROLDAN
 
Softwares
SoftwaresSoftwares
Softwares
jhonnypedro456
 
Direct Xy Open Gl
Direct Xy Open GlDirect Xy Open Gl
Direct Xy Open Gl
guest5506a9
 
Software libre en la ingeniería.Charla2
Software libre en la ingeniería.Charla2Software libre en la ingeniería.Charla2
Software libre en la ingeniería.Charla2
Vicente Mataix Ferrándiz
 
Gráficos 3D en Linux con Mesa (GPUL Labs Meetup)
Gráficos 3D en Linux con Mesa (GPUL Labs Meetup)Gráficos 3D en Linux con Mesa (GPUL Labs Meetup)
Gráficos 3D en Linux con Mesa (GPUL Labs Meetup)
Igalia
 

Similar a Buenooo opengl (20)

Open gl chica
Open gl chicaOpen gl chica
Open gl chica
 
Gpu Lorena[1]
Gpu Lorena[1]Gpu Lorena[1]
Gpu Lorena[1]
 
Open gl. endcynthia
Open gl. endcynthiaOpen gl. endcynthia
Open gl. endcynthia
 
Open gl. endcynthia
Open gl. endcynthiaOpen gl. endcynthia
Open gl. endcynthia
 
Open gl endcynthia
Open gl endcynthiaOpen gl endcynthia
Open gl endcynthia
 
Manual de practicas segundo parcial
Manual de practicas segundo parcialManual de practicas segundo parcial
Manual de practicas segundo parcial
 
Artec alternativas moviles
Artec alternativas movilesArtec alternativas moviles
Artec alternativas moviles
 
Análisis de Alternativas para el Desarrollo de Aplicaciones Gráficas 3D
Análisis de Alternativas para el Desarrollo de Aplicaciones Gráficas 3DAnálisis de Alternativas para el Desarrollo de Aplicaciones Gráficas 3D
Análisis de Alternativas para el Desarrollo de Aplicaciones Gráficas 3D
 
Análisis de alternativas para el desarrollo de aplicaciones gráficas 3D sobre...
Análisis de alternativas para el desarrollo de aplicaciones gráficas 3D sobre...Análisis de alternativas para el desarrollo de aplicaciones gráficas 3D sobre...
Análisis de alternativas para el desarrollo de aplicaciones gráficas 3D sobre...
 
Simuladores
SimuladoresSimuladores
Simuladores
 
NSCoder - Metal
NSCoder - MetalNSCoder - Metal
NSCoder - Metal
 
Práctica no1.1
Práctica  no1.1Práctica  no1.1
Práctica no1.1
 
Práctica no1.1
Práctica  no1.1Práctica  no1.1
Práctica no1.1
 
Andrid studio
Andrid studioAndrid studio
Andrid studio
 
Informe
InformeInforme
Informe
 
2-CapaPercepción.pdf
2-CapaPercepción.pdf2-CapaPercepción.pdf
2-CapaPercepción.pdf
 
Softwares
SoftwaresSoftwares
Softwares
 
Direct Xy Open Gl
Direct Xy Open GlDirect Xy Open Gl
Direct Xy Open Gl
 
Software libre en la ingeniería.Charla2
Software libre en la ingeniería.Charla2Software libre en la ingeniería.Charla2
Software libre en la ingeniería.Charla2
 
Gráficos 3D en Linux con Mesa (GPUL Labs Meetup)
Gráficos 3D en Linux con Mesa (GPUL Labs Meetup)Gráficos 3D en Linux con Mesa (GPUL Labs Meetup)
Gráficos 3D en Linux con Mesa (GPUL Labs Meetup)
 

Último

1º GRADO CONCLUSIONES DESCRIPTIVAS PRIMARIA.docx
1º GRADO CONCLUSIONES DESCRIPTIVAS  PRIMARIA.docx1º GRADO CONCLUSIONES DESCRIPTIVAS  PRIMARIA.docx
1º GRADO CONCLUSIONES DESCRIPTIVAS PRIMARIA.docx
FelixCamachoGuzman
 
Proceso de admisiones en escuelas infantiles de Pamplona
Proceso de admisiones en escuelas infantiles de PamplonaProceso de admisiones en escuelas infantiles de Pamplona
Proceso de admisiones en escuelas infantiles de Pamplona
Edurne Navarro Bueno
 
El fundamento del gobierno de Dios. Lec. 09. docx
El fundamento del gobierno de Dios. Lec. 09. docxEl fundamento del gobierno de Dios. Lec. 09. docx
El fundamento del gobierno de Dios. Lec. 09. docx
Alejandrino Halire Ccahuana
 
FORTI-JUNIO 2024. CIENCIA, EDUCACION, CULTURA,pdf
FORTI-JUNIO 2024. CIENCIA, EDUCACION, CULTURA,pdfFORTI-JUNIO 2024. CIENCIA, EDUCACION, CULTURA,pdf
FORTI-JUNIO 2024. CIENCIA, EDUCACION, CULTURA,pdf
El Fortí
 
c3.hu3.p3.p2.Superioridad e inferioridad en la sociedad.pptx
c3.hu3.p3.p2.Superioridad e inferioridad en la sociedad.pptxc3.hu3.p3.p2.Superioridad e inferioridad en la sociedad.pptx
c3.hu3.p3.p2.Superioridad e inferioridad en la sociedad.pptx
Martín Ramírez
 
Portafolio de servicios Centro de Educación Continua EPN
Portafolio de servicios Centro de Educación Continua EPNPortafolio de servicios Centro de Educación Continua EPN
Portafolio de servicios Centro de Educación Continua EPN
jmorales40
 
3° UNIDAD 3 CUIDAMOS EL AMBIENTE RECICLANDO EN FAMILIA 933623393 PROF YESSENI...
3° UNIDAD 3 CUIDAMOS EL AMBIENTE RECICLANDO EN FAMILIA 933623393 PROF YESSENI...3° UNIDAD 3 CUIDAMOS EL AMBIENTE RECICLANDO EN FAMILIA 933623393 PROF YESSENI...
3° UNIDAD 3 CUIDAMOS EL AMBIENTE RECICLANDO EN FAMILIA 933623393 PROF YESSENI...
rosannatasaycoyactay
 
Fase 1, Lenguaje algebraico y pensamiento funcional
Fase 1, Lenguaje algebraico y pensamiento funcionalFase 1, Lenguaje algebraico y pensamiento funcional
Fase 1, Lenguaje algebraico y pensamiento funcional
YasneidyGonzalez
 
CALENDARIZACION DEL MES DE JUNIO - JULIO 24
CALENDARIZACION DEL MES DE JUNIO - JULIO 24CALENDARIZACION DEL MES DE JUNIO - JULIO 24
CALENDARIZACION DEL MES DE JUNIO - JULIO 24
auxsoporte
 
FICHA DE EJERCICIOS GRECIA 1º DE LA ESO HISTORIA
FICHA DE EJERCICIOS GRECIA 1º DE LA ESO HISTORIAFICHA DE EJERCICIOS GRECIA 1º DE LA ESO HISTORIA
FICHA DE EJERCICIOS GRECIA 1º DE LA ESO HISTORIA
JavierMontero58
 
Introducción a la ciencia de datos con power BI
Introducción a la ciencia de datos con power BIIntroducción a la ciencia de datos con power BI
Introducción a la ciencia de datos con power BI
arleyo2006
 
Semana #10-PM3 del 27 al 31 de mayo.pptx
Semana #10-PM3 del 27 al 31 de mayo.pptxSemana #10-PM3 del 27 al 31 de mayo.pptx
Semana #10-PM3 del 27 al 31 de mayo.pptx
LorenaCovarrubias12
 
INFORME MINEDU DEL PRIMER SIMULACRO 2024.pdf
INFORME MINEDU DEL PRIMER SIMULACRO 2024.pdfINFORME MINEDU DEL PRIMER SIMULACRO 2024.pdf
INFORME MINEDU DEL PRIMER SIMULACRO 2024.pdf
Alejandrogarciapanta
 
CONCLUSIONES-DESCRIPTIVAS NIVEL PRIMARIA
CONCLUSIONES-DESCRIPTIVAS NIVEL PRIMARIACONCLUSIONES-DESCRIPTIVAS NIVEL PRIMARIA
CONCLUSIONES-DESCRIPTIVAS NIVEL PRIMARIA
BetzabePecheSalcedo1
 
PRESENTACION DE LA SEMANA NUMERO 8 EN APLICACIONES DE INTERNET
PRESENTACION DE LA SEMANA NUMERO 8 EN APLICACIONES DE INTERNETPRESENTACION DE LA SEMANA NUMERO 8 EN APLICACIONES DE INTERNET
PRESENTACION DE LA SEMANA NUMERO 8 EN APLICACIONES DE INTERNET
CESAR MIJAEL ESPINOZA SALAZAR
 
Asistencia Tecnica Cartilla Pedagogica DUA Ccesa007.pdf
Asistencia Tecnica Cartilla Pedagogica DUA Ccesa007.pdfAsistencia Tecnica Cartilla Pedagogica DUA Ccesa007.pdf
Asistencia Tecnica Cartilla Pedagogica DUA Ccesa007.pdf
Demetrio Ccesa Rayme
 
Conocemos la ermita de Ntra. Sra. del Arrabal
Conocemos la ermita de Ntra. Sra. del ArrabalConocemos la ermita de Ntra. Sra. del Arrabal
Conocemos la ermita de Ntra. Sra. del Arrabal
Profes de Relideleón Apellidos
 
CLASE N.1 ANÁLISIS ADMINISTRATIVO EMPRESARIAL presentación.pptx
CLASE N.1 ANÁLISIS ADMINISTRATIVO EMPRESARIAL presentación.pptxCLASE N.1 ANÁLISIS ADMINISTRATIVO EMPRESARIAL presentación.pptx
CLASE N.1 ANÁLISIS ADMINISTRATIVO EMPRESARIAL presentación.pptx
LilianaRivera778668
 
UNIDAD DE APRENDIZAJE DEL MES Junio 2024
UNIDAD DE APRENDIZAJE DEL MES  Junio 2024UNIDAD DE APRENDIZAJE DEL MES  Junio 2024
UNIDAD DE APRENDIZAJE DEL MES Junio 2024
EdwardYumbato1
 
Septima-Sesion-Ordinaria-del-Consejo-Tecnico-Escolar-y-el-Taller-Intensivo-de...
Septima-Sesion-Ordinaria-del-Consejo-Tecnico-Escolar-y-el-Taller-Intensivo-de...Septima-Sesion-Ordinaria-del-Consejo-Tecnico-Escolar-y-el-Taller-Intensivo-de...
Septima-Sesion-Ordinaria-del-Consejo-Tecnico-Escolar-y-el-Taller-Intensivo-de...
AracelidelRocioOrdez
 

Último (20)

1º GRADO CONCLUSIONES DESCRIPTIVAS PRIMARIA.docx
1º GRADO CONCLUSIONES DESCRIPTIVAS  PRIMARIA.docx1º GRADO CONCLUSIONES DESCRIPTIVAS  PRIMARIA.docx
1º GRADO CONCLUSIONES DESCRIPTIVAS PRIMARIA.docx
 
Proceso de admisiones en escuelas infantiles de Pamplona
Proceso de admisiones en escuelas infantiles de PamplonaProceso de admisiones en escuelas infantiles de Pamplona
Proceso de admisiones en escuelas infantiles de Pamplona
 
El fundamento del gobierno de Dios. Lec. 09. docx
El fundamento del gobierno de Dios. Lec. 09. docxEl fundamento del gobierno de Dios. Lec. 09. docx
El fundamento del gobierno de Dios. Lec. 09. docx
 
FORTI-JUNIO 2024. CIENCIA, EDUCACION, CULTURA,pdf
FORTI-JUNIO 2024. CIENCIA, EDUCACION, CULTURA,pdfFORTI-JUNIO 2024. CIENCIA, EDUCACION, CULTURA,pdf
FORTI-JUNIO 2024. CIENCIA, EDUCACION, CULTURA,pdf
 
c3.hu3.p3.p2.Superioridad e inferioridad en la sociedad.pptx
c3.hu3.p3.p2.Superioridad e inferioridad en la sociedad.pptxc3.hu3.p3.p2.Superioridad e inferioridad en la sociedad.pptx
c3.hu3.p3.p2.Superioridad e inferioridad en la sociedad.pptx
 
Portafolio de servicios Centro de Educación Continua EPN
Portafolio de servicios Centro de Educación Continua EPNPortafolio de servicios Centro de Educación Continua EPN
Portafolio de servicios Centro de Educación Continua EPN
 
3° UNIDAD 3 CUIDAMOS EL AMBIENTE RECICLANDO EN FAMILIA 933623393 PROF YESSENI...
3° UNIDAD 3 CUIDAMOS EL AMBIENTE RECICLANDO EN FAMILIA 933623393 PROF YESSENI...3° UNIDAD 3 CUIDAMOS EL AMBIENTE RECICLANDO EN FAMILIA 933623393 PROF YESSENI...
3° UNIDAD 3 CUIDAMOS EL AMBIENTE RECICLANDO EN FAMILIA 933623393 PROF YESSENI...
 
Fase 1, Lenguaje algebraico y pensamiento funcional
Fase 1, Lenguaje algebraico y pensamiento funcionalFase 1, Lenguaje algebraico y pensamiento funcional
Fase 1, Lenguaje algebraico y pensamiento funcional
 
CALENDARIZACION DEL MES DE JUNIO - JULIO 24
CALENDARIZACION DEL MES DE JUNIO - JULIO 24CALENDARIZACION DEL MES DE JUNIO - JULIO 24
CALENDARIZACION DEL MES DE JUNIO - JULIO 24
 
FICHA DE EJERCICIOS GRECIA 1º DE LA ESO HISTORIA
FICHA DE EJERCICIOS GRECIA 1º DE LA ESO HISTORIAFICHA DE EJERCICIOS GRECIA 1º DE LA ESO HISTORIA
FICHA DE EJERCICIOS GRECIA 1º DE LA ESO HISTORIA
 
Introducción a la ciencia de datos con power BI
Introducción a la ciencia de datos con power BIIntroducción a la ciencia de datos con power BI
Introducción a la ciencia de datos con power BI
 
Semana #10-PM3 del 27 al 31 de mayo.pptx
Semana #10-PM3 del 27 al 31 de mayo.pptxSemana #10-PM3 del 27 al 31 de mayo.pptx
Semana #10-PM3 del 27 al 31 de mayo.pptx
 
INFORME MINEDU DEL PRIMER SIMULACRO 2024.pdf
INFORME MINEDU DEL PRIMER SIMULACRO 2024.pdfINFORME MINEDU DEL PRIMER SIMULACRO 2024.pdf
INFORME MINEDU DEL PRIMER SIMULACRO 2024.pdf
 
CONCLUSIONES-DESCRIPTIVAS NIVEL PRIMARIA
CONCLUSIONES-DESCRIPTIVAS NIVEL PRIMARIACONCLUSIONES-DESCRIPTIVAS NIVEL PRIMARIA
CONCLUSIONES-DESCRIPTIVAS NIVEL PRIMARIA
 
PRESENTACION DE LA SEMANA NUMERO 8 EN APLICACIONES DE INTERNET
PRESENTACION DE LA SEMANA NUMERO 8 EN APLICACIONES DE INTERNETPRESENTACION DE LA SEMANA NUMERO 8 EN APLICACIONES DE INTERNET
PRESENTACION DE LA SEMANA NUMERO 8 EN APLICACIONES DE INTERNET
 
Asistencia Tecnica Cartilla Pedagogica DUA Ccesa007.pdf
Asistencia Tecnica Cartilla Pedagogica DUA Ccesa007.pdfAsistencia Tecnica Cartilla Pedagogica DUA Ccesa007.pdf
Asistencia Tecnica Cartilla Pedagogica DUA Ccesa007.pdf
 
Conocemos la ermita de Ntra. Sra. del Arrabal
Conocemos la ermita de Ntra. Sra. del ArrabalConocemos la ermita de Ntra. Sra. del Arrabal
Conocemos la ermita de Ntra. Sra. del Arrabal
 
CLASE N.1 ANÁLISIS ADMINISTRATIVO EMPRESARIAL presentación.pptx
CLASE N.1 ANÁLISIS ADMINISTRATIVO EMPRESARIAL presentación.pptxCLASE N.1 ANÁLISIS ADMINISTRATIVO EMPRESARIAL presentación.pptx
CLASE N.1 ANÁLISIS ADMINISTRATIVO EMPRESARIAL presentación.pptx
 
UNIDAD DE APRENDIZAJE DEL MES Junio 2024
UNIDAD DE APRENDIZAJE DEL MES  Junio 2024UNIDAD DE APRENDIZAJE DEL MES  Junio 2024
UNIDAD DE APRENDIZAJE DEL MES Junio 2024
 
Septima-Sesion-Ordinaria-del-Consejo-Tecnico-Escolar-y-el-Taller-Intensivo-de...
Septima-Sesion-Ordinaria-del-Consejo-Tecnico-Escolar-y-el-Taller-Intensivo-de...Septima-Sesion-Ordinaria-del-Consejo-Tecnico-Escolar-y-el-Taller-Intensivo-de...
Septima-Sesion-Ordinaria-del-Consejo-Tecnico-Escolar-y-el-Taller-Intensivo-de...
 

Buenooo opengl

  • 1. 5º Ingeniería Informática Informática Gráfica Capitulo 2: Introducción a OpenGL Montserrat Mateos Sánchez
  • 2. Introducción OpenGL 2.1. INTRODUCCIÓN ...................................................................................................................... 3 2.2 RESEÑA HISTÓRICA ............................................................................................................... 4 2.3. ¿QUÉ ES OPENGL? .................................................................................................................. 5 2.3.1. CARACTERÍSTICAS DE OPEN GL .............................................................................................. 5 2.4. APLICACIONES ........................................................................................................................ 8 2.5. LIBRERÍAS RELACIONADAS CON OPENGL ................................................................. 11 2.5.1 GLUT (O PENGL UTILITY TOOLKIT) ..................................................................................... 12 2.5.1.1. Características .............................................................................................................. 12 2.5.1.2. Funciones de GLUT...................................................................................................... 12 2.5.2 LIBRERÍA AUX ...................................................................................................................... 23 2.5.2.1. Características .............................................................................................................. 23 2.5.2.2. Funciones ...................................................................................................................... 24 2.6. PROGRAMACIÓN CON OPENGL PARA WINDOWS. WIGGLE ................................. 27 2.6.1. FUNCIÓN W INMAIN .............................................................................................................. 28 2.6.2. FUNCIÓN W NDPROC ............................................................................................................. 30 2.6.3. DIBUJAR EN UNA VENTANA DE WINDOWS............................................................................. 32 2.7. USAR OPENGL ........................................................................................................................ 38 2.7.1. DIBUJAR EN 3D..................................................................................................................... 38 2.7.1.1. Dibujar Objetos ............................................................................................................ 38 2.7.2. TRANSFORMACIÓN DE COORDENADAS ................................................................................. 43 2.7.3. COLOR Y SOMBRAS............................................................................................................... 46 2.7.4. LUCES Y LÁMPARAS ............................................................................................................. 48 2.7.5. GRÁFICOS P LANOS EN OPENGL ............................................................................................. 51 2.7.5.1. Mapas de bits ................................................................................................................ 51 2.7.5.2. Mapas de píxeles ........................................................................................................... 53 2.7.6. TEXTURAS............................................................................................................................. 54 2.8. CONCLUSIONES ..................................................................................................................... 54 2.9. BIBLIOGRAFÍA....................................................................................................................... 55 2
  • 3. 2. Introducción OpenGL 2.1. Introducción Utilizar información gráfica se ha convertido en el mundo de la computación en un recurso habitual para la comunicación entre los ordenadores y los usuarios. Este tipo de información no solo se usa para la gestión de las aplicaciones a través de la utilización de menús y ventanas, sino que cada vez se usa más para la representación gráfica de imágenes reales. Las imágenes reales o con efectos realistas se consiguen aproximando al máximo la representación gráfica que se genera en la pantalla del ordenador a las imágenes que percibe el ser humano con la vista. Para dar realismo a las imágenes por ordenador se utilizan técnicas de sombreado, brillo, nieblas, transparencias etc. El empleo de imágenes tridimensionales o con realismo gráfico es un recurso más, dentro de los que se dispone para el desarrollo de cualquier aplicación informática. El uso de manera eficiente de todos estos recursos, así como, la estandarización de los procedimientos de generación de gráficos por computador, se abordaron por primera vez con las librerías de gráficos OpenGL. El que todas las aplicaciones que presentan gráficos por computador sigan los mismos patrones, representa una importante ventaja en cuanto a la portabilidad entre sistemas diferentes. Si además esos patrones se ajustan a modelos y métodos avanzados y eficientes para la representación gráfica por ordenador, entonces se tiene la herramienta ideal. Todo esto lo cumple la librería OpenGL, compatibilidad y versatilidad. Pocos efectos gráficos quedan fuera de las capacidades que tienen las OpenGL y cada vez más sistemas permiten la ejecución de aplicaciones basadas en OpenGL. En éste capitulo de introducción a OpenGL, primero se explicará que es OpenGL, junto sus características más destacadas, posteriormente se explicarán de forma muy rápida algunas de las librerías relacionadas con ésta y por último y de forma rápida se mostrarán algunas de las funciones de OpenGL. 3
  • 4. 2.2 Reseña Histórica OpenGL, se puede considerar como una norma industrial. Su antecesora fue GL (Graphics Library) desarrollada por Silicon Graphics, Inc. (líder mundial en gráficos y animaciones por ordenador) en 1982. Iris GL fue la primera API (Aplication Programing Interface) de programación para las estaciones gráficas IRIS de alto rendimiento de la compañía. Estas máquinas, contaban con un hardware optimizado para la visualización de gráficos. Con éste hardware, se podía entre otras cosas, realizar transformaciones matriciales muy rápidas, además proporcionaban soporte grafico para el buffer de profundidad y otras prestaciones. Las subrutinas de GL hacen uso directo de las tarjetas gráficas instaladas en las estaciones de trabajo; los gráficos GL normalmente se refieren a gráficos hardware, en oposición a gráficos X Windows, que se refieren a gráficos software. Cuando se realiza renderización software, la imagen gráfica es creada vía el software que está corriendo en la máquina. La imagen renderizada es entonces visualizada en una ventana llamada X. Con el renderizado por hardware, la mayor parte del trabajo de crear la imagen la hace la tarjeta gráfica. GL incluye soporte para conseguir desde dispositivos la entrada de datos, crear y dibujar en ventanas, configuración y control del buffer y renderizado 3D básico y avanzado. GL fue elegido por IBM como el API para soportar los adaptadores gráficos que fueron instalados en las estaciones de trabajo de la serie RS/6000, y fue usado por mas de 1500 aplicaciones incluyendo IBM Data Explorer, AVS, Grass, (www.ats.ucla.edu) Pero, IRIS GL no era portable a otras plataformas hardware con lo que se trabajó sobre ello y apareció OpenGL. Este nuevo lenguaje, debía ofrecer la potencia de GL y a la vez, ser más abierto para su adaptación tanto a otras plataformas hardware así como a otros sistemas operativos. El 1 de Julio de 1992 se presentó la versión 1.0 de la especificación de OpenGL. Poco después, en la sala de exhibición de empresas se expuso la proyección de secuencias de películas 4
  • 5. como Terminator 2, El juicio final y algunas aplicaciones médicas gráficas creadas con OpenGL, y esto tuvo un gran impacto. En 1995 se aprobó la especificación final de la versión 1.1 de OpenGL. (Sweet, M. et all) Actualmente, existe la Plataforma para Revisiones de la Arquitectura OpenGL (ARB), está formada por SGI, DEC , IBM, Intel, Microsoft, se reúne dos veces al año y es la que decide las mejoras de OpenGL. Estas reuniones o encuentros, son de carácter público y puede asistir cualquier compañía aunque solo tienen derecho a voto las anteriores. 2.3. ¿Qué es OpenGL? OpenGL, es una interfaz software para gráficos por hardware. Es una biblioteca de trazado de gráficos de alto rendimiento, fácil de usar, intuitivo, portable, en el que el programador describe las llamadas necesarias a funciones y comandos para conseguir una escena, apariencia o efecto. Consta de 120 comandos o funciones distintos que tienen la misma sintaxis; e stas funciones, se pueden usar para especificar objetos y las operaciones necesarias para desarrollar aplicaciones gráficas interactivas 2D y 3D; Los algoritmos que utiliza fueron desarrollados y optimizados por Silicon Graphics. (Neider, J. et all). 2.3.1. Características de OpenGL OpenGL es por diseño independiente del hardware, sistema operativo o sistema de ventanas. Las funciones de OpenGL trabajan de la misma forma en cualquier plataforma, es decir, se pueden llamar a las funciones de OpenGL desde un programa escrito y obtener los mismos resultados independientemente del lugar donde el programa se este ejecutando. Esto hace que sea portable y la programación sea más fácil con OpenGL que con un API integrado en el sistema de ventanas. Para conseguir la independencia del hardware, OpenGL no incluye ninguna función para la gestión de ventanas, interactividad con el usuario ni manejo de ficheros. Cada sistema operativo tiene sus propias funciones para realizar estas tareas, por lo que, los programas creados con OpenGL deben interactuar con el sistema de ventanas de la plataforma donde os gráficos serán l visualizados ya que los gráficos, son normalmente visualizados en una ventana. Hay varias 5
  • 6. herramientas y librerías para el manejo de ventanas que han sido desarrolladas para trabajar con OpenGL. (www.linuxfocus.org) Está diseñado para trabajar eficientemente en un entorno cliente/servidor; Existe un protocolo para mover por la red los comandos de OpenGL entre el servidor y el cliente. De esta forma el ordenador que visualiza los gráficos no es el mismo que ejecuta el programa de gráficos, es decir, el programa o aplicación que produce los gráficos puede correr en otra maquina distinta en la que se están visualizando los gráficos, e incluso el cliente y el servidor no tienen porque ejecutarse en el mismo tipo de plataforma o sistema operativo. (www.ats.ucla.edu) Las funciones de OpenGL como ya se comentó anteriormente, están diseñadas para permitir crear gráficos 2D y 3D con especial énfasis en 3D. OpenGL tiene funciones o primitivas con las que se podrá realizar modelado 3D, transformaciones, utilización de color e iluminación, sombras, mapeado de texturas, animación, movimiento borroso.... Para conseguir rendimiento no tiene comandos para describir modelos complejos (mapas, pájaros, moléculas, etc) sino que tiene primitivas que permiten dibujar puntos, líneas y polígonos, y es el programador el que tendrá que construir objetos más complejos. Con OpenGL cualquier comando es ejecutado inmediatamente. Cuando en un programa se especifica que dibuje algo, lo hace inmediatamente. Pero existe la opción de poner comandos en Display Lists. Una display list es una lista no editable de comandos almacenados para una ejecución posterior y se puede ejecutar más de una vez. Por ejemplo, se pueden usar para redibujar el grafico cuando el usuario cambia el tamaño de la ventana, también se puede utilizar para dibujar la misma forma mas de una vez si esta se repite como un elemento de un grafico. Todos los comandos de OpenGL utilizan la misma sintaxis. Todos ellos usan el prefijo gl y después la palabra que forma el comando con la primera letra en mayúscula. También en algunos comandos va seguido como sufijo un numero y una letra, que indican el número de parámetros del comando y el tipo de sus argumentos. Así por ejemplo, glColor3f(1.0,1.0,1.0) Éste comando es de OpenGL y permite cambiar el color activo (Color) y tendrá 3 parámetros de tipo float. 6
  • 7. Además, algunos comandos pueden llevar la letra v al final que indica que el parámetro de la función es un puntero a un array o vector. OpenGL se puede considerar como una máquina de estados. Las aplicaciones se pueden poner en varios estados que permanecen en efecto hasta que se cambian. Por ejemplo el color, se puede poner un color y dibujar un objeto, y ese color seguirá activo hasta que se ponga otro color. Igual que ocurre con el color, OpenGL tiene otra variables de estado para otros controles tales como la vista actual y transformación de proyecciones, posiciones y características de luces y propiedades del material que los objetos están siendo dibujados. Algunas de estas variables de estado se pueden habilitar o deshabilitar con los comandos glEnable() o glDisable(). Cada variable de estado tiene un valor por defecto y el programador podrá preguntar el valor actual de cada una de estas variables. Además, también se podrá almacenar el valor de estas variables de estado para posteriormente recuperarlo. Las funciones que permiten hacer esto son glPushAttrib() y glPopAttrib(). OpenGL ha sido diseñado para ser llamado por C, C++, Fortran, Ada, Java. Aunque todos los manuales y documentación de opengl vienen con C. Otros lenguajes de programación como Visual Basic que pueden invocar a funciones de C, también podrán hacer uso de OpenGL. Con OpenGL se debe seguir un o rden para la realización de las operaciones graficas necesarias para renderizar una imagen en la pantalla, lo primero que se debe hacer es construir formas desde la primitivas geométricas, después disponer los objetos en el espacio tridimensional y seleccionar la posición deseada para ver la composición, posteriormente calcular el color para todos los objetos y por último convertir la descripción matemática de los objetos y su información de color asociada a píxeles en la pantalla (rasterización). OpenGL tene sus propios tipos de datos para así hacer el código mas fácilmente portable, i aunque estos tipos de datos corresponden con los tipos de datos de C, y por tanto se podrán utilizar unos u otros indistintamente. Pero si es importante tener en cuenta que si se utilizan los tipos de datos de C, dependiendo del compilador y entorno habrá unas reglas para planificar el espacio de memoria de varias variables. Así que, para evitar esto se deben utilizar los tipos de Opengl. 7
  • 8. Todos los tipos de opengl tienen el sufijo gl y a continuación el tipo de C correspondiente. La siguiente tabla nos lo muestra: Tipo de dato en Definición como tipo C Representación interna Glbyte Char con signo Entero de 8 bits Glshort Short Entero de 16 bits GLint, Glsizei Long Entero de 32 bits GLfloat, GLclampf Float Coma flotante de 32 bits Gldouble, GLclampd Double Coma flotante de 64 bits GLubyte, GLboolean Unsigned char Entero de 8 bits sin signo Glushort Unsigned short Entero de 16 bits sin signo GLuint, GLenum, Unsigned long Entero de 32 bits sin signo OpenGL Glbitfield Tabla 2.1: Tipos de OpenGL (Huescar M. et all) 2.4. Aplicaciones OpenGL es la API para gráficos 3D más utilizada para aplicaciones gráficas, tanto profesionales como de consumo, así como para juegos y se usa para una amplia variedad de fines. Se pueden distinguir las siguientes categorías: - Software para modelado, rendering y efectos animados. Algunas aplicaciones podrían ser: ? Carrara, modelado, rendering, construcción de escenas y animaciones ? ? Inferno, crear efectos visuales 3d para películas ? ? 3Space Publisher, para crear gráficos y animaciones 3D para la web ? - Aplicaciones CAD para diseño, ingeniería y arquitectura: ? SoftCAD ? ? Kinetix ? ? Actify ? - Herramientas y librerias para el desarrollo de aplicaciones y juegos. 8
  • 9. ? 3D Charting Toolkit ? ? 3D MasterSuite ? ? AllegroGL ? ? 3D game engine scene composer & player ? ? Surrender ? - Juegos ? Azteroids ? ? Diablo II ? ? Quake II ? ? Star Trek Voyager – Elite Force ? ? Ultimate Golf ? - Realidad virtual ? VRWave ? ? V-Realm Builder ? ? Envision ? - Salvapantallas ? Physical Toy screen saber ? ? Screensaver fighter game ? - Aplicaciones de simulación y visualización ? Amira, visualización 3D para medicina ? ? HiQ, visualización de datos de laboratorio ? ? SimFUSION, Simulador y generador de imágenes ? - Aplicaciones científicas, médicas y de análisis de datos ? Momol, modelado molecular ? ? Functor, análisis gráficos de funciones algebraicas ? ? MapRender3D ? ? Solar System Simulation ? (www.opengl.org) 9
  • 10. Algunos ejemplos sencillos de escenas que se pueden hacer con OpenGL podrían ser los siguientes: Figura 2.2: Figuras geométicas Figura 2.1: Animación 10
  • 11. Figura 2.5: Perspectiva Figura 2.6: Perspectiva Figura 2.7: Sombras Figura 2.8: Texturas 2.5. Librerías relacionadas con OpenGL Hay que destacar que la API de OpenGL está divida en tres librerías distintas: - AUX, (denominada también librería de recursos, glaux.lib, glaux.h) . Es una librería que proporciona una estructura de trabajo independiente de la plataforma para invocar a las funciones de opengl. Todas las funciones comienzan con el sufijo aux. - Funciones que definen OPENGL (es la propia librería, opengl32.dll, gl.h). - La librería glu32.dll, y su cabecera glu.h. Esta librería contiene funciones útiles que hacen el trabajo diario más sencillo, como el dibujo de esferas, discos, cilindros. Esta escrita usando funciones y comandos de opengl. 11
  • 12. Otro aspecto a tener en cuenta a la hora de hablar de las librerías relacionadas con OpenGL, es que la especificación de OpenGL se aisló de cualquier dependencia de un sistema de ventanas concreto, y por tanto, es el sistema de ventanas nativo el encargado de abrir y trazar ventanas. Por eso OpenGL debe comunicarse con el sistema nativo a través de librerias adicionales auxiliares, como por ejemplo GLX (interacción entre OpenGL y el sistema Windows), GLUT, y otras. 2.5.1 GLUT (OpenGL Utility Toolkit) 2.5.1.1. Características - GLUT ofrece una interfaz común para múltiples plataformas para el manejo de ventanas, buffers, renderización de texto, entrada por teclado y menús, por lo que, los desarrolladores podrán usar un interface común para el sistema de ventanas independiente de la plataforma, es decir, las aplicaciones de OpenGl que usan GLUT se pueden portar entre plataformas sin tener que introducir muchos cambios en el código fuente. - Es un interfaz de programación con enlaces para ANSI C y FORTRAN que, permitirá e scribir programas OpenGL independientes del sistema de ventanas. - Al igual que OpenGL, utiliza una serie de variables de estado que duran toda la ejecución de la aplicación, y luego el programador podrá modificar el valor de dichas variables para ajustarlas. - Es pequeño y fácil de aprender. Las funciones de GLUT son simples, tienen pocos parámetros y no manejan punteros excepto los punteros a cadenas de caracteres y manejadores de fuentes que se le pasan a algunas funciones. 2.5.1.2. Funciones de GLUT Las funciones de GLUT se pueden dividir o clasificar según su funcionalidad: ?? Inicialización 12
  • 13. Antes de empezar a trabajar hay que inicializar el estado de la máquina de estados de GLUT. Todas las funciones de inicialización comienzan por glutInit Dentro de este grupo de funciones tendríamos las siguientes: glutInit (int **argcp, char **argv ) Modifica las variables de estado de Glut y negocia una sesión con el sistema de ventanas. Los parámetros que se le pasan son las variables argc y argv de la función main de C respectivamente. glutInitWindowPosition(int x, int **y) Indica mediante x e y la posición en la pantalla en píxeles de la ventana. glutInitWindowsSize(int width, int **height) Indica mediante width, height el ancho y alto respectivamente en pixeles de la ventana glutInitDisplayMode(unsigned int mode) Indica mediante mode el modo de display, este valor puede ser entre otros GLUT_RGBA, GLUT_RGB, GLUT_INDEX, GLUT_SINGLE, GLUT DOUBLE GLUT_LUMINANCE….. El siguiente trozo de código nos muestra como inicializar la máquina de estados, glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE| GLUT_RGBA); glutInitWindowPosition(0,0); glutInitWindowSize(500,500); Listado 2.1: Inicialización con Glut el sistema de ventanas 13
  • 14. En este ejemplo se utiliza doble buffer. El doble buffer se utiliza para animaciones, porque así se puede eliminar el parpadeo cuando cambia la imagen en la secuencia de animación. ?? Gestión de ventanas Para abrir una ventana, o enviar la orden de abrir una ventana para la aplicación al sistema de ventanas subyacente se hace con, int glutCreateWindow(char **name) donde name es el nombre de la ventana, nos devolverá el identificador de la ventana Además de ésta función existen otras funciones para el manejo de ventanas, a lgunas de ellas son las siguientes: glutSetWindow(int winId) Establece la ventana con el identificador winId como ventana actual glutGetWindow(void) Solicita el identificador de la ventana actual glutDestroyWindow(int winId) Cierra la ventana especificada por winId glutPostRedisplay(void) Solicita que la ventana sea redibujada glutPositionWindow(int x, int y) Solicita un cambio de posición de la ventana a la posición indicada por x e y glutReshapeWindow(int width, int height) Solicita un cambio en el tamaño de la ventana, el nuevo tamaño vendrá dado por width y height glutFullScreen() 14
  • 15. Solicita que la ventana actual sea cambia a tamaño completo glutShowWindows(void) Solicita que la ventana sea mostrada glutHideWindows(void) Solicita que la ventana se oculte glutIconifyWindow(void) Solicita que la ventana se minimice glutSetWindowTitle(char *name) Pone la barra de título en la ventana. glutSetIconTitle(char *name) Pone el título en la ventana. Minimizada. 15
  • 16. El listado 2.1 nos muestra como crear una ventana y como crear un dibujo en ella. #include <GL/glut.h> void pintar(void) { glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glPointSize(50); glBegin(GL_POINTS); glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(-0.25,-0.25); glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(0.25,0.25); glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(-0.25,0.25); glColor3f(0.5f, 0.5f, 0.5f); glVertex2f(0.25,-0.25); glEnd(); glFlush(); }; int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); glutInitWindowPosition(0,0); glutInitWindowSize(500,500); glutCreateWindow("Mi primera ventana"); glutDisplayFunc(pintar); glutMainLoop(); return 0; } Listado 2.2: Creación y dibujado de ventanas 16
  • 17. La ejecución de éste pequeño programa nos mostrará una ventana como la siguiente, Figura 2.9: Ventana creada con Glut. ?? Usar subventanas A la hora de crear subventanas tenemos que tener en cuenta los siguientes aspectos: - Cuando se crea una ventana, hay que guardar el identificador de la ventana; el identificador es un entero devuelto por la función glutCreateWindow - Solo puede haber una función callback idle() en una aplicación, y esta función es global para todas las ventanas de la aplicación, por lo tanto, a la hora de implementar esta función tendrá que estar implementado el refresco para todas las ventanas. - Para crear una subventana, hay que proporcionar el identificador de la ventana superior y las coordenadas para la subventana y el ancho y el alto para la subventana. 17
  • 18. - Cuando Glut abre una subventana, le proporciona un contexto completo, con lo que hay una perdida de rendimiento porque el driver de la tarjeta de video tiene que refrescar la memoria para cada una de las ventanas. Para la creación de una subventana se utiliza la siguiente función, int glutCreateSubWindow(int winId, int x, int y, int width, int height) ?? Procesado de Eventos GLUT esta dirigido por eventos, es decir, hay un bucle continuo que comienza después de la inicialización y va procesando todos los eventos. Los eventos pueden ser por ejemplo un botón del ratón que se pulsa, una ventana que se abre, se redimensiona, se cierra, una tecla del teclado que se ha pulsado... Los eventos se registran como rutinas de registro callback. Después de registrar todos los eventos en el programa hay que llamar a la función de procesado de eventos que es glutMainLoop() Funciones de registro de callback: glutDisplayFunc(void * void) Registra la función de display para la ventana actual, como parámetro se le pasa la función que se ejecutará cuando se produzca el evento de visualizar la ventana. glutReshapeFunc(void *void( int width, int height)) Registra la función de cambio de tamaño para la ventana actual, como parámetro se le pasa la función que llamara cuando se cambie de tamaño y el nuevo tamaño. glutIdleFunc(void * void) Registra la función idle, esta función es llamada cuando no hay entradas de usuario, como parámetro se le pasa la función que se ejecutará. 18
  • 19. glutKeyboardFunc(void *void, unsigned charkey, int x, int y) Registra la función de pulsado de teclado para la ventana actual. Otra rutina útil en animaciones es: glutSwapBuffers() Intercambia los buffers, mostrando en la ventana de golpe todo lo que se ha dibujado. ?? Uso de teclado En el momento de pulsar una tecla en el teclado, el driver de proceso de eventos de GLUT registra un evento de teclado. Estos eventos son manejados por las funciones callback de teclado. La función asociada de callback toma como argumentos el código ASCII asociado con la tecla y la posición x,y del cursor. La generación de callbacks de teclado se puede deshabilitar con la función glutKeyBoardFunc() y pasándole el valor NULL. ?? Trazar texto en una ventana OpenGL La librería OpenGL no tiene funciones para manejar el trazado de texto, solo tiene unas directivas muy primitivas para el trazado de bitmaps, por lo que cada uno tiene que hacerse su propia librería de bitmaps para cada carácter. GLUT proporciona unas funciones que permiten dibujar un carácter en una posición especificada: GlutBitmapCharacter GlRasterPos Con el siguiente programa se puede ver gran parte de estas funciones como son crear una subventana, trazar texto, dibujar en una ventana, tratar el evento de pulsación de teclado o cambiar el tamaño de la ventana. 19
  • 20. #include <string.h> #include <stdio.h> #include <GL/glut.h> #include <GL/gl.h> int IdMain; int IdSub; static double tiempo = 0.0; static double angulo = 0.0; static char label[100]; void pintarcadena (char *s) { unsigned int i; for (i = 0; i < strlen (s); i++) glutBitmapCharacter (GLUT_BITMAP_TIMES_ROMAN_24, s[i]); }; void pintarventana(void) { glutSetWindow (IdMain); glClearColor(1.0F, 1.0F, 1.0F,1.0F); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity (); glPushMatrix (); glRotatef (angulo, 0.0, 0.0, 1.0); glBegin (GL_POLYGON); glColor3f (1.0F, 0.0F, 0.0F); glVertex2f(0.0F, 0.5F); glColor3f (0.0F, 1.0F, 0.0F); glVertex2f(0.5F,0.5F); glColor3f (0.0F, 0.0F, 1.0F); glVertex2f(0.5F,0.0F); glColor3f (1.0F, 0.0F, 0.0F); glVertex2f(0.0F,0.0F); glEnd (); glPopMatrix (); glutSwapBuffers (); }; void pintarsubventana () { glutSetWindow (IdSub); glClearColor (1.0, 1.0, 1.0, 0.0); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f (0.0F, 0.0F, 0.0F); glBegin (GL_LINE_LOOP); glVertex2f (0.0F, 0.0F); glVertex2f (0.0F, 0.99F); glVertex2f (0.999F, 0.99F); glVertex2f (0.999F, 0.0F); glEnd (); 20
  • 21. glColor3f (1.0F, 0.0F, 1.0F); sprintf (label, " Subventana "); glRasterPos2f (0.40F, 0.70F); pintarcadena (label); sprintf (label, " de OpenGL creada con GLUT "); glRasterPos2f (0.33F, 0.35F); pintarcadena ( label); glutSwapBuffers (); }; void tamanoventana (int w, int h) { glViewport (0, 0, w, h); glMatrixMode (GL_PROJECTION); glLoadIdentity (); gluOrtho2D (-1.0F, 1.0F, -1.0F, 1.0F); glMatrixMode (GL_MODELVIEW); glLoadIdentity (); glutSetWindow (IdSub); glutReshapeWindow (w - 10, h / 10); glutPositionWindow (5, 5); glutSetWindow (IdMain); }; void tamanosubventana (int w, int h) { glViewport (0, 0, w, h); glMatrixMode (GL_PROJECTION); glLoadIdentity (); gluOrtho2D (0.0F, 1.0F, 0.0F, 1.0F); }; void teclado (unsigned char key, int x, int y) { static int info_banner = 1; switch (key) { case 'i': case 'I': if (info_banner) { glutSetWindow (IdSub); glutHideWindow (); } else { glutSetWindow (IdSub); glutShowWindow (); }; info_banner = !info_banner; break; case 'q': case 'Q': exit (0); break; }; 21
  • 22. }; void idle (void) { angulo += 5.0; tiempo += 0.1; glutSetWindow (IdMain); glutPostRedisplay (); glutSetWindow (IdSub); glutPostRedisplay (); }; int main (int argc, char **argv) { glutInit (&argc, argv); glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); glutInitWindowPosition (20, 20); glutInitWindowSize (600, 600); IdMain = glutCreateWindow ("Ventana con subventanas"); glutDisplayFunc (pintarventana); glutReshapeFunc (tamanoventana); glutKeyboardFunc (teclado); glutIdleFunc (idle); IdSub = glutCreateSubWindow (IdMain, 20, 20, 600 - 10, 600 / 10); glutDisplayFunc (pintarsubventana); glutReshapeFunc (tamanosubventana); glutMainLoop (); return 0; }; Listado 2.3: Crear ventanas y subventanas con Glut El ejemplo anterior nos daría la siguiente salida, Figura 2.10: Ventana que contiene una subventana creada con Glut. 22
  • 23. ?? Menús Una forma más de comunicación entre el usuario y una aplicación es el uso de menús, por lo tanto, es una cuestión importante a tener en cuenta cuando se realizan aplicaciones. GLUT también dispone una serie de funciones para la creación de menús. Algunas de ellas serían: int glutCreateMenu(void (f*) (int)) mainMenu(int) subMenu(int) glutAddMenuEntry(char *s, int nr) glutAddSubMenu(char *s, int nr) glutAttachMenu() (www.linuxfocus.org, 1998), (Kilgard, M., 1996) 2.5.2 Librería AUX 2.5.2.1. Características - Esta librería no forma parte de la especificación de OpenGL, pero aparece en todas las plataformas a las que se porta opengl. - Fue creada principalmente para facilitar el aprendizaje de OpenGL, olvidándose de los detalles de la plataforma y sistema operativo. - Se utiliza para probar cosas programadas en OpenGL, pero no para escribir aplicaciones serias, por lo tanto no se debe utilizar demasiado. - Las funciones de la librería son rudimentarias y permiten gestionar la creación y manipulación de ventanas, las entradas de usuario, dibujar figuras 3D completas.... - AUX, también tiene funciones para operaciones especificas del sistema, como pueden ser intercambio de buffers y apertura de imágenes, entre otras. - Internamente la librería AUX hace uso de la API nativa del entorno para estas funciones. - Las funciones de la librería son iguales en todas las plataformas. (Sweet, M.) 23
  • 24. Al igual que la librería GLUT tiene funciones para la inicialización, el manejo de ventanas, el procesado de eventos, aunque la librería AUX es menos completa que GLUT. 2.5.2.2. Funciones ?? Inicialización Las funciones utilizadas para la inicialización son: auxInitDisplayMode(Glbitfield mascara) Inicializa el modo de visualización en la ventana. Es la primera función a la que hay que llamar. El parámetro indicará las características de la ventana. auxInitPosition(GLint x, GLint y, Glsizei ancho, Glsizei alto) Especifica la posición en la pantalla y el tamaño de la ventana. ?? Gestión de ventanas Para crear e inicializar la ventana de dibujo se utiliza la función auxInitWindow auxInitWindow(Glbyte *cadenatitulo) Inicializa y muestra la ventana de generación de OpenGL. El parámetro será el título que aparecerá en la barra de la ventana. El siguiente ejemplo muestra como inicializar el sistema y la creación de una ventana. #include <glglaux.h> #include <glgl.h> void CALLBACK nada() { }; void main(void) { auxInitDisplayMode(AUX_SINGLE|AUX_RGBA); auxInitPosition(0,0,350,350); auxInitWindow("Mi ventana creada con la librería AUX"); glClearColor(1.0F, 1.0F, 1.0F, 1.0F); glClear(GL_COLOR_BUFFER_BIT); glFlush(); auxMainLoop(nada); } Listado 2.4: Crear ventanas con la librería Aux 24
  • 25. ?? Rellamada Estás funciones, son muy similares a las que tiene GLUT para el procesado de eventos, es decir, son funciones que se propia librería llamará cuando se necesite, por ejemplo, cuando se cambie de tamaño una ventana, cuando se pulse una tecla o un botón del ratón, cuando se necesite redibujar la ventana.... Para declarar e implementar funciones que son llamadas por estas funciones de rellamada se debe poner delante la sentencia CALLBACK. Las principales son las siguientes: auxMainLoop(AUXMAINPROC func) Permite especificar la función que debe usarse para actualizar la ventana OpenGL. El parámetro será la función que se llamará cuando hay que refrescar la ventana. auxReshapeFunc(AUXRESHAPEPROC func) Permite especificar la función que debe llamarse cuando se cambie de tamaño la ventana. auxIdleFuncion(AUXIDLEPROC func) Permite especificar la función de rellamada que debe llamarse cuando no hay otra actividad pendiente. auxKeyFunc(GLint tecla, void (*funcion(void)) Permite especificar la función de rellamada cuando se pulse la tecla tecla que se le pasa como parámetro. auxMouseFunc(int boton, int modo, AUXMOUSEPROC func) Permite especificar la función de rellamada con la actividad de los botones del ratón. ?? Otras funciones Hay otras funciones útiles que se pueden utilizar como son, auxSwapBuffers(void) Ocasiona el intercambio del buffer empleado para dibujar con el de pantalla. auxWireTeapot(Gldouble tamaño) Dibuja una tetera alámbrica. El parámetro especificar el tamaño de la tetera. 25
  • 26. auxSolidTeapot(Gldouble tamaño) Dibuja una tetera sólida. El parámetro especificar el tamaño de la tetera. El siguiente código nos muestra como crear y dibujar en una ventana. #include <windows.h> #include <glgl.h> #include <glglaux.h> void CALLBACK tamanoventana(GLsizei w, GLsizei h) { if(h == 0) h = 1; glViewport(0, 0, w, h); glLoadIdentity(); if (w <= h) glOrtho (-100.0f, 100.0f, -100.0f, 100.0f*h/w, -100.0, 100.0); else glOrtho (-100.0f, 100*w/h, -100.0f, 100.0f, -100.0, 100.00); } void CALLBACK pintarventana(void) { glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glRotatef(1.0f,0.0f,0.0f,1.0f); glBegin (GL_POLYGON); glColor3f (1.0F, 0.0F, 0.0F); glVertex2f(30.0F, 75.0F); glColor3f (0.0F, 1.0F, 0.0F); glVertex2f(75.0F,75.0F); glColor3f (0.0F, 0.0F, 1.0F); glVertex2f(75.0F,30.0F); glColor3f (1.0F, 0.0F, 0.0F); glVertex2f(30.0F,30.0F); glEnd (); glFlush(); auxSwapBuffers(); } void CALLBACK idle (void) { pintarventana(); }; void CALLBACK teclado (void) { exit (0); }; 26
  • 27. void main(void) { auxInitDisplayMode(AUX_DOUBLE|AUX_RGBA); auxInitPosition(50,50,300,300); auxInitWindow("Ventana creada con la librería AUX"); auxReshapeFunc(tamanoventana); auxKeyFunc(81, teclado); auxKeyFunc(113, teclado); auxIdleFunc(idle); auxMainLoop(pintarventana); } Listado 2.5: Crear y dibujar una ventana con la librería Aux Como se puede observar en la siguiente figura la ejecución del programa produce casi la misma salida que el ejemplo creado con la librería Glut. Figura 2.11: Ventana creada con la librería Aux, que contiene un dibujo geométrico. (Neider, J.) (Sweet, M.) 2.6. Programación con OpenGL para Windows. WIGGLE Como ya se ha dicho anteriormente, OpenGL no tiene funciones para la interacción con el usuario, la gestión de la pantalla, la asociación de comandos de dibujo de OpenGL a una ventana, selección del modo de buffer, etc. Para todas estas tareas se pueden utilizar algunas librerias que son independientes de la plataforma como las explicadas en el apartado anterior, o bien, utilizar las 27
  • 28. propias funciones que nos da el sistema, es decir, el lenguaje de programación anfitrión es el que tiene que asumir, y por lo tanto tener funciones para todas esas tareas. Microsoft Windows ofrece seis funciones que son añadidas a OpenGL para realizar estas tareas, estas funciones son las llamadas funciones wiggle; además de estas seis hay otras cinco añadidas al GDI de Windows. Por lo tanto es importante ver como se trabaja en un entorno Windows. Para la creación y gestión de las ventanas Windows el programador deberá realizar algunas tareas, como son, describir la ventana WinMain, el registro de las clases de windows, crear la ventana y gestionar o controlar la ventana con WndProc. Para esto se utilizaran dos funciones WinMain y WndProc. 2.6.1. Función WinMain El prototipo de ésta función es: int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) Esta función es igual que la función main, pero en un entorno Windows. Los parámetros que se le pasan serán: hInstance, para es el handle del programa en uso. hPrevInstance, indica el número de veces que se activa el mismo programa lpszCmdLine, es una cadena para indicar todos los parámetros de la línea de comandos que se pasan al programa. nCmdShow, permite especificar como se mostrara la ventana inicial (normal, maximizada, minimizada). Las características de una ventana Windows se indican mediante la estructura WNDCLASS, y será dentro de la función winMain donde se le darán valores a todos los atributos de la estructura WNDCLASS. Typedef struct_WNDCLASSW{ UINT style; WNDPROC lpfnWndProc; 28
  • 29. int cbClsExtra; int cbWndExtra; HISTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCWSTR lpszMenuName; LPCWSTR lpszClassName; } WNDCLASS Los campos o atributos de esta estructura son: style: permite especificar las características de redibujado de la ventana. ipfnWndProc: puntero a una función que está relacionada con la clase ventana. CbClsExtra , cbWndExtra: estos dos valores definen la clase y las extensiones de la ventana. hInstance: permite asociar la clase ventana al programa asociada. hIcon: permite especificar el icono asociado a la aplicación hCursor: permite especificar el cursor asociado a la aplicación hbrBackground: para determinar el pincel de colores que se utilizara para el fondo de la ventana de aplicación. lpszMenuName: para indicar la clase de menú que se va a utilizar con la ventana. LpszClassName: para asignar nombre a la ventana. Después de dados los valores a la estructura tenemos que registrar la ventana con la función: RegisterClass(&wc) donde wc es de tipo WNDCLASS Posteriormente se crea la ventana con la función CreateWindow: hWnd CreateWindow( LPCTSTR lpszClassName, LPCTSTR lpzWindowName, DWORD dwStyle, int nX, int nY, int nWidth, int nHeight, HWND hwndParent, HMENU hmenu, HANDLE hinst, LPVOID lpvParam ); 29
  • 30. Los parámetros que se le pasan a ésta función serían los siguientes: lpszClassName: es el nombre que se utilizó en la clase anterior para registrar la clase de ventana. lpzWindowName: es el título de la ventana dwStyle: permite especificar detalles de la ventana. (Si se puede minimizar, maximizar, si tiene scroll..) nX , nY: permite especificar la posición inicial de la ventana. nWidth , nHeight: permite especificar el tamaño de la ventana. hwndParent: para indicar el handler de la ventana padre. menú: para indicar el handler del menú inst: para indicar el handler de la aplicación en uso. LpvParam: siempre a NULL 2.6.2. Función WndProc El prototipo de la función es: LONG WINAPI WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); Con esta función, se pueden controlar y gestionar los eventos que se produzcan en el programa, es donde se especifica como debe actuar el programa según el tipo de evento que se produzca. Hay muchos eventos o mensajes que se pueden controlar, como pueden ser: WM_PAINT (para dibujar la ventana), WM_DESTROY (cuando se cierra la ventana), WM_CREATE (cuando se crea la ventana), WM_SIZE (Cuando se cambia de tamaño), etc. El siguiente código mostrará el esqueleto para crear una ventana para una aplicación: 30
  • 31. #include <windows.h> #include <glgl.h> #define WIDTH #define HEIGHT 600 500 HDC ghDC; HGLRC ghRC; HINSTANCE hInst; LONG WINAPI WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { LONG lRet = 1; RECT rect; PAINTSTRUCT ps; HDC hdc; static HINSTANCE hInstance; switch (msg){ case WM_PAINT: BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); break; case WM_DESTROY: if (ghRC) wglDeleteContext(ghRC); if (ghDC) ReleaseDC(hWnd, ghDC); PostQuitMessage (0); break; default: lRet=DefWindowProc(hWnd,msg,wParam,lParam); break; } return lRet; } int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { static char szAppName[] = "W1"; static char szTitle[]="Ventana creada con GDI de Windows"; WNDCLASS wc; MSG msg; HWND hWnd; wc.style = 0; wc.lpfnWndProc = (WNDPROC)WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon (hInstance,IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszMenuName = NULL; wc.lpszClassName = szAppName; if (!RegisterClass(&wc )) return (FALSE); 31
  • 32. hWnd = CreateWindow( szAppName, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WIDTH, HEIGHT, NULL, NULL, hInstance, NULL ); if (!hWnd) return(FALSE); ShowWindow( hWnd, nCmdShow ); UpdateWindow( hWnd ); while (GetMessage(&msg,NULL,0,0)) { TranslateMessage( &msg ); DispatchMessage( &msg ); } return( msg.wParam ); } Listado 2.5: Esqueleto de un programa para con el sistema de ventanas propio de Windows 2.6.3. Dibujar en una ventana de Windows Hasta ahora se ha visto como crear una ventana Windows, pero ahora debemos aprender a dibujar en ella. Para dibujar en una ventana se puede hacer sin usar OpenGL y por lo tanto se utilizarían las funciones del GDI (Interfaz Gráfica de Dispositivos) de Windows, en cuyo caso, habría que tener en cuenta el concepto de Contexto de Dispositivo, o bien, utilizar OpenGL y entonces hay que tener en cuenta el concepto de Contexto de Generación. 32
  • 33. Contexto de Dispositivo Cada ventana, tiene un contexto de dispositivo que recibe la salida de gráficos, y cada función GDI toma un contexto de dispositivo como argumento para indicar a que ventana queremos que afecte la función. Podemos tener múltiples contextos de dispositivo, pero sólo uno para cada ventana. Contexto de Generación El concepto de contexto de generación no es de OpenGL sino de la API de Windows para soportar OpenGL. Antes de ejecutar ningún comando de OpenGL hay que indicar la ventana de generación, es decir, en que ventana se va dibujar. Puede haber varios contextos de generación, pero solo uno puede ser el actual. Al activar un contexto de generación, se asocia con una ventana particular. Para poder trabajar con el contexto de generación tenemos las funciones WIGGLE, que no son funciones propias de la especificación de OpenGL, sino que se añadieron para soportar todo este tipo de cosas propias de Windows. Algunas de las funciones relacionadas con el contexto de generación que más se utilizan son: HGLRC wglCreateContext(HDC hDC) Crea un contexto de generación adecuado para dibujar en el contexto de dispositivo especificado en el parámetro hDC BOOL wglDeleteContext(HGLRC hrc) Borra un contexto de generación. El contexto de generación se debe borrar después que la aplicación no lo necesita BOOL wglMakeCurrent(HDC hDC, HGLRC hrc) Activa el contexto de generación que se le pasa como parámetro hrc y lo asocia con el contexto de dispositivo especificado también como parámetro hDC Para la creación de un contexto de generación debemos crear primero un contexto de dispositivo con la función GetDc(HWND hwnd), esta función devuelve el contexto de dispositivo para la ventana que se e pasa como parámetro, y posteriormente crear el contexto de generación l con la función HGLRC wglCreateContext(HDC hDC) anteriormente expuesta, pasándole como 33
  • 34. parámetro el contexto de dispositivo creado y por último asignar el contexto de dispositivo con el contexto de generación mediante la función BOOL wglMakeCurrent(HDC hDC, HGLRC hrc). Estas operaciones normalmente se harán con el evento o mensaje WM_CREATE, que es el momento de creación de la ventana. El contexto de generación debe borrarse y normalmente se borrará cuando se cierre la ventana, es decir, cuando se produzca el mensaje WM_DESTROY. Para borrarlo se hará con la función anterior BOOL wglDeleteContext(HGLRC hrc) Para poder dibujar con OpenGL en una ventana hay que tener en cuenta otros dos aspectos, uno de ellos es el estilo de la ventana y el otro es el formato de Píxel. Para que OpenGL pueda dibujar en una ventana, la ventana no podrá tener el estilo CS_PARENTDC y deberá crearse con los estilos WS_CHIPCHILDREN y WS_CLIPSIBLINGS. El formato de Píxel también hay que especificarlo a la hora de dibujar en una ventana con OpenGL. El formato de píxel no viene con la especificación de OpenGL, si no que es una extensión a la API Win32 para soportar la funcionalidad de OpenGL. El formato de píxel debe seleccionarse para un contexto de dispositivo antes de que este se use en un contexto de generación. En el formato de píxel se seleccionan características tales como si la ventana tiene doble buffer, color, profundidad, etc. Para seleccionar el formato de píxel utilizaremos la estructura PIXELFORMATDESCRIPTOR, en el que le daremos valor a los campos de esta estructura dependiendo del tipo de ventana que se quiera, y las funciones: int ChoosePixelFormat(HDC hDC, PIXELFORMATDESCRIPTOR *ppfd) Esta función se usa para determinar el mejor formato de píxel disponible para el contexto de dispositivo hDC basado en las características deseadas descritas en la estructura ppfd. BOOL SetPixelFormat(HDC hDC, int iPixelFormat, PIXELFORMATDESCRIPTOR *ppfd) Selecciona el formato de píxel para un contexto de dispositivo. 34
  • 35. Ahora que ya se ha visto como crear ventanas y como dibujar en ellas, veamos un ejemplo: void tamanoventana(GLsizei w, GLsizei h) { if(h == 0) h = 1; glViewport(0, 0, w, h); glLoadIdentity(); if (w <= h) glOrtho (-100.0f, 100.0f, -100.0f, 100.0f*h/w, -100.0, 100.0); else glOrtho (-100.0f, 100*w/h, -100.0f, 100.0f, -100.0, 100.00); } void pintarventana(void) { glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glRotatef(1.0f,0.0f,0.0f,1.0f); glBegin (GL_POLYGON); glColor3f (1.0F, 0.0F, 0.0F); glVertex2f(30.0F, 75.0F); glColor3f (0.0F, 1.0F, 0.0F); glVertex2f(75.0F,75.0F); glColor3f (0.0F, 0.0F, 1.0F); glVertex2f(75.0F,30.0F); glColor3f (1.0F, 0.0F, 0.0F); glVertex2f(30.0F,30.0F); glEnd (); glFlush(); } void IdleFunction(void) { pintarventana(); } void SetDCPixelFormat(HDC hDC) { int nPixelFormat; static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 8, 0,0,0,0,0,0, 0,0, 0,0,0,0,0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0,0,0 }; 35
  • 36. int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; WNDCLASS wc; HWND hWnd; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC) WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = lpszAppName; if(RegisterClass(&wc) == 0) return FALSE; hWnd = CreateWindow( lpszAppName, lpszAppName, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, 300, 300, NULL, NULL, hInstance, NULL); if(hWnd == NULL) return FALSE; ShowWindow(hWnd,SW_SHOW); UpdateWindow(hWnd); while( GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static HGLRC hRC; static HDC hDC; switch (message) { case WM_CREATE: hDC = GetDC(hWnd); SetDCPixelFormat(hDC); hRC = wglCreateContext(hDC); wglMakeCurrent(hDC, hRC); SetTimer(hWnd,101,1,NULL); break; 36
  • 37. case WM_DESTROY: KillTimer(hWnd,101); wglMakeCurrent(hDC,NULL); wglDeleteContext(hRC); if(hPalette != NULL) DeleteObject(hPalette); PostQuitMessage(0); break; case WM_SIZE: tamanoventana(LOWORD(lParam), HIWORD(lParam)); break; case WM_TIMER: { IdleFunction(); InvalidateRect(hWnd,NULL,FALSE); } break; case WM_PAINT: { pintarventana(); SwapBuffers(hDC); ValidateRect(hWnd,NULL); } break; default: return (DefWindowProc(hWnd, message, wParam, lParam)); } return (0L); } Listado 2.6: Dibujar ventanas con el sistema de ventanas propio de Windows Lo que nos muestra este pequeño programa es el mismo objeto o dibujo que nos mostraba en los ejemplos anteriores con la librería Glut y Aux, pero la forma de crear, dibujar en la ventana y el procesado de eventos o mensajes es diferente como se puede apreciar en el código. (Huescar, J.M., 1999) 37
  • 38. 2.7. Usar OPENGL Hasta este momento se ha visto para que sirve OpenGL, que aplicaciones la utilizan, que se puede hacer con esta librería y como trabajar y preparar las ventanas dependiendo del sistema y plataforma para visualizar escenas hechas con OpenGL. Ahora y de una forma rápida, ya que posteriormente se hará más hincapié en cada uno de las cuestiones, se expondrá como usar OpenGL. 2.7.1. Dibujar en 3D Antes de enumerar las diferentes primitivas para la creación de objetos hay que tener en cuenta como se comporta OpenGL a la hora de dibujar. Dibujar con OpenGL es distinto a trabajar con otras librerías o funciones; con OpenGL lo que se hace es definir un volumen de visualización y para dibujar objetos las c oordenadas no se indican en pixeles, ni en coordenadas físicas si no con lo que se denomina coordenadas posiciónales en el volumen de visualización. Por lo que para poder trabajar con OpenGL después de crear la ventana de la aplicación, debemos definir la ventana de visualización o volumen de visualización donde dibujaremos los objetos geométricos, tomando como referencia coordenadas posiciónales. 2.7.1.1. Dibujar Objetos Después de definir el área de visualización, se pueden comenzar a dibujar objetos. Para dibujar objetos las funciones que se utilizan son las siguientes: glVertexXX() Se usa para especificar las coordenadas de un vértice. Se pueden definir vértices en dos y tres dimensiones, dependiendo del número de coordenadas que se pasen como parámetros a la función. OpenGL trabaja normalmente en coordenadas homogéneas representadas por cuatro componentes, (x, y, z, h), por lo tanto cuando estamos definiendo puntos en dos dimensiones el valor z coge el valor 0 y h el valor 1, en tres dimensiones h coge el valor 1. 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), 38
  • 39. 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, para ello deberemos utilizar el sufijo v indicando que es un vector de coordenadas. glBegin(GLenum modo) glEnd() Estas funciones se utilizan juntas, y permiten delimitar los vértices de la primitiva pasada como parámetro. El valor de modo indicará la primitiva a dibujar y podrá tomar distinto valores como puede ser GL_POINTS, GL_LINES, GL_POLYGON... El formato para utilizar estas funciones será el siguiente: glBegin(modo); glVertex(x,y,z); glVertex(x,y,z); ... glEnd(); donde modo es el identificador del tipo a dibujar en la pantalla y glVertex es la descripción de un punto de la pantalla. ?? Dibujar Puntos La primitiva para dibujar puntos es GL_POINTS. Este es el parámetro que llevará la función glBegin() y posteriormente se indicarán los puntos mediante la función glVertex(). El tamaño de los puntos a dibujar se puede cambiar utilizando la función, glPointSize(GLfloat tamano) ?? Dibujar Líneas Para poder dibujar una línea hay que definir dos puntos en el área de visualización. Por lo que, entre los comandos glBegin y glEnd hay que especificar al menos dos vértices con glVertex. 39
  • 40. A la hora de dibujar líneas tenemos varias opciones dependiendo de la primitiva indicada en la función glBegin Las primitivas disponibles para dibujar líneas son las siguientes: GL_LINES Genera una serie de líneas que no se conectan entre sí. Las líneas se definen 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 GL_LINE_STRIP Genera una serie de líneas pero que se conectan entre sí, es decir el punto final 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. GL_LINE_LOOP Genera una serie de líneas conectadas entre sí, es parecido al modo anterior pero este modo conecta automáticamente el punto inicial con el punto final. También se le podría cambiar el tipo de línea o patrón, para que sea punteada, a rayas, con puntos y rayas, etc.. Para glEnable(GL_LINE_STIPPLE) ello, y habría que posteriormente habilitar especificar el patronaje el con la función patrón con la función glLineStipple(patron). ?? Dibujar Polígonos El dibujado de polígonos es la base de composición de objetos de OpenGL. Con lo visto hasta ahora se pueden dibujar, puntos, líneas e incluso formas cerradas, pero no superficies sólidas. Para ello hay un conjunto de primitivas especificas. Las primitivas para polígonos serían las siguientes: GL_POLYGON Genera un simple polígono relleno con los vértices especificados 40
  • 41. GL_TRIANGLES Genera una serie de triángulos rellenos que no se conectan entre sí. El 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. GL_TRIANGLE_STRIP Genera una serie de triángulos rellenos conectados entre sí, y dos de los vértices de un triángulo son los vértices del siguiente triángulo. Debemos saber que con N vértices se pueden crear N-2 triángulos. De igual forma que anteriormente el número de vértices debe ser múltiplo de tres, si no lo es se ignora aquellos que sobran. GL_TRIANGLE_FAN 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 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. GL_QUADS 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 esto entonces OpenGL ignora los vértices que sobran. Cada cuatro vértices se describe un cuadrilátero. GL_QUAD_STRIP 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 si tenemos un total de N vértices podremos obtener 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. A la hora de dibujar polígonos debemos tener en cuenta dos reglas: - Todos los polígonos deben ser planares. - Los polígonos deben ser convexos. 41
  • 42. El siguiente código es un ejemplo muy sencillo que muestra como utilizar estas primitivas para crear dibujos u objetos. void RenderScene(void) { GLfloat y; GLint factor = 1; GLushort pattern = 0x5555; GLfloat x,z, angle; glClear(GL_COLOR_BUFFER_BIT); glPushMatrix(); glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); glBegin(GL_POLYGON); glVertex2f(-80.0, -80.0); glVertex2f(-55.0, -80.0); glVertex2f(-55.0, -55.0); glVertex2f(-80.0, -55.0); glEnd(); glEnable(GL_LINE_STIPPLE); for(y = 20.0f; y < 60.0f; y += 5.0f) { glLineStipple(factor,pattern); glBegin(GL_LINES); glVertex2f(40.0f, y); glVertex2f(80.0f, y); glEnd(); factor++; } glBegin(GL_POINTS); z = 10.0f; for(angle = 0.0f; angle <= (2.0f*GL_PI)*3.0f; angle += 0.1f) { x = 15.0f*sin(angle); y = 15.0f*cos(angle); glVertex3f(-x, -y, z); z += 0.5f; } glEnd(); glPopMatrix(); glFlush(); } Listado 2.7: Uso de primitivas para crear objetos geométricos 42
  • 43. El código anterior producirá la siguiente salida, Figura 2.12: Puntos, lineas y polígonos 2.7.2. Transformación de Coordenadas Los dibujos o gráficos están compuestos de las formas explicadas anteriormente, pero, para que todas estas formas se conviertan en una escena coherente hay que colocarlas con relación a otras formas y al observador, por esta razón habrá que saber m over, rotar o cambiar de tamaño los objetos, o mejor dicho, el sistema de coordenadas. Cuando se mueve el sistema de coordenadas el efecto que produce es que se mueve el objeto, es decir, se vuelve a redibujar con el nuevo sistema de coordenadas. Esto es lo que se denomina transformación. Hay varios tipos de transformación: - Transformación del observador: especifica la localización del observador o de la cámara. Ésta transformación debe ser la primera en especificarse ya que será la que cambie el sistema de coordenadas oculares. 43
  • 44. - Transformación del modelado: permite manipular tanto el modelo como los objetos que contiene. Es decir, permitirá trasladar, rotar o escalar un objeto. - Transformación del modelador: describe la dualidad de las transformaciones de m odelado y vista. Entre las dos transformaciones anteriores en realidad no hay ninguna diferencia ya que da igual que se mueva el objeto hacia arriba o que se desplace el eje de coordenadas hacia abajo. Las funciones que nos permitirán este tipo de transformación serán: glTranslate(GLdouble x, GLdouble y, GLdouble z) glRotatef(Gldouble angulo, GLdouble x, GLdouble y, GLdouble z) glScale(GLdouble x, GLdouble y, GLdouble z) que permitirán respectivamente trasladar, rotar y escalar objetos. - Transformaciones de la vista: esta transformación se refiere al mapeado de la escena a coordenadas físicas de la ventana. La función que nos permite definir este tipo de transformación es: gluLookAt(GLdouble ojos, GLdouble ojoy, GLdouble ojoz, GLdouble centrox, GLdouble centroy, GLdouble centroz, GLdouble arribax, GLdouble arribay, GLdouble arribaz) - Transformación de la proyección: define y dimensiona el volumen de visualización. Hay dos tipos: - Ortogonal. Con este tipo de perspectiva los objetos se dibujan con las dimensiones especificadas. - Perspectiva. Con este tipo de perspectiva la imagen parece más real, ya que se tienen en cuenta las distancias de los objetos. Las funciones que permiten definir estas perspectivas son, void glOrtho(GLdouble izquierda, GLdouble derecha, GLdouble abajo, GL arriba, GLdouble cerca, GLdouble lejos) 44
  • 45. Esta función se utiliza para especificar una proyección ortográfica. Este tipo de proyección define un volumen de vista rectangular, es decir, define un paralelepípedo de tamaño infinito, por lo que se debe definir una serie de planos de corte para detallar con exactitud el volumen de visualización. Los 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. void glFrustum(GLdouble izquierda, GLdouble derecha, GLdouble abajo, GLdouble arriba, GLdouble cerca, GLdouble lejos) Esta función se utiliza para definir una proyección perspectiva, y por tanto define como volumen de visualizacion una pirámide; el objeto a visualizar tiene un aspecto mucho más realista. Igual que en la proyección ortogonal 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. gluPerpespective (GLdouble angulo, GLdouble aspecto, GLdouble zCerca, GLdouble zlejos) Esta función es muy parecida a la función glFrustum, la diferencia entre ambas está en la forma de definir la ventana de visualización. La función glFrustum define los dos vértices necesarios de la ventana y en la sentencia glPerpestive solamente se definirá el ángulo de apertura de la cámara y la relación entre el largo y ancho del plano cercano de corte. 45
  • 46. Cada una de las transformaciones explicadas puede describirse como la multiplicación de dos o más matrices. Todos los cambios de perspectiva que se realicen son acumulativos, es decir, si por ejemplo se rota un objeto y posteriormente se traslada, ésta traslación se hace sobre la posición que tomo después de la rotación. Pero habrá ocasiones que necesitemos hacer operaciones sobre la situación anterior, o bien, poder volver a la situación anterior. Para ello se pueden utilizar las siguientes funciones: glMatrixMode glLoadIdentity glPushMatrix glPopMatrix 2.7.3. Color y Sombras El aspecto de las aplicaciones gráficas tiene gran influencia a la hora de evaluar y decidirse por una aplicación concreta. Por lo que el color es muy importante a la hora de realizar este tipo de aplicaciones. El color en los ordenadores se genera especificando intensidades separadas de las componentes roja, verde y azul. Por esta razón los monitores se fabrican para producir estos tres tipos de luz. Para especificar un color utilizamos tres valores positivos (que serían las tres componentes). Por lo que, sí un ordenador utiliza 24 bits para el almacenamiento de este tipo de información, entonces tendríamos ocho bits para cada componente y por tanto cada componente de color se podría especificar con valores entre 0 y 255. De ésta forma se podría modelar los colores disponibles como un volumen llamado espacio de color. Si se forma un cubo a partir del espacio anterior, se obtiene un cubo con todos los colores posibles. 46
  • 47. OpenGL soporta dos modos de color: - RGBA, se expresa un color de forma precisa con sus tres componentes (roja, verde y azul) - Modo de color indexado, se elige un color especificando un índice en una matriz de colores (paleta). En la paleta se especifica el color exacto que se quiere seleccionando las intensidades de las componentes roja, verde y azul. ?? Selección de un Color La función de selección de un color es: void glColorXT(GLX rojo, GLX verde, GLX azul) Cuando se utiliza este comando, todos los objetos dibujados a partir de ese m omento tendrán el mismo color hasta que se especifique otro color. ?? Sombreado Otro aspecto importante a la hora de dibujar es lo que se denomina sombreado, que sería la transición suave entre un color y el siguiente, es decir, si al dibujar una línea especificamos en un vértice un color y en el otro vértice otro color, el color de la línea que se dibujará irá variando. El sombreado puede ser de dos tipos: - Suave, se produce una transición suave. - Plano, no se produce ninguna transición, normalmente con este d egradado el color es el del último vértice especificado. Para cambiar el sombreado se hará con , void glShadeModel (Glenum modo) donde modo puede tomar los valores GL_SMOOTH (suave) o GL_FLAT (plano). Dentro de Color y Sombras otra cuestión importante sería la definición y creación de paletas de colores para ajustar o elegir los colores necesarios en un momento dado para una aplicación. 47
  • 48. ?? Cambiar el Color de Fondo Cuando se habla de color es importante explicar como se puede cambiar el color de fondo de una ventana. Según el tipo de aplicación que se quiera crear habrá que modificar el color de fondo de la ventana. Para modificar el color de fondo de la ventana se utiliza la siguiente función: void glClearColor (GLclampf rojo, GLclampf verde, GLclampf azul, GLclampf alfa) Define el color de fondo que se aplicará, utiliza los valores de RGB; Cada argumento corresponde a la intensidad del color, Rojo, Verde y Azul, el rango de estos valores debe ir comprendido entre el valor 0.0; El cuarto p arámetro corresponde al valor alpha del color que se utiliza para determinar información referente a la transparencia del color. Después de definido el color de fondo hay que utilizar la función glClear para borrar la pantalla con el color que se había definido 2.7.4. Luces y Lámparas Los objetos en el mundo real no aparecen como un color sólido y OpenGL permite hacer una aproximación de los objetos dibujados al mundo real utilizando las funciones de iluminación. Anteriormente, se ha visto como darle color a los objetos, pero el color de un objeto puede variar dependiendo de la luz que incida sobre él, por lo que hay que tener en cuenta este aspecto a la hora de seleccionar el color. Un objeto, excepto que emita su propia luz, está iluminado por tres tipos de luz diferentes: - Luz ambiente, es la luz que no viene de ninguna dirección particular. - Luz difusa, esta luz viene de alguna dirección particular, pero es suavemente reflejada por una superficie (como ejemplo puede ser un fluorescente) 48
  • 49. - Luz especular, es direccional, pero no se refleja nítidamente es una dirección particular (como ejemplo se puede decir el sol) Al igual que un color esta compuesto por tres componentes, una fuente de luz está compuesta por tres componentes de luz también: ambiente, difusa y especular. Y así será la forma de especificar la luz. Para implementar y especificar la iluminación en los objetos hay que tener en cuentas aspectos tales como que propiedades reflectivas tienen los materiales de los objetos, calcular los efectos de la luz ambiente y los efectos de difusión y reflexión. Por lo tanto par añadir luz a la escena lo primero que hay que hacer es activar la iluminación con, glEnable (GL_LIGHTTING) Posteriormente, hay que configurar y seleccionar el modelo de iluminación. glfloat luzambiente[]={1.0f, 1.0f, 1.0f, 1.0f} glLightModelfv(GL_LIGHT_MODEL_AMBIENT, luzambiente) Y por último especificar o definir las propiedades de los materiales mediante las funciones, glEnable(GL_COLOR_MATERIAL) glColorMaterialfv(GLenum, cara, GLenum modo) El uso de la luz ambiente es sencillo y tiene sus aplicaciones, pero para darle más realidad a una escena se deben especificar varias fuentes de luz. A la hora de especificar fuentes de luz habrá que definir además de la intensidad y color, la localización de la fuente y la dirección. Para indicar la posición y el color de la luz se utiliza la misma función y se cambiará el valor de los parámetros. La función es la siguiente: glLight(GLenum luz, GLenum pnombre, GLfloat param) En el siguiente ejemplo se ve el efecto que produce la luz que incide sobre el cilindro dibujado. 49
  • 50. #include <windows.h> #include <GL/gl.h> #include <GL/glu.h> #include <GL/glaux.h> void inicializar(void) // Inicializacion de los parametros de OpenGL { GLfloat mat_difuso[] = {1.0,.0,1.0,1.0}; GLfloat posicion_luz[] = {1.0,1.0,1.0,0.0}; // Luz direccional glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); glMaterialfv(GL_FRONT,GL_DIFFUSE ,mat_difuso); glLightfv(GL_LIGHT0,GL_POSITION,posicion_luz); } void CALLBACK cambiartamano(GLsizei w, GLsizei h) { glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0,1.0*(GLfloat)w/(GLfloat)h,1.0,200.0); gluLookAt(0.0,0.0,5.0,0.0,0.0,0.0,0.0,1.0,0.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void CALLBACK dibujar(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); auxSolidCylinder(1.0,1.0); glFlush(); auxSwapBuffers(); } int main(int argc, char* argv[]) { auxInitDisplayMode(AUX_DOUBLE|AUX_RGBA|AUX_DEPTH); auxInitPosition(0,0,500,500); auxInitWindow("LUCES"); inicializar(); auxReshapeFunc(cambiartamano); auxMainLoop(dibujar); return 0; } Listado 2.8: Efecto que produce una luz difusa sobre un objeto 50
  • 51. La imagen que se produce con el código anterior es la siguiente, Figura 2.5: Luces 2.7.5. Gráficos Planos en Opengl Hasta ahora se ha visto que se pueden y como dibujar puntos, líneas, formas geométricas, etc., pero también es importante hablar de los mapas de bits y mapas de píxeles. 2.7.5.1. Mapas de bits Los mapas de bits son imágenes bicolor y se representan mediante arrays de dos dimensiones rellenado con ceros y unos que permitirá crear la imagen deseada. Los mapas de bits se suelen utilizar para crear fuentes. Para crear mapas de bits se utilizará la función, glBitmap(GLsizei ancho, GLsizei alto, GLfloat xorig, GLfloat yorig, GLfloat xmov, GLfloat ymov, const GLubyte *bits) Permite dibujar el mapa de bits que vendrá dado por *bits, que será la matriz que contiene el mapa de bits. 51
  • 52. Antes de dibujar la imagen con glBitmap hay que indicar la posición donde colocarlo (posición raster) con la función glRasterPos() El siguiente trozo de código nos muestra como mostrar la letra E utilizando bitmaps. #include <windows.h> #include <GL/gl.h> #include <GL/glaux.h> GLubyte ees[24]= { 0xff, 0xc0, 0xff, 0xc0, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xff, 0xc0, 0xff, 0xc0 }; void init(void) { glPixelStorei(GL_UNPACK_ALIGNMENT,1); glClearColor(1.0, 1.0, 1.0, 1.0); } void CALLBACK dibujar(void) { int i; float pos=0.0; float pos1=500.0; glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 0.0, 1.0); for (i = 0; i < 10; i ++) { glRasterPos2i(pos+i*50, pos+i*50); glBitmap(10, 12, 0.0, 0.0, 12.0, 0.0, ees); glRasterPos2i(pos+i*50, pos1-i*50); glBitmap(10, 12, 0.0, 0.0, 12.0, 0.0, ees); }; glFlush(); } void CALLBACK cambiotamano(GLsizei w, GLsizei h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, w, 0, h, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); } void main(int arg, char** argv) { auxInitDisplayMode(AUX_SINGLE|AUX_RGBA); auxInitPosition(0, 0, 500, 500); auxInitWindow("Mapa de bits"); init(); auxReshapeFunc(cambiotamano); auxMainLoop(dibujar); } 52
  • 53. Listado 2.9: Uso de producirá la siguiente salida, El código anterior bitmaps Figura 2.6: Bitmaps 2.7.5.2. Mapas de píxeles Los mapas de píxeles son como los mapa de bits, pero la imagen tendrá mas de dos colores. Estos se utilizan como imágenes de fondo. En OpenGL los mapas de píxeles pueden ser imágenes de 8 bits indexadas, o bien, imágenes RGB de 24 bits. La función utilizada para dibujar mapas de píxeles es: glDrawPixels(GLsizei ancho, GLsizei alto, GLenum formato, GLenum tipo, const GLvoid *píxeles) A la hora de trabajar con mapas de bits y de píxeles se puede hablar de los ficheros .BMP de Windows. Trabajar con estos ficheros desde programas OpenGL es muy sencillo. Para ello se utilizarán las estructuras BITMAPFILEHEADER y BITMAPINFOHEADER, que se encuentran dentro de cualquier fichero .BMP al comienzo de éste. Después de estas dos estructuras vendran ya los datos de la imagen. 53
  • 54. 2.7.6. Texturas Poner texturas en los gráficos es uno de los avances más importantes en los gráficos 3D. El mapeado de texturas es como poner papel pintado en una pared. Es decir, permite cubrir los polígonos que forman el dibujo con imágenes. El mapeado de texturas se utiliza para conseguir imágenes más reales. Se pueden mapear texturas en una, dos y tres dimensiones. Los pasos para utilizar el mapeado de texturas son, - Definir una imagen para textura antes de que se puedan dibujar con polígonos con textura. glTextImage?d(GLenum objetivo, GLint nivel, GLint componentes, GLsizei ancho, GLint borde, GLenum formato, GLenum tipo, cons GLvoid *píxeles) - Después hay que habilitar el mapeado de texturas con la función, glEnable(GL_TEXTURE_?D) - Por último, habrá que mapear la textura, es decir, cuando se dibuja el objeto, hay que indicar que posición de la textura la corresponde en cada vértice, glTextCoord??(Type *s) 2.8. Conclusiones Depués de ver en ésta introducción las características de OpenGL y algunas de la operaciones que se pueden realizar con ésta librería, se puede observar que es muy potente y fácil de usar, además de tener las ventajas de portabilidad y estandarización, y por tanto OpenGL es una buena elección para producir efectos visuales y escenas e imágenes realistas. De hecho está librería se esta utilizando en gran cantidad de aplicaciones como ya se comento anteriormente y es muy probable que se siga utilizando en muchas otras. 54
  • 55. 2.9. Bibliografía Neider J., Davis T., Woo M. (1993) OpenGL Programming Guide. The official guide to learning OpenGL, Release 1. Addison-Wesley Publising Company. Richard S. Wright Jr., Sweet M. Programación en OpenGL. Anaya Multimedia Kilgard M. (1996) The OpenGL Utility Toolkit (GLUT). Programing Interface. API Version 3. Silicon Graphics, Inc. Segal M., Akely K (1999). The OpenGL Graphcis System: A Specification (Version 1.2.1). Silicon Graphics, Inc. Segal M., Akely K (1994). The Design of the OpenGL Graphcis Interface. Silicon Graphics, Inc. Using OpenGl to Create 2D and 3D Graphics. UCLA Academic Technology Services. (http://www.ats.ucla.edu/at/software/scivis/Scientific Visualization Software - Using OpenGL to Create 2D and 3D Graphics.htm) Huescar J.M., Serra J.C., Bennasar A.F. (1999/2000). Manual de OpenGL Sepúlveda M.A. (1988) ¿Qué es OpenGL?. http://www.linuxfocus.org/Castellano/January1998/article15.html Sepúlveda M.A. (1988) Programando OpenGL: Trazado de Polígonos Simples. http://www.linuxfocus.org/Castellano/January1998/article17.html Sepúlveda M.A. (1988) Programando OpenGL: Más sobre líneas http://www.linuxfocus.org/Castellano/March1998/article28.html Sepúlveda M.A. (1988) Programación OpenGL: Escenas 3D. http://www.linuxfocus.org/Castellano/May1998/article46.html 55