Manual Opengl

download Manual Opengl

of 85

Transcript of Manual Opengl

  • Curso de introduccin a OpenGL (v1.0)Por Jorge Garca (Bardok)

    Este manual ha sido realizado para el e-ghost, por Jorge Garca, est sujeto a la licenciaFDL (GNU Free Document License), y confiere los derechos y obligaciones pertinentes. 2003 - Jorge Garca (Bardok)

  • Curso de introduccin a OpenGL (v1.0)

    ndice de contenidoCaptulo 1: Introduccin.............................................................................................................7

    1.1 Propsito de este manual...............................................................................................71.2 A quin est dirigido?...................................................................................................71.3 Acerca del manual..........................................................................................................8

    Captulo 2: OpenGL y Linux......................................................................................................92.1 La librera OpenGL.........................................................................................................92.2 Linux y OpenGL..............................................................................................................9

    2.2.1 Qu es necesario para desarrollar aplicaciones OpenGL?............................10Captulo 3: Conceptos bsicos sobre OpenGL.....................................................................13

    3.1 OpenGL como mquina de estados............................................................................133.2 El espacio 3D................................................................................................................14

    3.2.1 Las transformaciones de los objetos...................................................................143.2.2 Las coordenadas homogneas...........................................................................16

    3.3 Sobre GLUT..................................................................................................................173.4 Las funciones bsicas de OpenGL.............................................................................17

    3.4.1 Activacin/desactivacin de opciones.................................................................173.4.2 Las matrices y OpenGL........................................................................................173.4.3 El dibujado en OpenGL........................................................................................183.4.4 El color en OpenGL..............................................................................................193.4.5 La orientacin de las caras en OpenGL.............................................................193.4.6 Las transformaciones en OpenGL......................................................................203.4.7 La proyeccin en OpenGL...................................................................................20

    3.5 Primer contacto con OpenGL......................................................................................213.5.1 Mi primer programa OpenGL...............................................................................213.5.2 Visualizando en perspectiva................................................................................233.5.3 Ocultacin de objetos (Z-Buffer)..........................................................................253.5.4 Una jerarqua sencilla...........................................................................................27

    Captulo 4: Animaciones..........................................................................................................314.1 Los vectores para animar figuras................................................................................314.2 El doble buffering..........................................................................................................35

    Captulo 5: Iluminacin............................................................................................................375.1 El modelo de iluminacin en OpenGL.........................................................................37

    5.1.1 Luces.....................................................................................................................385.1.2 Materiales..............................................................................................................385.1.3 Normales...............................................................................................................38

    5.2 Utilizando iluminacin en OpenGL..............................................................................395.2.1 Luces.....................................................................................................................395.2.2 Materiales..............................................................................................................415.2.3 Ejemplo: iluminacin direccional sobre una superficie......................................425.2.4 Ejemplo: moviendo un foco alrededor de una esfera........................................435.2.5 Ejercicio propuesto...............................................................................................45

    Captulo 6: Texturas.................................................................................................................476.1 Las coordenadas de textura........................................................................................476.2 Aplicar las texturas.......................................................................................................48

    6.2.1 Repeticin de texturas..........................................................................................50Captulo 7: Interaccin bsica con GLUT..............................................................................53

    7.1 Interaccin con el teclado............................................................................................537.2 Redimensionado de la ventana...................................................................................54

    Captulo 8: Recursos de inters..............................................................................................57

    2003 - Jorge Garca (Bardok) 3

  • Curso de introduccin a OpenGL (v1.0)

    Anexo A: Cdigo de los programas de ejemplo....................................................................59A.a myfirstopenglprogram.c...............................................................................................59A.b quadortho.c...................................................................................................................60A.c quadpersp.c..................................................................................................................61A.d zbuffer-yes.c.................................................................................................................62A.e simpleguy.c...................................................................................................................63A.f sphere-rebotes.cpp.......................................................................................................66A.g sphere-rebotes-multi.cpp.............................................................................................69A.h normals-perp.c..............................................................................................................70A.i lit-sphere.c......................................................................................................................71A.j l-sphere-rebotes-multi.cpp............................................................................................73A.k triang-texture.c..............................................................................................................77A.l normals-perp-texture.c..................................................................................................78A.m texture-no-clamp.c + texture-yes-clamp.c.................................................................80A.n lit-sphere-keyb.c...........................................................................................................82

    4 ESIDE Ghost

  • Curso de introduccin a OpenGL (v1.0)

    ndice de ilustracionesFigura 2.1. Acceso al hardware a travs de OpenGL (Linux)..............................................10Figura 3.1. Ejes de coordenadas en OpenGL.......................................................................14Figura 3.2. Traslacin de un objeto........................................................................................15Figura 3.3. Rotacin de un objeto...........................................................................................15Figura 3.4. Escalado en el eje X.............................................................................................16Figura 3.5. Vrtices de un polgono........................................................................................19Figura 3.6. Volmen de proyeccin ortogrfico.....................................................................20Figura 3.7. Volmen de visualizacin en perspectiva...........................................................21Figura 3.8. Salida del programa "myfirstopenglprogram".....................................................23Figura 3.9. Salida del programa "quadortho".........................................................................24Figura 3.10. Salida del programa quadpersp......................................................................25Figura 3.11. Dibujado de sin Z-Buffer....................................................................................26Figura 3.12. Dibujado con Z-Buffer (salida del programa zbuffer-yes)................................27Figura 3.13. Salida del programa "simpleguy"......................................................................29Figura 3.14. Rotacin del brazo (simpleguy).........................................................................29Figura 4.1. Representacin de la posicin y velocidad con vectores..................................32Figura 4.2. Comportamiento del programa "rebotes"...........................................................32Figura 4.3. Posicin de la cmara en el ejemplo "sphere-rebotes".....................................34Figura 4.4. Salida del programa "sphere-rebotes"................................................................35Figura 4.5. Salida del programa "sphere-rebotes-multi".......................................................36Figura 5.1. Efecto de las normales en la iluminacin...........................................................39Figura 5.2. Tipos de luces.......................................................................................................40Figura 5.3. Salida del programa "lit-sphere"..........................................................................45Figura 5.4. Salida del programa "l-sphere-rebotes-multi".....................................................46Figura 6.1. Coordenadas de textura.......................................................................................47Figura 6.2. Mapeado de textura..............................................................................................48Figura 6.3. Diferencias entre GL_REPLACE y GL_MODULATE........................................49Figura 6.4. Texturas para suelo y pared................................................................................50Figura 6.5. Salida del programa "texture-no-clamp".............................................................51Figura 6.6. Salida del programa "texture-yes-clamp"...........................................................52

    2003 - Jorge Garca (Bardok) 5

  • Curso de introduccin a OpenGL (v1.0)

    ndice de tablasTabla 3.1. Primitivas de dibujado............................................................................................19Tabla 4.1. Mtodos de la clase TSphere...............................................................................33

    6 ESIDE Ghost

  • Captulo 1: Introduccin Curso de introduccin a OpenGL (v1.0)

    Captulo 1: Introduccin

    Cuando no sepas qu poner, mejor nopongas nada... (Bardok)

    1.1 Propsito de este manualEste manual intenta ser una gua para adentrarse en la programacin 3D, con la libreraOpenGL, y orientado a la programacin bajo Linux, aunque los conceptos aqu explicadosson mayormente vlidos para cualquier otra plataforma.El enfoque que se va a dar es muy prctico, basado casi ntegramente en la realizacin deejercicios que permitan al lector obtener los conocimientos bsicos para desenvolversepor su cuenta en el mundo de la programacin 3D.

    1.2 A quin est dirigido?Este manual est dirigido a cualquier persona que tenga inters en adentrarse en elmundo de la programacin 3D con OpenGL, y muy especialmente a los asistentes delcurso del e-ghost que se celebrar en Julio del ao 2003 en (esperemos) la Universidadde Deusto, en la que est fsicamente ubicada dicho grupo.Las personas que intenten hacer algo de utilidad con este manual, deben tener unosconocimientos mnimos de programacin en C/C++, y tambin vendran bien algunasnociones de Java, aunque esto no es indispensable...No son necesarios conocimientos de programacin especficos bajo Linux, ya que todo lonecesario para programar bajo esta plataforma se recoge en este manual.El manual no se recomienda a personas con conocimientos avanzados de OpenGL, yaque no va a contar nada revolucionario acerca de esta librera grfica 3D, si bien, quinsabe, siempre se puede aprender algo nuevo...

    2003 - Jorge Garca (Bardok) 7

  • Curso de introduccin a OpenGL (v1.0) Acerca del manual

    1.3 Acerca del manualEl contenido de este manual se divide en secciones que intentan abordar separadamentelos distintos puntos por los que un usuario principiante deber pasar al enfrentarse a laprogramacin con OpenGL bajo Linux (a partir de este momento, simplemente OpenGL).En el captulo 1 comenzaremos con una introduccin a la librera OpenGL.En el captulo 2 se explicarn las maneras en las que OpenGL aparece en la plataformaLinux, y cmo deberemos de instalar lo necesario para programar con l.En el captulo 3 se comenzar con la programacin en OpenGL como tal, viendo losconceptos bsicos acerca de transformaciones y visualizacin propios de esta librera.En el captulo 4 se hablar de cmo animar las escenas.En el captulo 5 se describen los fundamentos de la iluminacin, y cmo se utiliza enOpenGL.En el captulo 6 se explica la utilizacin de texturas en OpenGL, de manera bsica.En el captulo 7 se explica brevemente cmo interactuar con las ventanas mediante lalibrera glut.En el captulo 8 se recomiendan una serie de lecturas de inters.

    8 ESIDE Ghost

  • Captulo 2: OpenGL y Linux Curso de introduccin a OpenGL (v1.0)

    Captulo 2: OpenGL y Linux

    No permitas que los rboles teimpidan ver al chalado que te persiguecon una motosierra... (Bardok)

    2.1 La librera OpenGLOpenGL es un estndar creado por Silicon Graphics en el ao 1992 para el diseo de unalibrera 2D/3D portable [OPENGL]. Actualmente es una de las tecnologas ms empleadasen el diseo de aplicaciones 3D, y su ltima versin, a la fecha de hoy (2003), es la 1.4.Se divide en tres partes funcionales:

    La librera OpenGL, que proporciona todo lo necesario para acceder a las funciones dedibujado de OpenGL.

    La librera GLU (OpenGL Utility Library), una librera de utilidades que proporcionaacceso rpido a algunas de las funciones ms comunes de OpenGL., a travs de laejecucin de comandos de ms bajo nivel, pertenecientes a la librera OpenGLpropiamente dicha [REDBOOK].

    GLX (OpenGL Extension to the X Window System) proporciona un acceso a OpenGLpara poder interactuar con un sistema de ventanas X Window, y est incluido en lapropia implementacin de OpenGL (su equivalente en Windows es la librera WGL,externa a la implementacin de OpenGL).

    Adems de estas tres libreras, la librera GLUT (OpenGL Utility Toolkit) proporciona unainterfaz independiente de plataforma para crear aplicaciones de ventanas totalmenteportables [GLUT].

    2.2 Linux y OpenGLOpenGL aparece en Linux, habitualmente bajo la librera Mesa 3D [MESA], unaimplementacin libre de OpenGL. Esta implementacin es, de por s, una implementacin

    2003 - Jorge Garca (Bardok) 9

  • Curso de introduccin a OpenGL (v1.0) Linux y OpenGL

    totalmente software de la librera OpenGL (excepto para las tarjetas 3dfx Voodoo1,Voodoo2, Voodoo Rush, Voodoo Banshee, Voodoo3, que tienen acceso al hardware atravs del driver Mesa/Glide que proporciona Mesa), por lo que slo es aconsejableutilizarla en el caso de no disponer de ninguna otra implementacin de OpenGL.Actualmente (2003) la versin estable de esta librera es la 5.0.1, que implementa elestndar OpenGL 1.4.La utilizacin ms habitual de esta librera, no obstante, se realiza a partir de la libreraxlibmesa. Esta librera forma parte del sistema Xfree86, y proporciona acceso aaceleracin grfica por hardware, siempre que la tarjeta grfica y los drivers instalados lopermitan, a travs de DRI (Direct Rendering Infraestructure [DRI]). Este es el modo atravs del que podemos acceder a aceleracin por hardware para tarjetas de vdeo como3dfx, Intel, Matrox, ATI... DRI est presente en las implementaciones del servidor Xfree86a partir de la versin 4 del mismo.Finalmente, las tarjetas NVIDIA proporcionan su propia implementacin de la libreraOpenGL, independientemente de la librera Mesa, si bien es cierto que ciertas partes deMesa (las libreras de utilidades GLU y GLUT) pueden utilizarse junto con laimplementacin de NVIDIA.En resumen, podemos utilizar la librera OpenGL de diferentes maneras, segn nuestraconfiguracin de hardware:

    Figura 2.1. Acceso al hardware a travs de OpenGL (Linux)

    2.2.1 Qu es necesario para desarrollar aplicacionesOpenGL?A la hora de desarrollar aplicaciones OpenGL bajo Linux, necesitaremos las siguientesherramientas:

    Los binarios de la librera OpenGL, ya sea Mesa (compilado e instalado a partir delcdigo fuente), xlibmesa (incluido con Xfree86 4 y posteriores) o drivers propios.

    Los paquetes de desarrollo de estas libreras (xlibmesa-dev, en el caso de xlibmesa,

    10 ESIDE Ghost

    HARDWARE

    DRISoftware Render

    Xlibmesa

    Mesa/Glide

    Interfaz OpenGL

    Mesa

    Aplicacin 3D

    NVIDIA OpenGLDriver

  • Captulo 2: OpenGL y Linux Curso de introduccin a OpenGL (v1.0)

    glutg3-dev... para drivers propios depender del fabricante, y para Mesa, si se hainstalado compilando el cdigo fuente, no debera de haber problemas).

    Un compilador del lenguaje en el que vamos a programar, en este caso, en C, paralo que usaremos el compilador gcc, y g++ si utilizamos C++.

    Un editor de texto, ya sea en modo consola, o bajo el entorno X Windows (a m megusta el Kate de KDE, pero cada cual tiene sus preferencias).

    Ahora ya estamos listos para comenzar a programar con OpenGL...

    2003 - Jorge Garca (Bardok) 11

  • Captulo 3: Conceptos bsicos sobre OpenGL Curso de introduccin a OpenGL (v1.0)

    Captulo 3: Conceptos bsicos sobre OpenGL

    Por qu narices habr puesto quedespus de el nombre de un captulo,me pida poner una cita de maneraautomtica? (Bardok)

    3.1 OpenGL como mquina de estadosOpenGL es una librera que trabaja como una mquina de estados. Esto es algo queoiremos hasta la saciedad al programar con OpenGL... pero qu significa? La utilizacinde OpenGL consiste en activar y desactivar opciones, y realizar ciertas acciones, quetendrn como fruto una representacin en pantalla (o no) de una serie de datos,dependiendo en el estado en que nos encontremos...As, no ser lo mismo dibujar un tringulo y activar una textura, que activar una textura ydibujar un tringulo... en OpenGL, el orden de las acciones resulta crtico en la mayora delas ocasiones... de igual manera, no ser lo mismo trasladar y rotar algo, que rotarlo ytrasladarlo, como veremos ms adelante, en lo referente a las transformaciones...De este modo, de manera muy abstracta, la manera de dibujar algo en OpenGL suele serla siguiente:1. Activar todas las opciones que van a ser persistentes a la escena (ponemos la cmara,

    activamos la iluminacin global...)2. Activar las opciones que establecen el estado de un objeto especfico (su posicin en el

    espacio, su textura...)3. Dibujar el objeto.4. Desactivar las opciones propias de ese objeto (volver a la posicin original, desactivar

    su textura)5. Volver al punto 2 hasta haber dibujado todos los objetos.Esto, evidentemente, es un esquema sencillo... como se ver ms adelante, estasoperaciones pueden agruparse en jerarquas, lo que proporciona una gran potencia y

    2003 - Jorge Garca (Bardok) 13

  • Curso de introduccin a OpenGL (v1.0) OpenGL como mquina de estados

    flexibilidad a la hora de programar (se nota que soy fan de OpenGL? ;-)

    3.2 El espacio 3DSi bien es cierto que OpenGL proporciona acceso a funciones de dibujado 2D, en estecurso nos vamos a centrar en el espacio 3D... OpenGL trabaja, a grandes rasgos, en unespacio de tres dimensiones, aunque veremos que realmente, trabaja con coordenadashomogneas (de cuatro dimensiones). Las tres dimensiones que nos interesan ahora sonlas especificadas por un sistema 3D ortonormal. Es decir, sus ejes son perpendiculares, ycada unidad en uno de ellos est representada por un vector de mdulo 1 (si nos alejamosuna unidad, nos alejamos la misma distancia del eje de coordenadas, da igual ladireccin).

    Figura 3.1. Ejes de coordenadas enOpenGL

    La cuarta coordenada se utiliza entre otras razones, para representar la perspectiva, perono nos meteremos con ello en este momento... de este modo, el sistema de coordenadasinicial de un sistema OpenGL puede representarse con esta matriz:

    1 0 0 00 1 0 00 0 1 00 0 0 1

    Finalmente, es recomendable desempolvar nuestros algebraicos bsicos (vectores,normales, etc.), porque como veremos, nos van a resultar de gran utilidad a la hora deprogramar en 3D...La situacin de los ejes de coordenadas se refleja en la matriz de transformacin. Estamatriz representa la transformacin que se aplicar a todos los vrtices que se dibujenmientras ella est activa.

    3.2.1 Las transformaciones de los objetosAl or hablar de programacin 3D, habremos odo hablar de las transformaciones deobjetos... estas transformaciones son las que van a describir cmo se visualiza un

    14 ESIDE Ghost

    Z

    X

    Y

  • Captulo 3: Conceptos bsicos sobre OpenGL Curso de introduccin a OpenGL (v1.0)

    objeto en el espacio, y son de tres tipos: Traslacin: una traslacin es un desplazamiento de un objeto en el espacio... por

    ejemplo, movemos un objeto a una nueva posicin desde la actual

    Figura 3.2. Traslacin de un objeto

    Rotacin: como su nombre indica, un objeto rota alrededor de un eje que pasa porsu centro de giro

    Figura 3.3. Rotacin de un objeto

    Escalado: un objeto puede ver afectado el tamao con que se visualiza por sutransformacin de escalado

    2003 - Jorge Garca (Bardok) 15

  • Curso de introduccin a OpenGL (v1.0) El espacio 3D

    Figura 3.4. Escalado en el eje X

    Sin entrar en demasiados detalles, es conveniente saber que toda trasformacinconstruye una matriz de cuatro dimensiones que se multiplicar por la matriz detransformacin inicial (aquella que define el eje de coordenadas).Por ejemplo, al trasladar un objeto dos unidades en el eje X, se genera la siguientematriz de transformacin:

    1 0 0 20 1 0 00 0 1 00 0 0 1

    Si aplicamos esta transformacin a la matriz original, nos quedar que la nueva matrizde transformacin es:

    1 0 0 00 1 0 00 0 1 00 0 0 1

    1 0 0 20 1 0 00 0 1 00 0 0 1

    1 0 0 20 1 0 00 0 1 00 0 0 1

    Si ahora dibujamos el punto (1,0,0), teniendo en cuenta que la matriz indica undesplazamiento de dos unidades en eje X, el punto debera de dibujarse en la posicin(3,0,0). Para esto, se multiplica el punto por la matriz de transformacin:

    1 0 0 20 1 0 00 0 1 00 0 0 1

    1001

    3001

    Para poder multiplicar el punto (1,0,0) por la matriz, lo hemos convertido a coordenadashomogneas, y para ello, hemos aadido una ltima componente con el valor 1.

    3.2.2 Las coordenadas homogneasCuando pensamos en dibujado 3D, estamos acostumbrados a pensar en espacios de

    16 ESIDE Ghost

  • Captulo 3: Conceptos bsicos sobre OpenGL Curso de introduccin a OpenGL (v1.0)

    tres coordenadas, o dos, para figuras 2D, pero en OpenGL todo se traduce acoordenadas homogneas. Las razones son varias (uniformidad de operacin conmatrices y facilidad de representacin de diferentes conceptos relativos a laprofundidad), pero no es objeto de este manual discutirlas.De esta forma, el punto 3D (1,2,3) es traducido por OpenGL al punto (1,2,3,1.0) y elpunto 2D (1,2) es traducido a (1,2,0.0,1.0). A grandes rasgos, podemos de decir que unpunto (x,y,z,w) en coordenadas homogneas, es equivalente al punto 3D (x/w,y/w,z/w).As los puntos (1,2,0,10), (1,2,0,1) y (1,2,0,0.00001) se corresponden con los puntos2D (0.1,0.2), (1,2) y (10000,20000).Un apunte interesante es que si la coordenada w es igual a 0, estaramos hablando, delpunto situado en el infinito en la direccin del vector que especifican las otras trescoordenadas (vemos que, si se decrementa la w, el punto 2D o 3D equivalente sealeja). Esto resultar muy til para entender ciertos aspectos de la iluminacin.

    3.3 Sobre GLUTPara los ejemplos de este manual vamos a utilizar la librera de ventanas GLUT, y paraello hemos de tener claros ciertos aspectos de esta librera.La librera GLUT incluye funciones para la creacin de ventanas independiente deplataforma. A medida que vayamos viendo distintos ejemplos, iremos profundizando enlas funciones utilizadas. Inicialmente, slo vamos a comentar que GLUT funcionageneralmente a travs de funciones de callback, es decir, como parmetro de una funcin,se le pasa un puntero a otra funcin que ser llamada por la funcin principal.

    3.4 Las funciones bsicas de OpenGLPara comenzar a utilizar OpenGL hemos de tener claras diversas funciones que vamos autilizar muy a menudo.

    3.4.1 Activacin/desactivacin de opcionesComo se ha comentado, OpenGL es una mquina de estados: activamos ydesactivamos opciones que afectan al dibujado. Habitualmente, las opciones se activany desactivan con glEnable() y glDisable().Por ejemplo glEnable(GL_LIGHTING) activar la iluminacin bsica de la escena.

    3.4.2 Las matrices y OpenGLAnteriormente hemos visto que OpenGL guarda la transformacin de los objetos enuna matriz. A esta matriz se le denomina matriz de visualizacin/modelado, porque seemplea para estas dos funciones.Adems de esta transformacin, OpenGL posee otra matriz muy importante, que es la

    matriz de proyeccin, en la que se guarda la informacin relativa a la cmara a travsde la cual vamos a visualizar el mundo.Al realizar operaciones que modifiquen alguna de estas dos matrices, tendremos quecambiar el modo de matriz, para que las operaciones afecten a la matriz que nosinteresa.Para ello utilizaremos las funciones glMatrixMode(GL_MODELVIEW) o

    2003 - Jorge Garca (Bardok) 17

  • Curso de introduccin a OpenGL (v1.0) Las funciones bsicas de OpenGL

    glMatrixMode(GL_PROJECTION).Adems, existen dos funciones que permiten guardar y restaurar los valores de lamatriz activa en una pila.La funcin glPushMatrix() guarda una matriz en la cima de la pila, y glPopMatrix() lasaca, y la restaura. Esto lo podemos utilizar para dibujar un objeto y, antes de dibujar elsiguiente, restauramos la transformacin inicial. Por ejemplo:

    glPushMatrix();

    glPopMatrix(); // volvemos a la transformacin comnglPushMatrix();

    glPopMatrix(); // volvemos a la transformacin comn...

    Finalmente, comentar la operacin glLoadIdentity(), que carga la matriz identidad comomatriz activa.

    3.4.3 El dibujado en OpenGLPara dibujar en OpenGL, tenemos que habilitar el modo de dibujado, establecer lasopciones de dibujado de cada vrtice, y dibujar cada uno de ellos. Al terminar dedibujar una figura, finalizamos el modo de dibujado.Para comenzar a dibujar, utilizaremos el comando glBegin(),dnde el modo de dibujado vendr dado por una constante:

    18 ESIDE Ghost

  • Captulo 3: Conceptos bsicos sobre OpenGL Curso de introduccin a OpenGL (v1.0)

    Parmetro DescripcinGL_POINTS Se dibujan vertices separadosGL_LINES Cada par de vrtices se interpreta como una lneaGL_POLYGON Los vrtices describen el contorno de un polgonoGL_TRIANGLES Cada triplete de vrtices de interpreta como un tringuloGL_QUADS Cada cuarteto de vrtices se interpreta como un cuadrilteroGL_LINE_STRIP Lneas conectadasGL_LINE_LOOP Lneas conectadas, con unin entre el primer y ltimo vrticeGL_TRIANGLE_STRIP

    Se dibuja un tringulo, y cada nuevo vrtice se interpreta conun tringulo entre los dos anteriores vrtices y el nuevo

    GL_TRIANGLE_FAN

    Se dibujan tringulos con un vrtice comn

    GL_QUAD_STRIP Igual que el TRIANGLE_STRIP, con cuadrilterosTabla 3.1. Primitivas de dibujado

    Entre las funciones que permiten establecer los atributos de cada vrtice, estnaquellas que nos permiten seleccionar su color (glColor*), normal (glNormal*),coordenadas de textura (glTexCoord*), etc.Finalmente, las funciones de dibujado de vrtices tienen la forma glVertex*.

    3.4.4 El color en OpenGLOpenGL puede utilizar dos modos de color: color RGBA y color indexado. Nosotrosvamos a centrarnos en el color RGBA. Este color recibe este nombre porque secompone de cuatro componentes: Rojo (Red), Verde (Green), Azul (Blue) y canal Alfa,o transparencia.

    3.4.5 La orientacin de las caras en OpenGLUn polgono tiene dos caras, delantera y trasera. La manera de saber qu cara es ladelantera, y cual la trasera, es que, si miramos la delantera, los vrtices se habrndibujado en orden antihorario.Por ejemplo, tenemos la siguiente figura:

    Figura 3.5. Vrticesde un polgono

    Si dibujamos los vertices en el orden 1,3,4,2, estaremos dibujando la cara delanteramirando hacia nosotros, pero si el orden es, por ejemplo, 1,2,4,3, estaremos mirando lacara trasera del polgono.

    2003 - Jorge Garca (Bardok) 19

    1 2

    3 4

  • Curso de introduccin a OpenGL (v1.0) Las funciones bsicas de OpenGL

    3.4.6 Las transformaciones en OpenGLFinalmente, como operaciones bsicas, vamos a comentar aquellas que nos van apermitir situar los objetos en el espacio, es decir, aplicarles transformaciones:

    glTranslate*: nos va a permitir trasladar un objeto en el espacio glRotate*: nos va a permitir rotar un objeto glScale*: nos va a permitir escalar un objeto glMultMatrix: multiplica la matriz de transformacin actual por una matriz dada. Esto

    es algo muy utilizado en motores 3DEs muy importante el orden en el que vayamos a realizar las transformaciones. No eslo mismo trasladar algo y despus rotarlo, que primero rotarlo y luego trasladarlo, comopodremos comprobar posteriormente...

    3.4.7 La proyeccin en OpenGLEn el modo de proyeccin podemos especificar cmo va a afectar la posicin de unobjeto a su visualizacin. Tenemos dos maneras de visualizar el espacio: con unaproyeccin ortogrfica, y con una proyeccin perspectiva:

    La proyeccin ortogrfica:La proyeccin ortogrfica nos permite visualizar todo aquello que se encuentredentro de un cubo, delimitado por los parmetros de la funcin glOrto. A la hora devisualizar, la distancia al observador slo se tiene en cuenta para determinar si elobjeto est dentro o fuera del cubo...

    Figura 3.6. Volmen de proyeccinortogrfico

    La proyeccin perspectiva:La proyeccin perspectiva delimita un volmen de visualizacin dado por un ngulode cmara, y una relacin alto/ancho. La distancia al observador determinar eltamao con el que un objeto se visualiza.

    20 ESIDE Ghost

    Anchura

    Largura

    Altu

    ra

  • Captulo 3: Conceptos bsicos sobre OpenGL Curso de introduccin a OpenGL (v1.0)

    Figura 3.7. Volmen de visualizacin en perspectiva

    3.5 Primer contacto con OpenGLBueno, aqu est lo que todo programador desea tocar: el cdigo ;-) vamos a comenzarcon unos sencillos programas con los que podremos comprobar cmo se utilizan losconceptos anteriormente explicados.

    3.5.1 Mi primer programa OpenGLEn este programa vamos a dibujar un tringulo en pantalla con un vrtice de cadacolor...Vamos a hacer un nico include, con la cabecera de GLUT. Generalmente, losarchivos de cabecera de OpenGL estarn en el direcctorio GL dentro del rbol dearchivos de cabecera:

    #include

    Slo inclumos este archivo, porque ya incluye las cabeceras gl.h y glu.h.Comenzamos con la funcin main:

    int main(int argc, char * argv){

    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);glutInitWindowPosition(20,20);glutInitWindowSize(500,500);glutCreateWindow(argv[0]);

    glutDisplayFunc(display);glutMainLoop();

    return 0;}

    Lsa cuatro primeras llamadas crean la ventana con la librera GLUT:1. Inicializamos los modos con los que se crear la ventana: con un slo buffer de

    dibujado, y modelo de color RGBA (rojo, verde, azl y canal alfa transparencias).

    2003 - Jorge Garca (Bardok) 21

  • Curso de introduccin a OpenGL (v1.0) Primer contacto con OpenGL

    2. Establecemos el tamao y posicin de la ventana3. Creamos la ventanaDespus establecemos que funcin indica qu hay que dibujar en la ventana. displayes un puntero a una funcin que contiene el cdigo de lo que vamos a dibujar, yllamamos a la funcin que comienza el dibujado.Ahora slo nos queda definir la funcin display:

    void display(void){

    glClearColor(0.0,0.0,0.0,0.0);// Color de fondo: negroglClear(GL_COLOR_BUFFER_BIT);// Boramos la pantalla

    glMatrixMode(GL_PROJECTION);// Modo proyeccinglLoadIdentity();// Cargamos la matriz identidad

    glOrtho(-1.0,1.0,-1.0,1.0,-1.0,1.0);// Proyeccin ortogrfica, dentro del cubo sealado

    glMatrixMode(GL_MODELVIEW);// Modo de modelado

    glBegin(GL_TRIANGLES);// Dibujamos un tringulo

    glColor3f(1.0,0.0,0.0);// Color del primer vrtice: rojoglVertex3f(0.0,0.8,0.0);// Coordenadas del primer vrticeglColor3f(0.0,1.0,0.0);// Color del segundo vrtice: verdeglVertex3f(-0.6,-0.2,0.0);// Coordenadas del segundo vrticeglColor3f(0.0,0.0,1.0);// Color del tercer vrtice: azlglVertex3f(0.6,-0.2,0.0);// Coordenadas del tercer vrtice

    glEnd();// Terminamos de dibujar

    glFlush();// Forzamos el dibujado

    sleep(10);// Esperamos 10 segundos

    exit(0);// Salimos del programa

    } La funcin glClearColor especifica cul va a ser el color con el que se va rellenar el

    buffer de pantalla cuando se borre Con glClear ordenamos a OpenGL que borre los buffers indicados como parmetro.

    Para borrar la pantalla (el buffer de color) lo indicamos con la constante

    22 ESIDE Ghost

  • Captulo 3: Conceptos bsicos sobre OpenGL Curso de introduccin a OpenGL (v1.0)

    GL_COLOR_BUFFER_BIT Establecemos el volmen de visualizacin, en modo proyeccin y con glOrtho. Dibujamos el tringuloGuardamos el cdigo como myfirtsopenglprogram.c, y lo compilamos con la siguientelnea de cdigo en una consola:

    user@machine:$gcc myfirtsopenglprogram.c -lglut -lGL -lGLU -omyfirtsopenglprogram

    Ejecutamos con:user@machine:$./myfirstopenglprogram

    Figura 3.8. Salida del programa "myfirstopenglprogram"

    3.5.2 Visualizando en perspectiva...Vamos a dibujar un cuadrado con un programa muy similar al que tenemos en elejemplo anterior. Para ello vamos a sustituir el cdigo referente al dibujado por elsiguiente cdigo:

    glBegin(GL_QUADS);// Dibujamos un cuadradoglColor3f(0.0,1.0,1.0);// Color para el cuadradoglVertex3f(-0.5,0.5,-0.5);// Coordenadas del primer vrtice (superior-izquierda)

    2003 - Jorge Garca (Bardok) 23

  • Curso de introduccin a OpenGL (v1.0) Primer contacto con OpenGL

    glVertex3f(-0.5,-0.5,0.5);// Coordenadas del segundo vrtice (inferior-izquierda)glVertex3f(0.5,-0.5,0.5);// Coordenadas del primer vrtice (inferior-derecha)glVertex3f(0.5,0.5,-0.5);// Coordenadas del primer vrtice (superior-derecha)

    glEnd();// Terminamos de dibujar

    Guardamos como quadortho.c, compilamos el programa, y observamos el resultado:user@machine:$gcc quadortho.c -lglut lGL -lGLU -o quadorthouser@machine:$./quadortho

    Figura 3.9. Salida del programa "quadortho"

    Si estudiamos el cdigo, observamos que la parte superior del cuadrado est msalejada del observador que la inferior, pero como se explic en el apartado relativo alas proyecciones, esto no se tiene en cuenta para la proyeccin ortogrfica. Siqueremos que esto se refleje, tendremos que crear una proyeccin perspectiva...Para ello vamos a sustituir la llamada a glOrtho por una llamada a gluPerspective, queestablecer el modo de visualizacin en perspectiva:

    gluPerspective(60.0,1.0,1.0,100.0);// Proyeccin perspectiva. El ngulo de visualizacin es de 60grados, la razn ancho/alto es 1 (son inguales), la distanciamnima es z=1.0, y la distancia mxima es z=100.0

    24 ESIDE Ghost

  • Captulo 3: Conceptos bsicos sobre OpenGL Curso de introduccin a OpenGL (v1.0)

    Guardamos como quadpersp.c, compilamos y ejecutamos:user@machine:$gcc quadpersp.c -lglut lGL -lGLU -o quadperspuser@machine:$./ quadpersp

    Y nos encontramos con que no se ve nada! Que no cunda el pnico... todo tienesentido... tal y como est todo planteado, el cuadrado se va a dibujar con centro en elorigen de coordenadas... pero dnde est el observador? En la visualizacinperspectiva, la posicin del observador determina cmo se ven las cosas... vamos atomar que el observador, ya que no hemos indicado lo contrario, se encuentra en laposicin (0,0,0). Vamos a retrasar un poco el cuadrado, para alejarlo del observador,porque sino, se dibuja justo en el mimo lugar que ste, y no puede verse nada... paraello, despus de entrar en el modo de modelado/visualizacin, aadimos:

    glTranslatef(0.0,0.0,-2.0);// Alejamos el cuadrado del observador dos unidades en el eje Z

    Guardamos, compilamos, ejecutamos y...

    Figura 3.10. Salida del programa quadpersp

    ...perfecto! La parte superior del tringulo se dibuja alejada del observador :-D

    3.5.3 Ocultacin de objetos (Z-Buffer)Si aadimos en el cdigo de visualizacin un tringulo con las coordenadas(0.0,0.5,0.0), (-0.7,-0.5,0.0),(0.7,-0.5,0.0), despus del codigo de dibujado del

    2003 - Jorge Garca (Bardok) 25

  • Curso de introduccin a OpenGL (v1.0) Primer contacto con OpenGL

    cuadrado, la salida es la siguiente:

    Figura 3.11. Dibujado sin Z-Buffer

    Como podemos observar, no se tiene en cuenta que la parte inferior del tringulodebera de estar tapada por el cuadrado, porque su coordenada Z, que indica laprofundidad, es mayor (-0.5 para el cuadrado y 0 para el tringulo). Para podervisualizar los objetos con oclusin, tenemos que activar el Z-Buffer.

    El Z-Buffer es un array que guarda la profundidad (coordenada Z) para todos los pxelsdel rea de dibujado, de manera que cuando un pxel va a ser dibujado, se mira si sucoordenada Z es menor que la coordenada en el Z-Buffer para ese pxel en pantalla.Para activarlo, hemos de aadir las siguientes lneas de cdigo, antes del dibujado:

    glDepthFunc(GL_LEQUAL);glEnable(GL_DEPTH_TEST);glClearDepth(1.0);

    Con la llamada a glEnable(GL_DEPTH_TEST) habilitamos la comprobacin de laprofundidad en el dibujado.Con glDepthFunc(GL_LEQUAL) decimos que el nuevo pxel se dibuje si su coordenadaZ es ms cercana al punto de visualizacin, o igual, que la que hay actualmente en Z-Buffer.Con glClearDepth(1.0) decimos que cada vez que quedamos borrar el buffer deprofundidad, se inicialicen sus posiciones al valor 1.0.Junto con esto, al borrar la pantalla, le indicamos al programa que inicialice el Z-Buffercon:

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    26 ESIDE Ghost

  • Captulo 3: Conceptos bsicos sobre OpenGL Curso de introduccin a OpenGL (v1.0)

    Finalmente, slo nos queda indicar al programa que, cuando se cree la ventana, sereserve espacio para el Z-Buffer. Esto lo indicamos al crear la ventana con:

    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);

    Tras estos cambios, la salida del programa es la siguiente:

    Figura 3.12. Dibujado con Z-Buffer (salida del programazbuffer-yes)

    3.5.4 Una jerarqua sencillaYa hemos visto los conceptos bsicos para dibujar figuras en OpenGL, ahora vamos ajugar un poco con transformaciones y matrices...Vamos a dibujar una especie de figura humanoide, con un cuerpo (un cubo), dosbrazos (compuestos por tres partes, brazo, antebrazo y manos, con dos cilindros y uncubo respectivamente) dos piernas (similares a los brazos) y una cabeza (una esfera).Las figuras geomtricas las vamos a dibujar mediante funciones de la librera GLUT.El cdigo para el dibujado es el siguiente:1. Primero alejamos la cmara

    glTranslatef(0,0,-16.0);2. Situamos el cuerpo y lo dibujamos. Como queremos dibujar el cuerpo con un cubo,

    vamos a hacer que en el eje Y sea ms grande que en el Z, y en el X un poco ms...para ello lo escalamos. Pero este escalado slo debe de afectar al cuerpo, por lotanto, despus de dibujar el cuerpo, desharemos el escalado, utilizandoglPushMatrix y glPopMatrix. Las medidas del cuerpo, las definimos como

    2003 - Jorge Garca (Bardok) 27

  • Curso de introduccin a OpenGL (v1.0) Primer contacto con OpenGL

    constantes:glTranslatef(0,BODY_HEIGHT/2,0);glPushMatrix();

    glScalef(BODY_WIDTH,BODY_HEIGHT,BODY_LENGTH);glColor3f(0.0,0.3,0.8);glutSolidCube(1);

    glPopMatrix();3. A partir del centro del cuerpo, situamos el brazo derecho. Hay que tener en cuenta

    que un cubo se dibuja partir de su centro. Despus vamos a rotar el brazo 30 gradosalrededor del eje Z... si lo giramos directamente, estaremos girando el brazo por elcentro... pero un brazo gira por su parte superior... para ello, trasladamos el pivotede giro a la parte superior del brazo, lo giramos, y devolvemos el pivote a su sitio,aplicamos el escalado, y ya podemos dibujar el brazo a partir de un cubo. Paradibujar la mano, trasladamos hacia abajo, aplicamos el escalado, y dibujamos. En lamano, no hemos aplicado el pushMatrix, porque su escalado no va a afectar a nadaque se dibuje despus, pero en caso contrario, deberamos deshacerlo.

    glPushMatrix();glTranslatef(-(BODY_WIDTH)/2,(BODY_HEIGHT-ARM_HEIGHT)/2,0);glTranslatef(0,ARM_LENGTH/2,0);glRotatef(-30,0,0,1);glTranslatef(0,-ARM_LENGTH/2,0);glPushMatrix();

    glScalef(ARM_WIDTH,ARM_HEIGHT,ARM_LENGTH);glutSolidCube(1);

    glPopMatrix();// ya tenemos el brazo... la manoglTranslatef(0,-(ARM_HEIGHT+ARM_WIDTH)/2,0);glColor3f(1,0.6,0.6);glScalef(ARM_WIDTH,ARM_WIDTH,ARM_LENGTH);glutSolidCube(1);

    glPopMatrix();4. Dibujamos el resto del cuerpo de manera anloga (ver cdigo fuente en el anexo).5. Finalmente, dibujamos la cabeza, como una esfera:

    glColor3f(1,0.6,0.6);glPushMatrix();

    glTranslatef(0,BODY_HEIGHT/2 + HEAD_RADIUS*3/4,0);glutSolidSphere(HEAD_RADIUS,10,10);

    glPopMatrix();El resultado del programa es el siguiente:

    28 ESIDE Ghost

  • Captulo 3: Conceptos bsicos sobre OpenGL Curso de introduccin a OpenGL (v1.0)

    Figura 3.13. Salida del programa "simpleguy"

    Vamos a estudiar ms detalladamente el giro del brazo, ya que puede resultar difcil dever:

    Figura 3.14. Rotacin del brazo (simpleguy)

    2003 - Jorge Garca (Bardok) 29

    1 2

    3 4

  • Curso de introduccin a OpenGL (v1.0) Primer contacto con OpenGL

    En el primer recuadro, tenemos el cuerpo junto con el brazo, sin rotar. Desplazamos elbrazo de manera que su centro de giro se encuentre en la poscin sobre la queoriginalmente queramos pivotar el brazo. Giramos el brazo el ngulo deseado, y ahora,con ese giro desplazamos el brazo hacia abajo, segn su eje de coordenadas, lamisma distancia que lo habamos desplazado antes.

    30 ESIDE Ghost

  • Captulo 4: Animaciones Curso de introduccin a OpenGL (v1.0)

    Captulo 4: Animaciones

    Cabe canem (proverbio latino)

    En este captulo vamos a describir de manera muy breve cmo animar las escenas quecreamos con OpenGL.En un principio, animar una figura es algo muy sencillo. Basta con:1. actualizar los datos de la figura2. borrar la pantalla3. dibujar la figura 4. volver al punto 1

    4.1 Los vectores para animar figurasEn muchos casos, dependiendo del tipo de animacin, es muy recomendable el uso devectores para representar hacia dnde se mueve un objeto y con qu velocidad.Imaginemos que tenemos un objeto que se mueve a lo largo del eje X, a la velocidad de 1unidad por frame, y que actualmente est en la posicin (-3,3,0).Podemos representar que el objeto se encuentra situado por un vector de traslacin (-3,3,0), de esta manera:

    2003 - Jorge Garca (Bardok) 31

  • Curso de introduccin a OpenGL (v1.0) Los vectores para animar figuras

    Figura 4.1. Representacin de laposicin y velocidad con vectores

    P es el vector de poscin, y V el de direccin. Si despus de dibujar un frame, sumamos alvector de poscin el de direccin, tenemos que en el siguiente frame el vector de poscinser P(-2,3,0), con lo que la figura habr avanzado por el eje X a la velocidad antesespecificada.Si queremos cambiar el movimiento, podemos variar la direccin del vector V, con lo quese modificar la direccin del movimiento, o su mdulo, con lo que se modificar lavelocidad del movimiento.Vamos con un ejemplo. El programa que vamos a elaborar va a consistir en una esferaque se va a mover dentro de un cubo, de manera que cuando llegue a una de las paredesva a rebotar:

    Figura 4.2. Comportamientodel programa "rebotes"

    El esquema del dibujado ser el siguiente: Comprobar que la esfera no est en el lmite del cubo

    S est: invertir la componente del vector de direccin correspondiente al lado con elque ha rebotado (p. ej. si hemos llegado al lmite por la derecha, el valor de la X sevolver negativo...)

    Sumar el vector de direccin al vector de posicin de la esfera Dibujar la esfera Volver al comienzo del buclePara este programa vamos a definir una clase que se encargue de representar la esfera, y

    32 ESIDE Ghost

    P(-3,3,0)

    V(1,0,0)

  • Captulo 4: Animaciones Curso de introduccin a OpenGL (v1.0)

    que guardar su posicin y velocidad. Los mtodos que proporciona esta clase sedefinene en la siguiente tabla:

    Mtodos FuncinTsphere (float maxpos, floatspeed);

    Crea una instancia de la clase. La esferarebotar si llega a la poscin +-maxpos, ytendr una velocidad speed. Su situacin ydireccin iniciales son aleatorias.

    void test(); Comprueba que la figura est dentro de losmrgenes, y si no le est, corregir su direccin.Despus, actualiza su poscin

    void modifySpeed(float inc); Incrementa la velocidad en incfloat * getPosv(); Obtiene un vector con la poscin de la esfera

    (en la posicin 0, la coord. X, en la 1 la Y y en la2 la Z)

    Tabla 4.1. Mtodos de la clase TSpherePara las animaciones vamos a utilizar varias funciones de GLUT. Por un lado,glutDisplayFunc(), que como ya hemos visto, dibuja un frame, y glutIdleFunc(), queespecifica la operacin que se realizar entre dos frames. Adems, agruparemos todaslas llamadas a OpenGL previas al dibujado de cualquier frame en una funcin deinicializacin.Con esto, el cdigo quedar de la siguiente manera:Vamos a utilizar una variable global para indicar la posicin de la esfera, y otra paraapuntar a la propia esfera:

    float * pos;TSphere * sphere;

    La inicializacin de OpenGL la vamos a realizar en una funcin aparte:void initgl(){glEnable(GL_DEPTH_TEST);glClearColor(0.0,0.0,0.0,0.0);

    glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(60.0,1.0,1.0,100.0);

    sphere = new TSphere(5,1);

    glMatrixMode(GL_MODELVIEW);gluLookAt(3,3,14,0,0,0,0,1,0);}

    En esta inicializacin vamos a hacer todo lo relativo a OpenGL que slo tiene que hacerseuna nica vez: establecer el color de fondo, habilitar el modo de perspectiva, alejar lacmara, y de paso, crear la esfera, que se va a mover en el rango [-5,5] con una velocidadde 1. Para alejar la cmara, utilizaremos la funcin gluLookAt. Esta funcin posiciona lacmara, ahorrando la realizacin de giros y traslaciones manuales, de la siguientemanera: recibe tres ternas: la poscin de la cmara en el espacio, la posicin hacia la queest mirando, y un vector que seala a la parte superior de la escena... en este caso:

    2003 - Jorge Garca (Bardok) 33

  • Curso de introduccin a OpenGL (v1.0) Los vectores para animar figuras

    Figura 4.3. Posicin de la cmara en elejemplo "sphere-rebotes"

    La cmara se situa por delante, y ligeramente por encima del eje de coordenadas, y algodesplazada en el eje X. Est mirando hacia el centro de coordenadas, y la parte superiorde la escena est apuntada por el vector top.La siguiente funcin ser la funcin de dibujado de cada frame, su cuerpo ser elsiguiente:

    void display(void){

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glColor3f(1.0,1.0,1.0);glutWireCube(10);glPushMatrix();

    glColor3f(0.0,0.0,1.0);pos = sphere->getPosv();glTranslatef(pos[0],pos[1],pos[2]);glutSolidSphere(1,10,10);

    glPopMatrix();glFlush();

    }Por cada frame, se borra la pantalla, se dibuja el cubo, se dibuja la esfera (deshaciendo sutransformacin, para no tener que rehacer la transformacin de la cmara en cadapasada).Finalmente vamos a crear una funcin llamada idle que va a ejecutar la actualizacin dela esfera entre dos frames, y va a esperar 33 milisegundos para dibujar el siguientefotograma:

    void idle(void){

    sphere->test();usleep(33);glutPostRedisplay();

    }La ltima llamada a glutPostRedisplay() hace que tras la actualizacin se dibuje elsiguiente frame.Para registrar estas funciones hacemos, en el programa principal:

    initgl();glutDisplayFunc(display);glutIdleFunc(idle);

    Pero si ejecutamos el programa, vemos un pequeo problema al visualizar: hay parpadeo

    34 ESIDE Ghost

    Top

  • Captulo 4: Animaciones Curso de introduccin a OpenGL (v1.0)

    (flickering). Esto se debe a que la pantalla est continuamente borrndose (se pone anegro) y redibujando la imgen. Para que esto no ocurra hemos de utilizar el llamadodoble buffering.

    4.2 El doble bufferingEl doble buffering es una tcnica muy simple, que dibuja la escena en un buffer fuera de lapantalla, mientras que la imgen de la pantalla no se toca para nada. Una vez que laimgen se ha dibujado en el buffer de fondo, se intercambia por el de la pantalla, demanera que eliminamos el parpadeo. El siguiente frame lo dibujaremos en lo que antesera el buffer de pantalla (ahora oculto), y luego se cambiar, y as sucesivamente.Activar el doble buffering es algo muy sencillo. Hemos de indicar a GLUT que vamos autilizar doble buffering al crear la pantalla con GLUT_DOUBLE, en lugar deGLUT_SINGLE:

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);Y despus de dibujar un frame hemos de cambiar el buffer oculto por el activo con:

    glutSwapBuffers();

    Una vez aadido esto, el cdigo quedara como el que se encuentra en el anexo.El resultado del programa es el siguiente:

    Figura 4.4. Salida del programa "sphere-rebotes"

    Y con una pequea modificacin (sphere-rebotes-multi) podemos conseguir una locuracomo esta:

    2003 - Jorge Garca (Bardok) 35

  • Curso de introduccin a OpenGL (v1.0) El doble buffering

    Figura 4.5. Salida del programa "sphere-rebotes-multi"

    36 ESIDE Ghost

  • Captulo 5: Iluminacin Curso de introduccin a OpenGL (v1.0)

    Captulo 5: Iluminacin

    Ratones: Los roedores durante muchosaos han estado "compartiendo" elalimento del hombre, son omnvoros,aunque muestran preferencia por lassemillas de los cereales y productosderivados. Cuando stas faltan puedencomer las cosas ms extraas que nospodamos imaginar : jabn, cuero, cera,plsticos o papel etc(www.amezdy.com/ratones.htm)

    La iluminacin nos permitir crear escenas ms realistas con OpenGL. Cada implementacinde OpenGL puede mantener un nmero de luces mayor o igual a 8 (nunca menor), aunqueno se recomienda abusar de stas, ya que el consumo de CPU por la utilizacin de luces esmuy grande.

    5.1 El modelo de iluminacin en OpenGLLa iluminacin de OpenGL se basa en luces y materiales. Una luz es una fuente deiluminacin para la escena. Emite un haz de luz de un color determinado, dividido en lastres componentes de color RGB. Un material determina la cantidad de cada color querefleja un objeto determinado.Por ejemplo, si un objeto tiene un material de color rojo -RGB(1,0,0)-, es decir, refleja todoel color rojo, y es iluminado por una luz blanca -RGB(1,1,1)-, reflejar toda la componentede color rojo, pero nada de la verde y azul, por lo que se ver de color rojo. Si este mismoobjeto fuese iluminado por una luz verde -RGB(0,1,0)-, se vera de color negro, al no tenernada de luz roja que poder reflejar. Adems, dependiendo del tipo de luz, el color final conel que se vea el objeto puede verse afectado por el ngulo de incidencia de la luz, ladistancia a esta, etc.

    2003 - Jorge Garca (Bardok) 37

  • Curso de introduccin a OpenGL (v1.0) El modelo de iluminacin en OpenGL

    5.1.1 LucesComo se ha dicho, una luz aporta iluminacin a una escena, segn unas determinadascomponentes de color.A partir de ahora distinguiremos entre fuente de luz, como entidad que proporciona luza una escena, y luz, como aportacin de esa fuente a la iluminacin de la escena.Una fuente puede emitir tipos diferentes de luz, que son complementarias, y puedendarse a la vez para un cierto tipo de luz.Los tipos de luz son:

    Emitted (emitida): es la luz emitida por un objeto. No se ve afectada por ningnotro tipo de luz. Por ejemplo, un fuego emite una determinada luz, y si lo miramos, loveremos de ese color, independientemente del color de las luces que estnapuntando al fuego.

    Diffuse (difusa): es la luz que indice sobre un objeto, y proviene de un determinadopunto. La intensidad con la que se refleja en la superficie del objeto puede dependerdel ngulo de incidencia, direccin, etc. Una vez incide sobre un objeto se refleja entodas direcciones.

    Specular (especular): es la luz que, al incidir sobre un objeto, se ve reflejada conun ngulo similar al de incidencia. Podemos pensar que es la luz que produce losbrillos.

    Ambient (ambiental): podemos considerarlo como los restos de luz que aparecendefido a la reflexin residual de una luz que ya se ha reflejado sobre muchosobjetos, y es imposible determinar su procedencia. Es algo as como la iluminacinglobal de una escena.

    5.1.2 MaterialesUn material define, para un determinado objeto, qu componentes refleja de cada tipode luz.Por ejemplo, un plstico rojo, emitir toda la componente roja de las luces ambiental ydifusa, pero generalmente emitir brillos de color blanco bajo una luz blanca, por lo quesu componente especular ser de color blanco. De este modo, la componente deemisin ser negra, puesto que un plastico no emite luz (aunque si es un plsticoradioactivo, puede emitir un leve destello fantasmal ;-)En un modelo con iluminacin, el color de un objeto se define por su material, no por elcolor de sus vrtices, tal y como hemos visto hasta ahora.

    5.1.3 NormalesLa iluminacin en OpenGL se calcula a nivel de vrtice, es decir, por cada vrtice, secalcula su color a partir del material activo, las luces activas, y cmo estas lucesinciden sobre el vrtice. Para saber cmo incide una luz sobre un vrtice, empleamosla normal del vrtice, un vector, que, generalmente, ser perpendicular a la cara queestemos dibujando, aunque podremos variarlo para conseguir distintos efectos.En la figura, podemos ver cmo incide la misma luz en el mismo objeto, pero con lasnormales cambiadas.

    38 ESIDE Ghost

  • Captulo 5: Iluminacin Curso de introduccin a OpenGL (v1.0)

    Figura 5.1. Efecto de las normales en la iluminacin

    5.2 Utilizando iluminacin en OpenGL

    5.2.1 LucesEl primer paso para utilizar la iluminacin en una aplicacin OpenGL es activarla,mediante la llamada

    glEnable(GL_LINGHTING);Una vez activada, hemos de establecer las propiedades de cada luz en la escena, yactivarlas. La especificacin inicial de OpenGL comtempla que, al menos, cadaimplementacin debe de poder definir 8 luces, identificadas por las constantesGL_LIGHTn, dnde 'n' es el nmero de la luz, comenzando por 0.Para establecer las propiedades de una luz utilizaremos llamadas a las funciones deltipo glLight*(). Las propiedades de toda luz son las siguientes:

    Posicin/Direccin:Indica la posicin/direccin de la luz, y especifica si sta es una luz posicional odireccional. Una luz posicional tiene una posicin concreta en el espacio, mientrasque una luz direccional consiste en un conjunto de haces de luz paralelos. Unejemplo de luz posicional es una lampara, mientras que, debido a su distancia,podramos considerar al sol como una fuente de luz direccional. Las lucesposicionales pueden ser de dos tipos: luces puntuales, que emiten luz a sualrededor de manera radial, y en todas direcciones, y luces focales, que emiten luzen una direccin concreta, en un radio de accin con forma de cono (como un foco).Podemos ver los diferentes tipos de luces en la siguiente figura:

    2003 - Jorge Garca (Bardok) 39

    Luz Luz

  • Curso de introduccin a OpenGL (v1.0) Utilizando iluminacin en OpenGL

    Figura 5.2. Tipos de lucesPara establecer esta propiedad utilizaremos la llamada:

    glLightfv(GL_LIGHTn,GL_POSITION,val_ptr);val_prt es un puntero a un vector de cuatro componentes de tipo float, de la forma(x,y,z,w). En el caso de que w sea 1, estaremos ante una luz posicional, y suposcin est determinada por (x,y,z). Si w es 0, la luz es direccional, y su direccines el vector (x,y,z).

    Direccin del foco:En el caso de una luz focal, debemos establecer su direccin. Esto lo haremos conla llamada:

    glLightfv(GL_LIGHTn,GL_SPOT_DIRECTION,val_prt);val_ptr es un puntero a un vector con la direccin, en formato (x,y,z).

    Apertura del foco:El ngulo de apertura del foco se define mediante:

    glLightf(GL_LIGHTn,GL_SPOT_CUTOFF,val);val expresa en grados la mitad del ngulo de apertura del foco.

    Atenuacin del foco:La atenuacin del foco (degradacin de la intensidad a medida que nos acercamosal borde) se define mediante:

    glLightf(GL_LIGHTn,GL_SPOT_EXPONENT,val); Intensidad de la luz:

    Define el color ambiental, difuso y especular de la luz. Se define mediante lallamada:

    glLightfv(GL_LIGHTn,GL_[AMBIENT|DIFFUSE|SPECULAR],val_ptr);val_ptr es un puntero a un vector de cuatro componentes de color RGBA.

    Atenuacin de la luzDefine la prdida de intensidad de la luz a medida que nos alejamos del foco (noafecta a las luces direccionales). Se establece mediante:glLightf(GL_LIGHTn,GL_[CONSTANT|LINEAR|QUADRATIC]_ATTENUATION,val);El factor de atenuacin de la luz se calcula segn la frmula:

    1k c

    k l d k q

    2

    40 ESIDE Ghost

    Luz puntual Luz focal Luz direccional

  • Captulo 5: Iluminacin Curso de introduccin a OpenGL (v1.0)

    Una vez establecidas las propiedades de una determinada luz, las activaremos con lallamada:

    glEnable(GL_LIGHTn);

    5.2.2 MaterialesTras definir las luces, antes de dibujar un objeto, hemos de definir su material.Para ello, estableceremos los valores de las diversas caractersticas del mismo,mediante las funciones del tipo glMaterial*(). Estas funciones reciben tres parmetros:1. Caras del polgono a las que se aplica el material. Podemos aplicar el material a la

    cara frontal (GL_FRONT) o a ambas caras del polgono (GL_FRONT_AND_BACK).2. Caracterstica que definimos, mediante su correspondiente constante.3. Valor de la caracterstica.Las diferentes caractersticas son:

    Color del material:Define el comportamiento del material para los distintos tipos de luz descritosanteriormente. El color ambiental, difuso y especular definen los colores delespectro que este material refleja de las luces que recibe. El color emitido es el tipode luminosidad que posee el material, intedependientemente de la luz que le afecte.Se define mediante la llamada:

    glMaterialfv(GL_FRONT[_AND_BACK],[GL_AMBIENT|GL_DIFUSSE|GL_AMBIENT_AND_DIFUSSE|GL_SPECULAR],val_ptr);

    val_ptr es un puntero a un conjunto de valores RGBA que especifica el color de lacomponente especfica.Como antes se ha comentado, es habitual que el comportamiento ante la luz difusay la ambiental sea el mismo, por lo que es posible establecer ambos al mismotiempo.

    Brillo de los reflejos:La intensidad del brillo puede definirse a travs de la llamada:

    glMaterialf(GL_FRONT[_AND_BACK],GL_SHININESS,val);Adems, podemos cambiar alguno de los valores establecidos para los colores de unmaterial mediante la funcin glColorMaterial(). Mediante esta funcin, que debemosactivar, podemos cambiar alguno de los colores del material.Esta opcin se activa mediante:

    glEnable(GL_COLOR_MATERIAL);y una vez activada, establecemos la propiedad que queremos cambiar mediante:

    glColorMaterial(GL_FRONT[_AND_BACK],[GL_AMBIENT|GL_DIFUSSE|GL_AMBIENT_AND_DIFUSSE|GL_SPECULAR]);

    y cambiamos el color reflejado de ese tipo de luz mediante, por ejemplo:glColor3f(r_val,g_val,b_val);

    Para evitar complicaciones, debemos desactivar esta opcin al terminar de usarla.Veremos la utilidad de esta opcin algo ms adelante, con un ejemplo.

    2003 - Jorge Garca (Bardok) 41

  • Curso de introduccin a OpenGL (v1.0) Utilizando iluminacin en OpenGL

    5.2.3 Ejemplo: iluminacin direccional sobre una superficieVamos a ver cmo se ha realizado el ejemplo con el que comprobamos el efecto de lasnormales sobre la iluminacin.Inicialmente vamos a definir una serie de arrays para los colores que vamos a emplear:El color ambiental y difuso del material:

    GLfloat mat_color [] = {0.0,1.0,1.0,1.0};El color difuso y especular de la luz:

    GLfloat light_color [] = {1.0,1.0,1.0,1.0};El color ambiental de la luz (si algo est fuera de la luz, no es iluminado):

    GLfloat light_ambient [] = {0.0,0.0,0.0,1.0};El valor de las normales (como el cuadrado est en el plano (x,z), las normales vanhacia arriba).

    GLfloat normal [] = {0.0,1.0,0.0};El valor de la direccin de la luz (es una luz situada en el eje Y, en el infinito, luego susrayos irn hacia abajo en el eje Y):

    GLfloat light_dir [] = {0.0,1.0,0.0,0.0};Seleccionamos el color de fondo, y borramos la pantalla:

    glClearColor(0.0,0.0,0.0,0.0);glClear(GL_COLOR_BUFFER_BIT);

    Activamos la luz, y sus caractersticas, excepto la direccin:glEnable(GL_LIGHTING);

    glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);glLightfv(GL_LIGHT0,GL_DIFFUSE,light_color);glLightfv(GL_LIGHT0,GL_SPECULAR,light_color);glEnable(GL_LIGHT0);

    Seleccionamos el color del material:glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_color);

    Establecemos la perspectiva y posicionamos al observador:glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(60.0,1.0,1.0,100.0);

    glMatrixMode(GL_MODELVIEW);glTranslatef(-0.3,-0.6,-4.0);

    Establecemos la direccin de la luz:glLightfv(GL_LIGHT0,GL_POSITION,light_dir);

    Esta direccin la establecemos despus de la transformacin de la cmara, porquequeremos que, en este caso, est tambin sometida a la transformacin de la cmara(por ejemplo, si dibujamos una lampara, su posicin en la escena ser relativa a dndeest el espectador de la escena).Dibujamos el cuadrado, y antes de cada vertice, establecemos su normal. En el casode que el smbolo SINGLE_NORMAL est definido, la normal ser siempre la misma.En caso contrario, los vrtices 1 y 3 tendrn una normal distinta, para lograr el efectoque se muestra en la figura 5.1:

    glBegin(GL_QUADS);

    42 ESIDE Ghost

  • Captulo 5: Iluminacin Curso de introduccin a OpenGL (v1.0)

    #ifdef SINGLE_NORMALglNormal3fv(normal);

    #elseglNormal3f(1.0,1.0,-1.0);

    #endifglVertex3f(-1.0,0.0,-1.0);

    glNormal3fv(normal);glVertex3f(-1.0,0.0,1.0);

    #ifdef SINGLE_NORMALglNormal3fv(normal);

    #elseglNormal3f(-1.0,1.0,-1.0);

    #endifglVertex3f(1.0,0.0,1.0);glNormal3fv(normal);glVertex3f(1.0,0.0,-1.0);

    glEnd();Finalmente, forzamos el dibujado, esperamos, y salimos del programa:

    glFlush();

    sleep(20);exit(0);

    5.2.4 Ejemplo: moviendo un foco alrededor de una esferaEn este ejemplo vamos a mover un foco alrededor de una esfera, y vamos a ver cmoafectan los distintos tipos de luz. Para ello utilizaremos dibujado con doble buffer, yzBuffer.El dibujado se har de este modo:

    Inicialmente definimos las caractersticas de la luz:float light_ambient [] = {0.0,0.2,0.0,1.0};float light_diffuse_specular [] = {0.8,0.8,0.8,1.0};float light_pos [] = {0.0,0.0,2.0,1.0};float spot_dir [] = {0.0,0.0,-1.0};float spot_cutoff = 30.0;float spot_exponent = 1.0;

    Las caractersticas del material de la esfera:float mat_ambient_diffuse [] = {0.0,0.8,1.0,1.0};float mat_specular [] = {0.7,0.0,0.0,1.0};float mat_emission [] = {0.0,0.0,0.0,1.0};float mat_shininess = 0.4;

    Vamos a poner un pequeo cono cuyo material tenga una emisin similar al colorde la luz, que nos indicar dnde est el foco. Este es su color de emisin:

    float focus_emission [] = {0.8,0.8,0.8,1.0}; Definimos un par de variables que indican la rotacin del foco:

    float rot_angle_y = 0.0;float rot_angle_x = 0.0;

    Habilitamos el zBuffer y establecemos el color de fondo:glEnable(GL_DEPTH_TEST);

    2003 - Jorge Garca (Bardok) 43

  • Curso de introduccin a OpenGL (v1.0) Utilizando iluminacin en OpenGL

    glClearColor(0.0,0.0,0.0,0.0); Activamos las luces y sus caractersticas. La primera llamada establece que las

    caras traseras de los polgonos no se iluminarn:glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_FALSE);glEnable(GL_LIGHTING);glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse_specular);glLightfv(GL_LIGHT0,GL_SPECULAR,light_diffuse_specular);glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,spot_cutoff);glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,spot_exponent);glEnable(GL_LIGHT0);

    Establecemos el material de la esfera:glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_ambient_diffuse);glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);glMaterialf(GL_FRONT,GL_SHININESS,mat_shininess);

    Establecemos la perspectiva y trasladamos la cmara:glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(60.0,1.0,1.0,100.0);

    glMatrixMode(GL_MODELVIEW);glTranslatef(0.0,0.0,-5.0);

    Todos los pasos anteriores se engloban en lo que sera la funcin de inicializacin. A continuacin tenemos el bucle de dibujado (glutDisplayFunc). En l, una vez

    borrada la pantalla, rotamos la luz, la posicionamos, y establecemos su direccin,que sern relativas a su rotacin. Despus, dibujamos un cono en la posicin de laluz. Este cono tendr como color de emisin el definido como tal. El cambio lohacemos con glColorMaterial(). Una vez dibujado, deshacemos estastransformaciones, dibujamos la esfera, dibujamos y cambiamos los buffers:

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glPushMatrix();

    glRotatef(30.0,0.0,0.0,1.0);glRotatef(rot_angle_y,0.0,1.0,0.0);glRotatef(rot_angle_x,1.0,0.0,0.0);glLightfv(GL_LIGHT0,GL_POSITION,light_pos);glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,spot_dir);

    glTranslatef(light_pos[0],light_pos[1],light_pos[2]);glColorMaterial(GL_FRONT,GL_EMISSION);glEnable(GL_COLOR_MATERIAL);

    glColor4fv(focus_emission);glutSolidCone(0.2,0.5,7,7);glColor4fv(mat_emission);

    glDisable(GL_COLOR_MATERIAL);glPopMatrix();glutSolidSphere(1.0,20,20);glFlush();glutSwapBuffers();

    Finalmente, definimos que, entre frame y frame (glutIdleFunc), la accin a realizarser actualizar la rotacin del foco:

    rot_angle_y = (rot_angle_y > 360.0)?0:rot_angle_y + ROT_INC;rot_angle_x = (rot_angle_x > 360.0)?0:rot_angle_x +

    44 ESIDE Ghost

  • Captulo 5: Iluminacin Curso de introduccin a OpenGL (v1.0)

    ROT_INC/(2*3.1416);glutPostRedisplay();

    Y aqu tenemos un frame de la animacin que hemos creado:

    Figura 5.3. Salida del programa "lit-sphere"

    Un efecto curioso es el hecho de observar los reflejos de color rojo que se emitendesde los bordes de la esfera, gracias a que hemos definido este color como el colorespecular del material.Como puede observarse, en todos estos ejemplos hay gran cantidad de trozos decdigo que se repiten. Por ello, es conveniente la agrupacin de estas llamadas enfunciones de motores grficos.

    5.2.5 Ejercicio propuestoComo final de este captulo se propone un ejercicio, consistente en una modificacindel programa sphere-rebotes-multi, de manera que la escena est iluminada por unaluz direccional, blanca, situada en el infinito, en una posicin apuntada por el vector(1,1,1), y cada esfera tenga su propio color (aleatorio) definido por las caractersticasambiental y difusa del material. El cubo no debe de verse afectado por la luz aldibujarse.El resultado debera de ser parecido al siguiente:

    2003 - Jorge Garca (Bardok) 45

  • Curso de introduccin a OpenGL (v1.0) Utilizando iluminacin en OpenGL

    Figura 5.4. Salida del programa "l-sphere-rebotes-multi"

    Una solucin a este ejercicio aparece en el anexo A, bajo el epgrafe l-sphere-rebotes-multi.cpp.

    46 ESIDE Ghost

  • Captulo 6: Texturas Curso de introduccin a OpenGL (v1.0)

    Captulo 6: Texturas

    T me das cremita, yo te doycremita... (La cancin del verano...)

    Las texturas permiten personalizar an ms el material de un objeto, y nos permiten obtenerimgenes mucho ms realistas en nuestras escenas. Por ejemplo, si queremos dibujar unapared de ladrillo, tenemos dos opciones: dibujar cada ladrillo, definiendo su material concolores, y dibujar el cemento entre los ladrillos, a base de polgonos, definiendo tambin sumaterial, o dibujar un nico cuadrado con la extensin de la pared, y hacer que su material,sea, por ejemplo, la foto de una pared de ladrillo.

    6.1 Las coordenadas de texturaPara saber qu partes de una imgen se dibujan en un polgono (por ejemplo untringulo), utilizamos lo que se denominan coordenadas de textura, o coordenadas UV.Estas coordenadas estn representadas por nmeros reales de 0 a 1, de la siguientemanera:

    Figura 6.1. Coordenadas detextura

    2003 - Jorge Garca (Bardok) 47

    (0,1) (1,1)

    (0,0) (1,0)

  • Curso de introduccin a OpenGL (v1.0) Las coordenadas de textura

    De esta manera, si queremos dibujar un tringulo con una textura, y aplicacamos a cadavrtice las coordenadas de textura indicadas en la figura, tenemos el siguiente resultado:

    Figura 6.2. Mapeado de textura

    6.2 Aplicar las texturasPara aplicar una textura tenemos que seguir una serie de pasos muy definidos:1. Creamos la textura2. Definimos las condiciones en que se va a aplicar la textura3. Habilitar la aplicacin de texturas4. Dibujar las escenas, proporcionando las coordenadas de texturaComo ejemplo sencillo, vamos a ir viendo cmo se ha creado el ejemplo del mapeado detexturas: Creacin de la textura [TEXT]:

    Primero hemos de obtener un identificador para la textura. Para ello pedimos aOpenGL que nos devuelva un identificador de textura libre:

    int texture;glGenTextures(1,&texture);

    Activamos la textura como textura activa:glBindTexture(GL_TEXTURE_2D,texture);

    Creamos la textura. El modo ms sencillo de hacerlo es a travs de una funcin deGLU que crea la textura y sus variaciones a aplicar segn la distancia a la que seencuentre:

    gluBuild2DMipmaps( GL_TEXTURE_2D, gimp_image.bytes_per_pixel,gimp_image.width, gimp_image.height,GL_RGB, GL_UNSIGNED_BYTE,gimp_image.pixel_data );

    Con el primer parmetro indicamos el tipo de textura. En este caso(GL_TEXTURE_2D) es una textura 2D. Los siguentes parmetros indican el nmero debytes por cada pixel, que dependern de la imgen (p. ej. 3 para RGB y 4 para RGBA;en este caso, la imgen es de tipo RGB), su anchura y altura (que han de ser pares, ymuy recomendable, mltiplos de 2), el formato de los datos (GL_RGB, GL_RGBA,...), eltipo de los datos, que en nuestro caso vendr dado por bytes sin signo, por lo queusaremos la constante GL_UNSIGNED_BYTE, y finalmente, un puntero a los datos.En este ejemplo, hemos utilizado una estructura para generar la imgen con elsiguiente formato:

    48 ESIDE Ghost

    (0,1) (1,1)

    (0,0) (1,0)

    (0,1) (1,1)

    (0.5,0)

    + =

  • Captulo 6: Texturas Curso de introduccin a OpenGL (v1.0)

    static const struct { unsigned int width; unsigned int height; unsigned int bytes_per_pixel; /* 3:RGB, 4:RGBA */ unsigned char pixel_data[128 * 128 * 3 + 1];} gimp_image = {128, 128, 3, [...] }

    Este formato de datos es producido de manera automtica por el programa Gimp algrabar una imgen como un archivo en c.

    Definir las condiciones en que se va a aplicar la textura:Estas condiciones se establecen a travs de la funcin glTexEnvf().

    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );En nuestro caso, hemos especificado que la textura se va a fundir con el color de fondodel polgono (GL_MODULATE), aunque bien podra sustituirlo (usando GL_REPLACE).La fusin con el color de fondo se utiliza para aplicar la iluminacin a un objeto contextura. En el ejemplo vemos cmo se visualiza un objeto iluminado, con la texturaaplicada mediante GL_MODULATE, y mediante GL_REPLACE:

    Figura 6.3. Diferencias entre GL_REPLACE y GL_MODULATE Habilitar la aplicacin de texturas:

    Mediante:glEnable(GL_TEXTURE_2D);

    Dibujar la geometra proporcionando las coordenadas de textura de cada vrtice:glBegin(GL_TRIANGLES);

    glTexCoord2d(0.0,1.0);glVertex3f(-0.5,-0.5,0.5);glTexCoord2d(1.0,1.0);glVertex3f(0.5,-0.5,0.5);glTexCoord2d(0.5,0.0);glVertex3f(0.0,0.5,0.5);

    glEnd();Si en algn momento queremos cambiar la textura activa, tan slo hemos de indicar qutextura queremos activar mediante la llamada:

    2003 - Jorge Garca (Bardok) 49

  • Curso de introduccin a OpenGL (v1.0) Aplicar las texturas

    glBindTexture(GL_TEXTURE_2D,texture);texture es el identificador de la textura que queremos activar.El cdigo completo de los ejemplos utilizados puede verse en el anexo A.

    6.2.1 Repeticin de texturasImaginemos que queremos dibujar una pared de ladrillos junto a un cesped, y tenemosestas dos texturas, para la pared y el suelo:

    Figura 6.4. Texturas para suelo y paredEl suelo va a ser u cuadrado, y la pared un rectngulo, y vamos a mapear las esquinasdel suelo y de la pared con las esquinas de de las texturas (cdigo completo en elanexo A):

    glBindTexture(GL_TEXTURE_2D,texture_floor);glBegin(GL_QUADS);

    glTexCoord2d(0.0,0.0);glVertex3f(-6.0,0.0,-6.0);glTexCoord2d(0.0,1.0);glVertex3f(-6.0,0.0,6.0);glTexCoord2d(1.0,1.0);glVertex3f(6.0,0.0,6.0);glTexCoord2d(1.0,0.0);glVertex3f(6.0,0.0,-6.0);

    glEnd();

    glBindTexture(GL_TEXTURE_2D,texture_wall);glBegin(GL_QUADS);

    glTexCoord2d(0.0,0.0);glVertex3f(-6.0,4.0,-6.0);glTexCoord2d(0.0,1.0);glVertex3f(-6.0,0.0,-6.0);glTexCoord2d(1.0,1.0);glVertex3f(6.0,0.0,-6.0);glTexCoord2d(1.0,0.0);glVertex3f(6.0,4.0,-6.0);

    glEnd();Un aspecto a resaltar es que la operacin glBindTexture, para seleccionar cul es latextura activa en este momento, tiene que realizarse fuera del contexto deglBegin/glEnd, o de lo contrario no funcionar.El resultado de dibujar esto es el siguiente:

    50 ESIDE Ghost

  • Captulo 6: Texturas Curso de introduccin a OpenGL (v1.0)

    Figura 6.5. Salida del programa "texture-no-clamp"

    Como podemos observar, los ladrillos de la pared salen demasiado alargados, y elsuelo demasiado distorsionado, por el hecho de que estamos agrandando las texturaspara acomodarlas al tamao de los objetos.Pero, y si repetimos las texturas? Por ejemplo, podramos repetir la textura de la en 3divisiones verticales, y la del suelo 36 veces (6 horizontales x 6 verticales).Para ello, debemos especificar que queremos repetir las texturas con las siguientesllamadas a funcin:

    glTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);glTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);

    La primera permite que las texturas se repitan en horizontal, y la segunda, en vertical.Con este cambio, podramos mapear las texturas con coordenadas mayores a 1, demanera que las texturas se repetiran, de esta manera:

    glBindTexture(GL_TEXTURE_2D,texture_floor);glBegin(GL_QUADS);

    glTexCoord2d(0.0,0.0);glVertex3f(-6.0,0.0,-6.0);glTexCoord2d(0.0,6.0);glVertex3f(-6.0,0.0,6.0);glTexCoord2d(6.0,6.0);glVertex3f(6.0,0.0,6.0);glTexCoord2d(6.0,0.0);glVertex3f(6.0,0.0,-6.0);

    glEnd();

    glBindTexture(GL_TEXTURE_2D,texture_wall);glBegin(GL_QUADS);

    glTexCoord2d(0.0,0.0);glVertex3f(-6.0,4.0,-6.0);glTexCoord2d(0.0,1.0);glVertex3f(-6.0,0.0,-6.0);glTexCoord2d(3.0,1.0);

    2003 - Jorge Garca (Bardok) 51

  • Curso de introduccin a OpenGL (v1.0) Aplicar las texturas

    glVertex3f(6.0,0.0,-6.0);glTexCoord2d(3.0,0.0);glVertex3f(6.0,4.0,-6.0);

    glEnd();La textura de la pared ha sido mapeada entre (0,0) y (3,1), para repetirla 3 veceshorizontalmente, y la textura del suelo entre (0,0) y (6,6). El resultado es sensiblementedistinto:

    Figura 6.6. Salida del programa "texture-yes-clamp"

    52 ESIDE Ghost

  • Captulo 7: Interaccin bsica con GLUT Curso de introduccin a OpenGL (v1.0)

    Captulo 7: Interaccin bsica con GLUT

    'Esto es to..., esto es to..., esto es todoamigos! (Porky)

    Como ltimo apartado, vamos a comentar de manera breve cmo interactuar con lasventanas utilizando GLUT.Ya se ha comentado anteriormente que GLUT trabaja generalmente a travs de funcionesCALLBACK.En la mayor parte de los casos, tendremos que registrar en GLUT a qu funcin queremosque se llame cuando se produzca cierto evento sobre la ventana (pulsacin de una tecla,movimiento del ratn...).

    7.1 Interaccin con el tecladoPara mostrar esto vamos a realizar un ejemplo, consistente en modificar el programa lit-sphere de manera que seamos nosotros quienes controlemos el movimiento de la luz.Esta estar quiera, y cuando toquemos las teclas derecha/izquierda se mover, rotandoalrededor del centro de la esfera, alrededor del eje Y, y cuando pulsemos arriba/abajo, lohar alrededor del eje X.La funcin que nos permite registrar este evento es glutSpecialFunc, que se encarga demanejar la pulsacin de teclas especiales, como los cursores.La declaracin de esta funcin es:

    glutSpecialFunc(void (*func)(int key, int x, int y));Es decir, recibe un puntero a funcin, que no devuelve nada, y recibe tres enteros: la teclapulsada, y la poscin X e Y del ratn en la pantalla.La rotacin alrededor de los ejes X e Y la vamos a controlar mediante dos variablesglobales (rot_angle_x, rot_angle_y).

    2003 - Jorge Garca (Bardok) 53

  • Curso de introduccin a OpenGL (v1.0) Interaccin con el teclado

    El cdigo de la funcin a la que hay que llamar al pulsar alguna tecla especial ser elsiguiente:

    void specialKeys(int key, int x, int y){

    switch (key){

    case GLUT_KEY_UP: rot_angle_x--;break;

    case GLUT_KEY_DOWN: rot_angle_x++;break;

    case GLUT_KEY_RIGHT: rot_angle_y++;break;

    case GLUT_KEY_LEFT: rot_angle_y--;break;

    }glutPostRedisplay();

    }Con esto, modificaremos la rotacin segn la tecla pulsada.Adems, para facilitar la salida del programa, vamos a aadir que, al pulsar la tecla Esc.,el programa termine. Para ello utilizaremos la funcin glutKeyboardFunc(), que recibircomo parmetro un puntero a la siguiente funcin:

    static void keys(unsigned char key, int x, int y){

    switch (key){

    case 27: exit(0);break;

    }glutPostRedisplay();

    }El resto del programa es prcticamente idndico al comentado en el captulo deiluminacin (la funcin idle se hace innecesaria, y hay que dar de alta los dos nuevosmanejadores de eventos aadiendo al programa principal:

    glutSpecialFunc(specialKeys);glutKeyboardFunc(keys);

    7.2 Redimensionado de la ventanaFinalmente, comentaremos que es posible redimensionar la ventana y su contenidomediante la funcin de CALLBACK glutReshapeFunc(), a la que se llama cada vez que laventana cambia de tamao, y que recibe el nuevo tamao de la ventana.En caso de que esto ocurra, tendremos que volver a ajustar la perspectiva (la relacinancho/alto) y establecer el tamao de la nueva ventana de visualizacin:

    void reshape(int width, int height){ GLfloat h = (GLfloat) height / (GLfloat) width;

    glViewport(0, 0, (GLint) width, (GLint) height);

    glMatrixMode(GL_PROJECTION);glLoadIdentity();

    54 ESIDE Ghost

  • Captulo 7: Interaccin bsica con GLUT Curso de introduccin a OpenGL (v1.0)

    gluPerspective(60.0,1.0,1.0,100.0);

    glMatrixMode(GL_MODELVIEW);glLoadIdentity();glTranslatef(0.0,0.0,-5.0);

    glutPostRedisplay();}

    glViewport() nos permitir establecer qu porcin de la ventana ser el rea visualizable.En este caso, establecemos que el rea visualizable ser toda la ventana con su nuevotamao.Adems, vamos a hacer que, al pulsar la tecla f pasemos a pantalla completa/modoventana de manera alternativa.Para ello, aadiremos una variable global que indique el modo actual de la pantalla, y eltratamiento para la pulsacin de la tecla f, que ser:

    case 'f': if (windowed == 1){glutFullScreen(); windowed = 0;}else{

    glutPositionWindow ( 20 , 20 );glutReshapeWindow ( 350,350);windowed = 0;

    }break;

    Si estamos en modo ventana, se pasa a pantalla completa. En caso contrario, sereposiciona y reforma la ventana, para pasar de nuevo a modo ventana.

    2003 - Jorge Garca (Bardok) 55

  • Captulo 8: Recursos de inters Curso de introduccin a OpenGL (v1.0)

    Captulo 8: Recursos de inters

    Por fin... se acab... (Bardok)

    En este ltimo epgrafe, me gustara comentar algunos recursos (libros y pginas web) queconsidero de gran inters: El libro rojo de OpenGL (The Red Book): es un libro bsico para cualquier persona que

    quiera empezar a programar con OpenGL. Tambin se conoce como la biblia deOpenGL.

    The OpenGL Utility Toolkit (GLUT) Programming Interface: contiene todo lonecesario para la utilizacin de la librera GLUT.

    Los tutoriales de nehe (nehe.gamedev.net/): estos tutoriales tienen una grancantidad de informacin destinada, en gran parte, a la programacin de juegos.

    Muchas gracias por tu inters en este curso. Para cualquier duda o sugerencia, no dudesen contactar conmigo en [email protected].

    2003 - Jorge Garca (Bardok) 57

  • Captulo 8: Recursos de inters Curso de introduccin a OpenGL (v1.0)

    Anexo A: Cdigo de los programas de ejemplo

    Ja ja ja! Con este libro, tengo elpoder de controlar hasta los rboles, yla propia ordenacin de todos loselementos...! (Bardok, en 1 decarrera, con el libro de EDA en lamano...)

    A.a myfirstopenglprogram.c#include

    void display(void){

    glClearColor(0.0,0.0,0.0,0.0);glClear(GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);glLoadIdentity();

    glOrtho(-1.0,1.0,-1.0,1.0,-1.0,1.0);

    glMatrixMode(GL_MODELVIEW);

    glBegin(GL_TRIANGLES);glColor3f(1.0,0.0,0.0);glVertex3f(0.0,0.8,0.0);glColor3f(0.0,1.0,0.0);glVertex3f(-0.6,-0.2,0.0);glColor3f(0.0,0.0,1.0);glVertex3f(0.6,-0.2,0.0);

    glEnd();

    2003 - Jorge Garca (Bardok) 59

  • Curso de introduccin a OpenGL (v1.0) Recursos de inters

    glFlush();

    sleep(10);exit(0);

    }

    int main(int argc, char ** argv){

    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);glutInitWindowPosition(20,20);glutInitWindowSize(500,500);glutCreateWindow(argv[0]);

    glutDisplayFunc(display);glutMainLoop();

    return 0;}

    A.b quadortho.c#include

    void display(void){

    glClearColor(0.0,0.0,0.0,0.0);glClear(GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);glLoadIdentity();

    glOrtho(-1.0,1.0,-1.0,1.0,-1.0,1.0);

    glMatrixMode(GL_MODELVIEW);

    glBegin(GL_QUADS);// Dibujamos un cuadrado

    glColor3f(0.0,1.0,1.0);// Color para el cuadradoglVertex3f(-0.5,0.5,-0.5);// Coordenadas del primer vrtice (superior-izquierda)glVertex3f(-0.5,-0.5,0.5);// Coordenadas del segundo vrtice (inferior-izquierda)glVertex3f(0.5,-0.5,0.5);// Coordenadas del primer vrtice (inferior-derecha)glVertex3f(0.5,0.5,-0.5);// Coordenadas del primer vrtice (superior-derecha)

    glEnd();// Terminamos de dibujar

    glFlush();

    sleep(10);exit(0);

    60 ESIDE Ghost

  • Captulo 8: Recursos de inters Curso de introduccin a OpenGL (v1.0)

    }

    int main(int argc, char ** argv){

    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);glutInitWindowPosition(20,20);glutInitWindowSize(500,500);glutCreateWindow(argv[0]);

    glutDisplayFunc(display);glutMainLoop();

    return 0;}

    A.c quadpersp.c#include

    void display(void){

    glClearColor(0.0,0.0,0.0,0.0);glClear(GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);glLoadIdentity();

    gluPerspective(60.0,1.0,1.0,100.0);// Proyeccin perspectiva. El ngulo de visualizacin es de 60

    grados, la razn ancho/alto es 1 (son inguales), la distanciamnima es z=1.0, y la distancia mxima es z=100.0

    glMatrixMode(GL_MODELVIEW);

    glTranslatef(0.0,0.0,-2.0);

    glBegin(GL_QUADS);// Dibujamos un cuadrado

    glColor3f(0.0,1.0,1.0);// Color para el cuadradoglVertex3f(-0.5,0.5,-0.5);// Coordenadas del primer vrtice (superior-izquierda)glVertex3f(-0.5,-0.5,0.5);// Coordenadas del segundo vrtice (inferior-izquierda)glVertex3f(0.5,-0.5,0.5);// Coordenadas del primer vrtice (inferior-derecha)glVertex3f(0.5,0.5,-0.5);// Coordenadas del primer vrtice (superior-derecha)

    glEnd();// Terminamos de dibujar

    glFlush();

    sleep(20);

    2003 - Jorge Garca (Bardok) 61

  • Curso de introduccin a OpenGL (v1.0) Recursos de inters

    exit(0);}

    int main(int argc, char ** argv){

    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);glutInitWindowPosition(20,20);glutInitWindowSize(500,500);glutCreateWindow(argv[0]);

    glutDisplayFunc(display);glutMainLoop();

    return 0;}

    A.d zbuffer-yes.c#include

    void display(void){

    glDepthFunc(GL_LEQUAL);glEnable(GL_DEPTH_TEST);// Activamos el el Z-BufferglClearColor(0.0,0.0,0.0,0.0);glClearDepth(1.0);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Borramos el buffer de color y el Z-Buffer

    glMatrixMode(GL_PROJECTION);glLoadIdentity();

    gluPerspective(60.0,1.0,1.0,100.0);// Proyeccin perspectiva. El ngulo de visualizacin es de 60

    grados, la razn ancho/alto es 1 (son inguales), la distanciamnima es z=1.0, y la distancia mxima es z=100.0

    glMatrixMode(GL_MODELVIEW);

    glTranslatef(0.0,0.0,-2.0);

    glBegin(GL_QUADS);// Dibujamos un cuadrado

    glColor3f(0.0,1.0,1.0);// Color para el cuadradoglVertex3f(-0.5,0.5,-0.5);// Coordenadas del primer vrtice (superior-izquierda)glVertex3f(-0.5,-0.5,0.5);// Coordenadas del segundo vrtice (inferior-izquierda)glVertex3f(0.5,-0.5,0.5);// Coordenadas del primer vrtice (inferior-derecha)glVertex3f(0.5,0.5,-0.5);// Coordenadas del primer vrtice (superior-derecha)

    62 ESIDE Ghost

  • Captulo 8: Recursos de inters Curso de introduccin a OpenGL (v1.0)

    glEnd();// Terminamos de dibujar

    glBegin(GL_TRIANGLES);glColor3f(1.0,0.0,0.0);glVertex3f(0.0,0.5,0.0);glVertex3f(-0.7,-0.5,0.0);glVertex3f(0.7,-0.5,0.0);

    glEnd();

    glFlush();

    sleep(20);exit(0);

    }

    int main(int argc, char ** argv){

    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);glutInitWindowPosition(20,20);glutInitWindowSize(500,500);glutCreateWindow(argv[0]);

    glutDisplayFunc(display);glutMainLoop();

    return 0;}

    A.e simpleguy.c#include #include

    // Medidas del cuerpo

    #define BODY_HEIGHT 4.0#define BODY_WIDTH 2.5#define BODY_LENGTH 1.0

    #define ARM_HEIGHT 3.5#define ARM_WIDTH 1.0#define ARM_LENGTH 1.0

    #define LEG_HEIGHT 4.5#define LEG_WIDTH 1.0#define LEG_LENGTH 1.0

    #define HEAD_RADIUS 1.1

    void display(void){

    glDepthFunc(GL_LEQUAL);glEnable(GL_DEPTH_TEST);

    2003 - Jorge Garca (Bardok) 63

  • Curso de introduccin a OpenGL (v1.0) Recursos de inters

    // Activamos el el Z-BufferglClearColor(0.0,0.0,0.0,0.0);glClearDepth(1.0);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Borramos el buffer de color y el Z-Buffer

    glMatrixMode(GL_PROJECTION);glLoadIdentity();

    gluPerspective(60.0,1.0,1.0,100.0);// Proyeccin perspectiva. El ngulo de visualizacin es de 60

    grados, la razn ancho/alto es 1 (son inguales), la distanciamnima es z=1.0, y la distancia mxima es z=100.0

    glMatrixMode(GL_MODELVIEW);

    glTranslatef(0.0,0.0,-16.0);

    // Dibujamos el cuerpoglTranslatef(0,BODY_HEIGHT/2,0);glPushMatrix();

    glScalef(BODY_WIDTH,BODY_HEIGHT,BODY_LENGTH);glColor3f(0.0,0.3,0.8);glutSolidCube(1);

    glPopMatrix();

    // Dibujamos el brazo derechoglPushMatrix();

    glTranslatef(-(BODY_WIDTH)/2,(BODY_HEIGHT-ARM_HEIGHT)/2,0);glTranslatef(0,ARM_HEIGHT/2,0);glRotatef(-30,0,0,1);glTranslatef(0,-ARM_HEIGHT/2,0);glPushMatrix();

    glScalef(ARM_WIDTH,ARM_HEIGHT,ARM_LENGTH);glutSolidCube(1);

    glPopMatrix();// ya tenemos el