Está en la página 1de 94

Curso de introduccin a OpenGL (v1.

1)
Por Jorge Garca -aka Bardok (2004)-

bardok@telefonica.net - shadow@bardok.net http://www.bardok.net

This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike icense. To view a cop! of this license" visit http://creativecommons.or#/licenses/b!-nc-sa/$.%/ or send a letter to Creative Commons" &&' Nathan Abbott (a!" Stanford" California ')*%&" +SA

Curso de introducci,n a -pen. /v0.01

ndice de contenido
Cap2tulo 0: 3ntroducci,n....................................................................................4 0.0 5rop,sito de este manual........................................................................4 0.$ 6A 7ui8n est9 diri#ido:............................................................................4 0.* Acerca del manual...................................................................................; Cap2tulo $: -pen. ! .N+/ inu<.....................................................................' $.0 a librer2a -pen. ..................................................................................' $.$ .N+/ inu< ! -pen. ............................................................................0% $.$.0 6=u8 es necesario para desarrollar aplicaciones -pen. :...........00 Cap2tulo *: Conceptos b9sicos sobre -pen. .................................................0* *.0 -pen. como m97uina de estados.......................................................0* *.$ >l espacio *?.........................................................................................0) *.$.0 as transformaciones de los ob@etos..............................................0& *.$.$ as coordenadas homo#8neas........................................................04 *.* Sobre . +T...........................................................................................04 *.) as funciones b9sicas de -pen. .........................................................0; *.).0 Activaci,n/desactivaci,n de opciones............................................0; *.).$ as matrices ! -pen. ..................................................................0; *.).* >l dibu@ado en -pen. ...................................................................0' *.).) >l color en -pen. ........................................................................$% *.).& a orientaci,n de las caras en -pen. .........................................$% *.).A as transformaciones en -pen. ..................................................$% *.).4 a pro!ecci,n en -pen. ..............................................................$% *.& 5rimer contacto con -pen. ................................................................$0 *.&.0 Bi primer pro#rama -pen. .........................................................$$ *.&.$ CisualiDando en perspectiva...........................................................$) *.&.* -cultaci,n de ob@etos /E-Fuffer1....................................................$A *.&.) Gerar7u2as.......................................................................................$; Cap2tulo ): Animaciones..................................................................................*& ).0 os vectores para animar fi#uras..........................................................*& ).$ >l doble bufferin#..................................................................................*' Cap2tulo &: 3luminaci,n...................................................................................)* &.0 >l modelo de iluminaci,n en -pen. ...................................................)* &.0.0 uces..............................................................................................)) &.0.$ Bateriales.......................................................................................)) &.0.* Normales........................................................................................)) &.$ +tiliDando iluminaci,n en -pen. ........................................................)& &.$.0 uces..............................................................................................)& &.$.$ Bateriales.......................................................................................)4 &.$.* >@emplo: iluminaci,n direccional sobre una superficie.................); &.$.) >@emplo: moviendo un foco alrededor de una esfera.....................&% &.$.& >@ercicio propuesto.........................................................................&$ Cap2tulo A: Te<turas........................................................................................&& A.0 as coordenadas de te<tura...................................................................&& A.$ Aplicar las te<turas................................................................................&A A.$.0 Hepetici,n de te<turas....................................................................&; Cap2tulo 4: 3nteracci,n b9sica con . +T........................................................A* 4.0 3nteracci,n con el teclado.....................................................................A*
Gor#e .arc2a -Fardok- /$%%)1 *

Curso de introducci,n a -pen. /v0.01

4.$ Hedimensionado de la ventana..............................................................A) Cap2tulo ;: Hecursos de inter8s.......................................................................A4 Ane<o A: C,di#o de los pro#ramas de e@emplo...............................................A' A.a m!firstopen#lpro#ram.c........................................................................A' A.b 7uadortho.c...........................................................................................4% A.c 7uadpersp.c...........................................................................................40 A.d Dbuffer-!es.c..........................................................................................4$ A.e simple#u!.c............................................................................................4* A.f @erar7uia-cuadro.c..................................................................................4& A.# @erar7uia-cuadro-recursivo.c.................................................................4A A.h sphere-rebotes.cpp................................................................................44 A.i sphere-rebotes-multi.cpp.......................................................................;% A.@ normals-perp.c.......................................................................................;0 A.k lit-sphere.c.............................................................................................;$ A.l l-sphere-rebotes-multi.cpp.....................................................................;) A.m trian#-te<ture.c.....................................................................................;A A.n normals-perp-te<ture.c..........................................................................;; A.o te<ture-no-clamp.c I te<ture-!es-clamp.c............................................;' A.p lit-sphere-ke!b.c....................................................................................'0

>S3?>-.host

Curso de introducci,n a -pen. /v0.01

ndice de ilustraciones
Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura Ji#ura $.0. Acceso al hardware a trav8s de -pen. /.N+/ inu<1................00 *.0. >@es de coordenadas en -pen. ..................................................0) *.$. Traslaci,n de un ob@eto.................................................................0& *.*. Hotaci,n de un ob@eto...................................................................0A *.). >scalado en el e@e K......................................................................0A *.&. C8rtices de un pol2#ono................................................................$% *.A. ColLmen de pro!ecci,n orto#r9fico..............................................$0 *.4. ColLmen de visualiDaci,n en perspectiva.....................................$0 *.;. Salida del pro#rama Mm!firstopen#lpro#ramM..............................$) *.'. Salida del pro#rama M7uadorthoM.................................................$& *.0%. Salida del pro#rama N7uadperspO...............................................$A *.00. ?ibu@ado sin E-Fuffer..................................................................$4 *.0$. ?ibu@ado con E-Fuffer /salida del pro#rama Dbuffer-!es1...........$; *.0*. Gerar7u2a sencilla /salida del pro#rama @erar7uia-cuadro.c1......*% *.0). Gerar7u2a fractal /pro#rama @erar7uia-cuadro-recursivo.c1........*% *.0&. Salida del pro#rama Msimple#u!M................................................*$ *.0A. Hotaci,n del braDo /simple#u!1..................................................** ).0. Hepresentaci,n de la posici,n ! velocidad con vectores..............*A ).$. Comportamiento del pro#rama MrebotesM.....................................*A ).*. 5osici,n de la c9mara en el e@emplo Msphere-rebotesM.................*; ).). Salida del pro#rama Msphere-rebotesM..........................................)% ).&. Salida del pro#rama Msphere-rebotes-multiM................................)0 &.0. >fecto de las normales en la iluminaci,n.....................................)& &.$. Tipos de luces...............................................................................)A &.*. Salida del pro#rama Mlit-sphereM...................................................&$ &.). Salida del pro#rama Ml-sphere-rebotes-multiM..............................&* A.0. Coordenadas de te<tura................................................................&A A.$. Bapeado de te<tura......................................................................&A A.*. ?iferencias entre . PH>5 AC> ! . PB-?+ AT>.....................&; A.). Te<turas para suelo ! pared..........................................................&' A.&. Salida del pro#rama Mte<ture-no-clampM.......................................A% A.A. Salida del pro#rama Mte<ture-!es-clampM.....................................A0

Gor#e .arc2a -Fardok- /$%%)1

&

Curso de introducci,n a -pen. /v0.01

ndice de tablas
Tabla *.0. 5rimitivas de dibu@ado....................................................................0' Tabla ).0. B8todos de la clase TSphere..........................................................*4

>S3?>-.host

Cap2tulo 0: 3ntroducci,n

Curso de introducci,n a -pen. /v0.01

Captulo 1: Introduccin

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

1.1 Propsito de este manual


>ste manual intenta ser una #u2a para adentrarse en la pro#ramaci,n *?" con la librer2a -pen. " ! orientado a la pro#ramaci,n ba@o .N+/ inu<" aun7ue los conceptos a7u2 e<plicados son ma!ormente v9lidos para cual7uier otra plataforma. >l enfo7ue 7ue se va a dar es mu! pr9ctico" basado casi 2nte#ramente en la realiDaci,n de e@ercicios 7ue permitan al lector obtener los conocimientos b9sicos para desenvolverse por su cuenta en el mundo de la pro#ramaci,n *?.

1.2 A quin est dirigido?


>ste manual est9 diri#ido a cual7uier persona 7ue ten#a inter8s en adentrarse en el mundo de la pro#ramaci,n *? con -pen. " ! mu! especialmente a los asistentes del curso del e-#host 7ue se celebrar9 en Gulio del aQo $%%) en la +niversidad de ?eusto" en la 7ue est9 f2sicamente ubicada dicho #rupo. as personas 7ue intenten hacer al#o de utilidad con este manual" deben tener unos conocimientos m2nimos de pro#ramaci,n en C/CII... No son necesarios conocimientos de pro#ramaci,n espec2ficos ba@o .N+/ inu<" !a 7ue todo lo necesario para pro#ramar ba@o esta plataforma se reco#e en este manual.

Gor#e .arc2a -Fardok- /$%%)1

Curso de introducci,n a -pen. /v0.01

6A 7ui8n est9 diri#ido:

>l manual no se recomienda a personas con conocimientos avanDados de -pen. " !a 7ue no va a contar nada revolucionario acerca de esta tecnolo#2a #r9fica *?" si bien" 7ui8n sabe" siempre se puede aprender al#o nuevo...

1.3 Acerca del manual


>l contenido de este manual se divide en secciones 7ue intentan abordar separadamente los distintos puntos por los 7ue un usuario principiante deber9 pasar al enfrentarse a la pro#ramaci,n con -pen. ba@o .N+/ inu< /a partir de este momento" simplemente -pen. 1. >n el cap2tulo 0 comenDaremos con una introducci,n a la librer2a -pen. . >n el cap2tulo $ se e<plicar9n las maneras en las 7ue -pen. aparece en la plataforma .N+/ inu<" ! c,mo deberemos de instalar lo necesario para pro#ramar con 8l. >n el cap2tulo * se comenDar9 con la pro#ramaci,n en -pen. como tal" viendo los conceptos b9sicos acerca de transformaciones ! visualiDaci,n propios de esta librer2a. >n el cap2tulo ) se hablar9 de c,mo animar las escenas. >n el cap2tulo & se describen los fundamentos de la iluminaci,n" ! c,mo se utiliDa en -pen. . >n el cap2tulo A se e<plica la utiliDaci,n de te<turas en -pen. " de manera b9sica. >n el cap2tulo 4 se e<plica brevemente c,mo interactuar con las ventanas mediante la librer2a #lut. >n el cap2tulo ; se recomiendan una serie de lecturas de inter8s.

>S3?>-.host

Cap2tulo $: -pen. ! .N+/ inu<

Curso de introducci,n a -pen. /v0.01

Captulo 2: OpenGL y G !"Linu#

No permitas que los rboles te impidan ver al chalado que te persigue con una motosierra... (Bardok)

2.1 La librera

pen!L

-pen. es un est9ndar creado por Silicon .raphics en el aQo 0''$ para el diseQo de una librer2a $?/*? portable R-5>N. S. Actualmente es una de las tecnolo#2as m9s empleadas en el diseQo de aplicaciones *?" ! su Lltima versi,n" a la fecha de ho! /$%%)1" es la 0.&" ! est9 en proceso la especificaci,n de la versi,n $.%" 7ue incluir9 muchas me@oras.. Se divide en tres partes funcionales:

a librer2a -pen. " 7ue proporciona todo lo necesario para acceder a las funciones de dibu@ado de -pen. . a librer2a . + /-pen. +tilit! ibrar!1" una librer2a de utilidades 7ue proporciona acceso r9pido a al#unas de las funciones m9s comunes de -pen. " a trav8s de la e@ecuci,n de comandos de m9s ba@o nivel" pertenecientes a la librer2a -pen. propiamente dicha RH>?F--TS. . K /-pen. ><tension to the K (indow S!stem1 proporciona un acceso a -pen. para poder interactuar con un sistema de ventanas K (indow" ! est9 incluido en la propia implementaci,n de -pen. /su e7uivalente en (indows es la librer2a (. " e<terna a la implementaci,n de -pen. 1.

Adem9s de estas tres librer2as" la librer2a . +T /-pen. +tilit! Toolkit1 proporciona una interfaD independiente de plataforma para crear aplicaciones de ventanas totalmente portables R. +TS.
Gor#e .arc2a -Fardok- /$%%)1 '

Curso de introducci,n a -pen. /v0.01

.N+/ inu< ! -pen.

2.2 !"#$Linu% &

pen!L

-pen. aparece en .N+/ inu<" habitualmente ba@o la librer2a Besa *? RB>SAS" una implementaci,n libre de -pen. . >sta implementaci,n es" de por s2" una implementaci,n totalmente software de la librer2a -pen. /e<cepto para las tar@etas *df< Coodoo0" Coodoo$" Coodoo Hush" Coodoo Fanshee" Coodoo*" 7ue tienen acceso al hardware a trav8s del driver Besa/.lide 7ue proporciona Besa1" por lo 7ue s,lo es aconse@able utiliDarla en el caso de no disponer de nin#una otra implementaci,n de -pen. . Actualmente /$%%)1 la versi,n estable de esta librer2a es la A.%.0" 7ue implementa el est9ndar -pen. 0.&. a utiliDaci,n m9s habitual de esta librer2a" no obstante" se realiDa a partir de la librer2a <libmesa. >sta librer2a forma parte del sistema Kfree;A" ! proporciona acceso a aceleraci,n #r9fica por hardware" siempre 7ue la tar@eta #r9fica ! los drivers instalados lo permitan" a trav8s de ?H3 /?irect Henderin# 3nfraestructure R?H3S1. >ste es el modo a trav8s del 7ue podemos acceder a aceleraci,n por hardware para tar@etas de v2deo como *df<" 3ntel" Batro<" AT3... ?H3 est9 presente en las implementaciones del servidor Kfree;A a partir de la versi,n ) del mismo. B9s concretamente" la versi,n ).* de Kfree;A trae consi#o la librer2a <libmesa ).%.)" 7ue implementa el est9ndar -pen. 0.*. Jinalmente" las tar@etas NC3?3A proporcionan su propia implementaci,n de la librer2a -pen. " independientemente de la librer2a Besa" si bien es cierto 7ue ciertas partes de Besa /las librer2as de utilidades . + ! . +T1 pueden utiliDarse @unto con la implementaci,n de NC3?3A. >n resumen" podemos utiliDar la librer2a -pen. se#Ln nuestra confi#uraci,n de hardware: de diferentes maneras"

0%

>S3?>-.host

Cap2tulo $: -pen. ! .N+/ inu<

Curso de introducci,n a -pen. /v0.01

Apli a i!n "D Interfaz OpenGL Mesa Xlibmesa #$IDIA OpenGL Dri%er

Mesa/Glide

Software Render

DRI

HARDWARE

Ji#ura $.0. Acceso al hardware a trav8s de -pen.

/.N+/ inu<1

2.2.1 $%u& es necesario para desarrollar aplicaciones OpenGL'


A la hora de desarrollar aplicaciones necesitaremos las si#uientes herramientas:

-pen.

ba@o

.N+/ inu<"

os binarios de la librer2a -pen. " !a sea Besa /compilado e instalado a partir del c,di#o fuente1" <libmesa /incluido con Kfree;A ) ! posteriores1 o drivers propios. os pa7uetes de desarrollo de estas librer2as /<libmesa-dev" en el caso de <libmesa" #lut#*-dev... para drivers propios depender9 del fabricante" ! para Besa" si se ha instalado compilando el c,di#o fuente" no deber2a de haber problemas1. +n compilador del len#ua@e en el 7ue vamos a pro#ramar" en este caso" en C" para lo 7ue usaremos el compilador #cc" ! #II si utiliDamos CII. +n editor de te<to" !a sea en modo consola" o ba@o el entorno K (indows /a m2 me #usta el Tate de T?>" pero cada cual tiene sus preferencias1.

Ahora !a estamos listos para comenDar a pro#ramar con -pen. ...

Gor#e .arc2a -Fardok- /$%%)1

00

Cap2tulo *: Conceptos b9sicos sobre -pen.

Curso de introducci,n a -pen. /v0.01

Captulo (: Conceptos b)sicos sobre OpenGL

Por qu narices habr puesto que despus de el nombre de un captulo, me pida poner una cita de manera automtica? (Bardok)

3.1

pen!L como mquina de estados

-pen. es una librer2a 7ue traba@a como una m97uina de estados. >sto es al#o 7ue oiremos hasta la saciedad al pro#ramar con -pen. ... 6pero 7u8 si#nifica: a utiliDaci,n de -pen. consiste en activar ! desactivar opciones" ! realiDar ciertas acciones" 7ue tendr9n como fruto una representaci,n en pantalla /o no1 de una serie de datos" dependiendo en el estado en 7ue nos encontremos... As2" no ser9 lo mismo dibu@ar un tri9n#ulo ! activar una te<tura" 7ue activar una te<tura ! dibu@ar un tri9n#ulo... en -pen. " el orden de las acciones resulta cr2tico en la ma!or2a de las ocasiones... de i#ual manera" no ser9 lo mismo trasladar ! rotar al#o" 7ue rotarlo ! trasladarlo" como veremos m9s adelante" en lo referente a las transformaciones... ?e este modo" de manera mu! abstracta" la manera de dibu@ar al#o en -pen. suele ser la si#uiente: 0. Activar todas las opciones 7ue van a ser persistentes a la escena /ponemos la c9mara" activamos la iluminaci,n #lobal...1 $. Activar las opciones 7ue establecen el estado de un ob@eto espec2fico /su posici,n en el espacio" su te<tura...1

Gor#e .arc2a -Fardok- /$%%)1

0*

Curso de introducci,n a -pen. /v0.01

-pen. como m97uina de estados

*. ?ibu@ar el ob@eto. ). ?esactivar las opciones propias de ese ob@eto /volver a la posici,n ori#inal" desactivar su te<tura1 &. Colver al punto $ hasta haber dibu@ado todos los ob@etos. >sto" evidentemente" es un es7uema sencillo... como se ver9 m9s adelante" estas operaciones pueden a#ruparse en @erar7u2as" lo 7ue proporciona una #ran potencia ! fle<ibilidad a la hora de pro#ramar /6se nota 7ue so! fan de -pen. : U-1

3.2 'l espacio 3(


Si bien es cierto 7ue -pen. proporciona acceso a funciones de dibu@ado $?" en este curso nos vamos a centrar en el espacio *?... -pen. traba@a" a #randes ras#os" en un espacio de tres dimensiones" aun7ue veremos 7ue realmente" traba@a con coordenadas homo#8neas /de cuatro dimensiones1. as tres dimensiones 7ue nos interesan ahora son las especificadas por un sistema *? ortonormal. >s decir" sus e@es son perpendiculares" ! cada unidad en uno de ellos est9 representada por un vector de m,dulo 0 /si nos ale@amos una unidad" nos ale@amos la misma distancia del e@e de coordenadas" da i#ual la direcci,n1.

Z
Ji#ura *.0. >@es de coordenadas en -pen.

a cuarta coordenada se utiliDa entre otras raDones" para representar la perspectiva" pero no nos meteremos con ello en este momento... de este modo" el sistema de coordenadas inicial de un sistema -pen. puede representarse con esta matriD:

0)

>S3?>-.host

Cap2tulo *: Conceptos b9sicos sobre -pen.

Curso de introducci,n a -pen. /v0.01

Jinalmente" es recomendable desempolvar nuestros al#ebraicos b9sicos /vectores" normales" etc.1" por7ue como veremos" nos van a resultar de #ran utilidad a la hora de pro#ramar en *?... a situaci,n de los e@es de coordenadas se refle@a en la matriD de transformaci,n. >sta matriD representa la transformaci,n 7ue se aplicar9 a todos los v8rtices 7ue se dibu@en mientras ella est8 activa.

[ ]
1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1

(.2.1 Las trans*or+aciones de los ob,etos


Al o2r hablar de pro#ramaci,n *?" habremos o2do hablar de las transformaciones de ob@etos... estas transformaciones son las 7ue van a describir c,mo se visualiDa un ob@eto en el espacio" ! son de tres tipos:

Traslaci,n: una traslaci,n es un desplaDamiento de un ob@eto en el espacio... por e@emplo" movemos un ob@eto a una nueva posici,n desde la actual

Ji#ura *.$. Traslaci,n de un ob@eto

Hotaci,n: como su nombre indica" un ob@eto rota alrededor de un e@e 7ue pasa por su Ncentro de #iroO

Gor#e .arc2a -Fardok- /$%%)1

0&

Curso de introducci,n a -pen. /v0.01

>l espacio *?

Ji#ura *.*. Hotaci,n de un ob@eto

>scalado: un ob@eto puede ver afectado el tamaQo con 7ue se visualiDa por su transformaci,n de escalado

Ji#ura *.). >scalado en el e@e K

Sin entrar en demasiados detalles" es conveniente saber 7ue toda trasformaci,n constru!e una matriD de cuatro dimensiones 7ue se multiplicar9 por la matriD de transformaci,n inicial /a7uella 7ue define el e@e de coordenadas1. 5or e@emplo" al trasladar un ob@eto dos unidades en el e@e K" se #enera la si#uiente matriD de transformaci,n:

[
0A

1 0 0 0

0 1 0 0

0 0 1 0

2 0 0 1

]
>S3?>-.host

Cap2tulo *: Conceptos b9sicos sobre -pen.

Curso de introducci,n a -pen. /v0.01

Si aplicamos esta transformaci,n a la matriD ori#inal" nos 7uedar9 7ue la nueva matriD de transformaci,n es:

Si ahora dibu@amos el punto /0"%"%1" teniendo en cuenta 7ue la matriD indica un desplaDamiento de dos unidades en e@e K" el punto deber2a de dibu@arse en la posici,n /*"%"%1. 5ara esto" se multiplica el punto por la matriD de transformaci,n:

[ ][ ][ ]
1 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 1 0 2 1 0 0 0 1 = 0 0 0 1 0 0 0 0 1 0 2 0 0 1

5ara poder multiplicar el punto /0"%"%1 por la matriD" lo hemos convertido a coordenadas homo#8neas" ! para ello" hemos aQadido una Lltima componente con el valor 0.

[ ][][]
1 0 0 0 0 1 0 0 0 0 1 0 2 1 3 0 0 0 = 0 0 0 1 1 1

(.2.2 Las coordenadas -o+o.&neas


Cuando pensamos en dibu@ado *?" estamos acostumbrados a pensar en espacios de tres coordenadas" o dos" para fi#uras $?" pero en -pen. todo se traduce a coordenadas homo#8neas. as raDones son varias /uniformidad de operaci,n con matrices ! facilidad de representaci,n de diferentes conceptos relativos a la profundidad1" pero no es ob@eto de este manual discutirlas. ?e esta forma" el punto *? /0"$"*1 es traducido por -pen. al punto /0"$"*"0.%1 ! el punto $? /0"$1 es traducido a /0"$"%.%"0.%1. A #randes ras#os" podemos de decir 7ue un punto /<"!"D"w1 en coordenadas homo#8neas" es e7uivalente al punto *? /</w"!/w"D/w1. As2 los puntos /0"$"%"0%1" /0"$"%"01 ! /0"$"%"%.%%%%01 se corresponden con los puntos $? /%.0"%.$1" /0"$1 ! /0%%%%"$%%%%1. +n apunte interesante es 7ue si la coordenada w es i#ual a %" estar2amos hablando" del punto situado en el infinito en la direcci,n del vector 7ue especifican las otras tres coordenadas /vemos 7ue" si se decrementa la w" el punto $? o *? e7uivalente se ale@a1. >sto resultar9 mu! Ltil para entender ciertos aspectos de la iluminaci,n.

3.3 )obre !L#*


5ara los e@emplos de este manual vamos a utiliDar la librer2a de ventanas . +T" ! para ello hemos de tener claros ciertos aspectos de esta librer2a. a librer2a . +T inclu!e funciones para la creaci,n de ventanas independiente de plataforma. A medida 7ue va!amos viendo distintos
Gor#e .arc2a -Fardok- /$%%)1 04

Curso de introducci,n a -pen. /v0.01

Sobre . +T

e@emplos" iremos profundiDando en las funciones utiliDadas. 3nicialmente" s,lo vamos a comentar 7ue . +T funciona #eneralmente a trav8s de funciones de callback" es decir" como par9metro de una funci,n" se le pasa un puntero a otra funci,n 7ue ser9 llamada por la funci,n principal.

3.+ Las ,unciones bsicas de

pen!L

5ara comenDar a utiliDar -pen. hemos de tener claras diversas funciones 7ue vamos a utiliDar mu! a menudo.

(./.1 0ctivacin"desactivacin de opciones


Como se ha comentado" -pen. es una m97uina de estados: activamos ! desactivamos opciones 7ue afectan al dibu@ado. Vabitualmente" las opciones se activan ! desactivan con #l>nable/W-5T3-NX1 ! #l?isable/W-5T3-NX1. 5or e@emplo #l>nable/. P 3.VT3N.1 activar9 la iluminaci,n b9sica de la escena.

(./.2 Las +atrices y OpenGL


Anteriormente hemos visto 7ue -pen. #uarda la transformaci,n de los ob@etos en una matriD. A esta matriD se le denomina matriD de visualiDaci,n/modelado" por7ue se emplea para estas dos funciones. Adem9s de esta transformaci,n" -pen. posee otra matriD mu! importante" 7ue es la matriD de pro!ecci,n" en la 7ue se #uarda la informaci,n relativa a la Nc9maraO a trav8s de la cual vamos a visualiDar el mundo. Al realiDar operaciones 7ue modifi7uen al#una de estas dos matrices" tendremos 7ue cambiar el Nmodo de matriDO" para 7ue las operaciones afecten a la matriD 7ue nos interesa. 5ara ello utiliDaremos las funciones #lBatri<Bode/. PB-?> C3>(1 o #lBatri<Bode/. P5H-G>CT3-N1. Adem9s" e<isten dos funciones 7ue permiten #uardar ! restaurar los valores de la matriD activa en una pila. a funci,n #l5ushBatri</1 #uarda una matriD en la cima de la pila" ! #l5opBatri</1 la saca" ! la restaura. >sto lo podemos utiliDar para dibu@ar un ob@eto !" antes de dibu@ar el si#uiente" restauramos la transformaci,n inicial. 5or e@emplo:

Wtransformaci,n comLn para la escenaX #l5ushBatri</1U Wtrasformaci,n propia del elemento 0X Wdibu@ado del elemento 0X
0; >S3?>-.host

Cap2tulo *: Conceptos b9sicos sobre -pen.

Curso de introducci,n a -pen. /v0.01

#l5opBatri</1U // volvemos a la transformaci,n comLn #l5ushBatri</1U Wtransformaci,n propia del elemento $X Wdibu@ado del elemento $X #l5opBatri</1U // volvemos a la transformaci,n comLn ...

Jinalmente" comentar la operaci,n #l oad3dentit!/1" 7ue car#a la matriD identidad como matriD activa.

(./.( 1l dibu,ado en OpenGL


5ara dibu@ar en -pen. " tenemos 7ue habilitar el modo de dibu@ado" establecer las opciones de dibu@ado de cada v8rtice" ! dibu@ar cada uno de ellos. Al terminar de dibu@ar una fi#ura" finaliDamos el modo de dibu@ado. 5ara comenDar a dibu@ar" utiliDaremos el comando #lFe#in /WB-?-P?>P?3F+GA?-X1" d,nde el modo de dibu@ado vendr9 dado por una constante: Parmetro . P5-3NTS . P 3N>S . P5- Y.-N Descripcin Se dibu@an vertices separados Cada par de v8rtices se interpreta como una l2nea os v8rtices describen el contorno de un pol2#ono

. PTH3AN. >S Cada triplete de v8rtices de interpreta como un tri9n#ulo . P=+A?S . P 3N>PSTH35 . P 3N>P --5 . PTH3AN. >P STH35 . PTH3AN. >P JAN Cada cuarteto de v8rtices se interpreta como un cuadril9tero 2neas conectadas 2neas conectadas" con uni,n entre el primer ! Lltimo v8rtice Se dibu@a un tri9n#ulo" ! cada nuevo v8rtice se interpreta con un tri9n#ulo entre los dos anteriores v8rtices ! el nuevo Se dibu@an tri9n#ulos con un v8rtice comLn

. P=+A?PSTH3 3#ual 7ue el TH3AN. >PSTH35" con cuadril9teros 5


Tabla *.0. 5rimitivas de dibu@ado

>ntre las funciones 7ue permiten establecer los atributos de cada v8rtice" est9n a7uellas 7ue nos permiten seleccionar su color /#lColorZ1" normal /#lNormalZ1" coordenadas de te<tura /#lTe<CoordZ1" etc.
Gor#e .arc2a -Fardok- /$%%)1 0'

Curso de introducci,n a -pen. /v0.01

as funciones b9sicas de -pen.

Jinalmente" las funciones de dibu@ado de v8rtices tienen la forma N#lCerte<ZO.

(././ 1l color en OpenGL


-pen. puede utiliDar dos modos de color: color H.FA ! color inde<ado. Nosotros vamos a centrarnos en el color H.FA. >ste color recibe este nombre por7ue se compone de cuatro componentes: Ho@o /Hed1" Cerde /.reen1" ADul /Flue1 ! canal Alfa" o transparencia.

(./.2 La orientacin de las caras en OpenGL


+n pol2#ono tiene dos caras" delantera ! trasera. a manera de saber 7u8 cara es la delantera" ! cual la trasera" es 7ue" si miramos la delantera" los v8rtices se habr9n dibu@ado en orden antihorario. 5or e@emplo" tenemos la si#uiente fi#ura:

Ji#ura *.&. C8rtices de un pol2#ono

Si dibu@amos los vertices en el orden 0"*")"$" estaremos dibu@ando la cara delantera mirando hacia nosotros" pero si el orden es" por e@emplo" 0"$")"*" estaremos mirando la cara trasera del pol2#ono.

(./.3 Las trans*or+aciones en OpenGL


Jinalmente" como operaciones b9sicas" vamos a comentar a7uellas 7ue nos van a permitir situar los ob@etos en el espacio" es decir" aplicarles transformaciones:

#lTranslateZ: nos va a permitir trasladar un ob@eto en el espacio #lHotateZ: nos va a permitir rotar un ob@eto #lScaleZ: nos va a permitir escalar un ob@eto #lBultBatri<: multiplica la matriD de transformaci,n actual por una matriD dada. >sto es al#o mu! utiliDado en motores *?

>s mu! importante el orden en el 7ue va!amos a realiDar las transformaciones. No es lo mismo trasladar al#o ! despu8s rotarlo" 7ue primero rotarlo ! lue#o trasladarlo" como podremos comprobar posteriormente...

(./.4 La proyeccin en OpenGL


>n el modo de pro!ecci,n podemos especificar c,mo va a afectar la posici,n de un ob@eto a su visualiDaci,n. Tenemos dos maneras de visualiDar el
$% >S3?>-.host

Cap2tulo *: Conceptos b9sicos sobre -pen.

Curso de introducci,n a -pen. /v0.01

espacio: con una pro!ecci,n orto#r9fica" ! con una pro!ecci,n perspectiva:

a pro!ecci,n orto#r9fica: a pro!ecci,n orto#r9fica nos permite visualiDar todo a7uello 7ue se encuentre dentro de un cubo" delimitado por los par9metros de la funci,n #l-rto. A la hora de visualiDar" la distancia al observador s,lo se tiene en cuenta para determinar si el ob@eto est9 dentro o fuera del cubo...

Alt'ra

r( La a 'r

An &'ra

Ji#ura *.A. ColLmen de pro!ecci,n orto#r9fico

a pro!ecci,n perspectiva: a pro!ecci,n perspectiva delimita un volLmen de visualiDaci,n dado por un 9n#ulo de c9mara" ! una relaci,n alto/ancho. a distancia al observador determinar9 el tamaQo con el 7ue un ob@eto se visualiDa.

)n('lo

An &'ra ima -ima Dist* M+n Dist* M,


Ji#ura *.4. ColLmen de visualiDaci,n en perspectiva

3.- Primer contacto con

Alt'ra

pen!L

Fueno" a7u2 est9 lo 7ue todo pro#ramador desea tocar: el c,di#o U-1 vamos a comenDar con unos sencillos pro#ramas con los 7ue podremos
Gor#e .arc2a -Fardok- /$%%)1 $0

Curso de introducci,n a -pen. /v0.01

5rimer contacto con -pen.

comprobar c,mo se utiliDan los conceptos anteriormente e<plicados.

(.2.1 5i pri+er pro.ra+a OpenGL


>n este pro#rama vamos a dibu@ar un tri9n#ulo en pantalla con un v8rtice de cada color... Camos a hacer un Lnico NincludeO" con la cabecera de . +T. .eneralmente" los archivos de cabecera de -pen. estar9n en el direcctorio N. O dentro del 9rbol de archivos de cabecera:
#include <GL/glut.h>

S,lo inclu2mos este archivo" por7ue !a inclu!e las cabeceras N#l.hO ! N#lu.hO. ComenDamos con la funci,n 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; } sa cuatro primeras llamadas crean la ventana con la librer2a . +T:

0. 3nicialiDamos los modos con los 7ue se crear9 la ventana: con un s,lo buffer de dibu@ado" ! modelo de color H.FA /ro@o" verde" aDLl ! canal alfa [ transparencias1. $. >stablecemos el tamaQo ! posici,n de la ventana *. Creamos la ventana ?espu8s establecemos 7ue funci,n indica 7u8 ha! 7ue dibu@ar en la ventana. Ndispla!O es un puntero a una funci,n 7ue contiene el c,di#o de lo 7ue vamos a dibu@ar" ! llamamos a la funci,n 7ue comienDa el dibu@ado. Ahora s,lo nos 7ueda definir la funci,n Ndispla!O:
void display(void) { glClearColor(0.0,0.0,0.0,0.0); // Color de fondo: negro glClear(GL_COLOR_BUFFER_BIT); // Boramos la pantalla glMatrixMode(GL_PROJECTION); // Modo proyeccin glLoadIdentity(); // 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
$$ >S3?>-.host

Cap2tulo *: Conceptos b9sicos sobre -pen.

Curso de introducci,n a -pen. /v0.01

glBegin(GL_TRIANGLES); // Dibujamos un tringulo glColor3f(1.0,0.0,0.0); // Color del primer vrtice: rojo glVertex3f(0.0,0.8,0.0); // Coordenadas del primer vrtice glColor3f(0.0,1.0,0.0); // Color del segundo vrtice: verde glVertex3f(-0.6,-0.2,0.0); // Coordenadas del segundo vrtice glColor3f(0.0,0.0,1.0); // Color del tercer vrtice: azl glVertex3f(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 }

a funci,n #lClearColor especifica cu9l va a ser el color con el 7ue se va rellenar el buffer de pantalla cuando se borre Con #lClear ordenamos a -pen. 7ue borre los buffers indicados como par9metro. 5ara borrar la pantalla /el buffer de color1 lo indicamos con la constante . PC- -HPF+JJ>HPF3T >stablecemos el volLmen de visualiDaci,n" en modo pro!ecci,n ! con #l-rtho. ?ibu@amos el tri9n#ulo

.uardamos el c,di#o como Nm!firtsopen#lpro#ram.cO" ! lo compilamos con la si#uiente l2nea de c,di#o en una consola:
user@machine:$gcc myfirtsopenglprogram.c -lglut -lGL -lGLU -o myfirtsopenglprogram

>@ecutamos con:
user@machine:$./myfirstopenglprogram

Gor#e .arc2a -Fardok- /$%%)1

$*

Curso de introducci,n a -pen. /v0.01

5rimer contacto con -pen.

Ji#ura *.;. Salida del pro#rama Mm!firstopen#lpro#ramM

(.2.2 6isuali7ando en perspectiva...


Camos a dibu@ar un cuadrado con un pro#rama mu! similar al 7ue tenemos en el e@emplo anterior. 5ara ello vamos a sustituir el c,di#o referente al dibu@ado por el si#uiente c,di#o:
glBegin(GL_QUADS); // Dibujamos un cuadrado glColor3f(0.0,1.0,1.0); // Color para el cuadrado glVertex3f(-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

.uardamos como N7uadortho.cO" compilamos el pro#rama" ! observamos el resultado:


user@machine:$gcc quadortho.c -lglut lGL -lGLU -o quadortho user@machine:$./quadortho
$) >S3?>-.host

Cap2tulo *: Conceptos b9sicos sobre -pen.

Curso de introducci,n a -pen. /v0.01

Ji#ura *.'. Salida del pro#rama M7uadorthoM

Si estudiamos el c,di#o" observamos 7ue la parte superior del cuadrado est9 m9s ale@ada del observador 7ue la inferior" pero como se e<plic, en el apartado relativo a las pro!ecciones" esto no se tiene en cuenta para la pro!ecci,n orto#r9fica. Si 7ueremos 7ue esto se refle@e" tendremos 7ue crear una pro!ecci,n perspectiva... 5ara ello vamos a sustituir la llamada a #l-rtho por una llamada a #lu5erspective" 7ue establecer9 el modo de visualiDaci,n en perspectiva:
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 distancia mnima es z=1.0, y la distancia mxima es z=100.0

.uardamos como N7uadpersp.cO" compilamos ! e@ecutamos:


user@machine:$gcc quadpersp.c -lglut lGL -lGLU -o user@machine:$./ quadpersp quadpersp

\Y nos encontramos con 7ue no se ve nada] =ue no cunda el p9nico... todo tiene sentido... tal ! como est9 todo planteado" el cuadrado se va a dibu@ar con centro en el ori#en de coordenadas... 6pero d,nde est9 el observador: >n la visualiDaci,n perspectiva" la posici,n del observador determina c,mo
Gor#e .arc2a -Fardok- /$%%)1 $&

Curso de introducci,n a -pen. /v0.01

5rimer contacto con -pen.

se ven las cosas... vamos a tomar 7ue el observador" !a 7ue no hemos indicado lo contrario" se encuentra en la posici,n /%"%"%1. Camos a retrasar un poco el cuadrado" para ale@arlo del observador" por7ue sino" se dibu@a @usto en el mimo lu#ar 7ue 8ste" ! no puede verse nada... para ello" despu8s de entrar en el modo de modelado/visualiDaci,n" aQadimos:
glTranslatef(0.0,0.0,-2.0); // Alejamos el cuadrado del observador dos unidades en el eje Z

.uardamos" compilamos" e@ecutamos !...

Ji#ura *.0%. Salida del pro#rama N7uadperspO

...\perfecto] :-?

a parte superior del tri9n#ulo se dibu@a ale@ada del observador

(.2.( Ocultacin de ob,etos (89:u**er)


Si aQadimos en el c,di#o de visualiDaci,n un tri9n#ulo con las coordenadas /%.%"%.&"%.%1" /-%.4"-%.&"%.%1"/%.4"-%.&"%.%1" despu8s del codi#o de dibu@ado del cuadrado" la salida es la si#uiente:

$A

>S3?>-.host

Cap2tulo *: Conceptos b9sicos sobre -pen.

Curso de introducci,n a -pen. /v0.01

Ji#ura *.00. ?ibu@ado sin E-Fuffer

Como podemos observar" no se tiene en cuenta 7ue la parte inferior del tri9n#ulo deber2a de estar tapada por el cuadrado" por7ue su coordenada E" 7ue indica la profundidad" es ma!or /-%.& para el cuadrado ! % para el tri9n#ulo1. 5ara poder visualiDar los ob@etos con oclusi,n" tenemos 7ue activar el E-Fuffer.

>l E-Fuffer es un arra! 7ue #uarda la profundidad /coordenada E1 para todos los p2<els del 9rea de dibu@ado" de manera 7ue cuando un p2<el va a ser dibu@ado" se mira si su coordenada E es menor 7ue la coordenada en el E-Fuffer para ese p2<el en pantalla. 5ara activarlo" hemos de aQadir las si#uientes l2neas de c,di#o" antes del dibu@ado:
glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); glClearDepth(1.0);

Con la llamada a #l>nable/. P?>5TVPT>ST1 habilitamos la comprobaci,n de la profundidad en el dibu@ado. Con #l?epthJunc/. P >=+A 1 decimos 7ue el nuevo p2<el se dibu@e si su coordenada E es m9s cercana al punto de visualiDaci,n" o i#ual" 7ue la 7ue ha! actualmente en E-Fuffer. Con #lClear?epth/0.%1 decimos 7ue cada veD 7ue 7uedamos borrar el buffer de profundidad" se inicialicen sus posiciones al valor 0.%.

Gor#e .arc2a -Fardok- /$%%)1

$4

Curso de introducci,n a -pen. /v0.01

5rimer contacto con -pen.

Gunto con esto" al borrar la pantalla" le indicamos al pro#rama 7ue inicialice el E-Fuffer con:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Jinalmente" s,lo nos 7ueda indicar al pro#rama 7ue" cuando se cree la ventana" se reserve espacio para el E-Fuffer. >sto lo indicamos al crear la ventana con:
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);

Tras estos cambios" la salida del pro#rama es la si#uiente:

Ji#ura *.0$. ?ibu@ado con E-Fuffer /salida del pro#rama Dbuffer-!es1

(.2./ ;erar<uas
Ya hemos visto los conceptos b9sicos para dibu@ar fi#uras en -pen. " ahora vamos a N@u#arO un poco con transformaciones ! matrices... .enalmente" los ob@etos se a#rupan en @erar7u2as. >n ellas" e<iste al#Ln ob@eto de cu!a posici,n depende la posici,n del resto de ob@etos. >l e@emplo m9s claro es el cuerpo humano: de la posici,n del tronco depende la posici,n de los braDos" ! de la posici,n de los braDos" la de las manos. 5ara representar @erar7u2as con -pen. " utiliDaremos las pilas de matrices. >l procedimiento es el si#uiente:
$; >S3?>-.host

Cap2tulo *: Conceptos b9sicos sobre -pen.

Curso de introducci,n a -pen. /v0.01

0. Se sitLa el elemento principal $. Se dibu@a el elemento principal *. Se apila la matriD actual /#l5ushBatri<1 ). Se sitLa el primer elemento secundario con respecto al primero &. Se dibu@a el primer elemento secundario A. Cuelta a la situaci,n del elemento principal /#l5opBatri<1 4. Se repite para los dem9s elementos secundarios 5ara ver el funcionamiento de las @erar7u2as vamos a realiDar un pro#rama 7ue dibu@e un cuadrado /fi#ura principal1 ! cuatro cuadrados secundarios" dibu@ados con respecto al principal. 5ara ello" definimos" por comodidad" una funci,n Ndibu@arCuadroO 7ue recibe el tamaQo del cuadrado" ! lo dibu@a centrado:
void dibujarCuadro(float tam) { glBegin(GL_QUADS); glVertex3f(-tam/2.0,tam/2.0,0.0); glVertex3f(-tam/2.0,-tam/2.0,0.0); glVertex3f(tam/2.0,-tam/2.0,0.0); glVertex3f(tam/2.0,tam/2.0,0.0); glEnd(); }

5ara dibu@ar la @erar7u2a" hacemos:


glColor4f(1.0,0.0,0.0,1.0); dibujarCuadro(1.0); glPushMatrix(); glTranslatef(0.0, 2.0, 0.0); dibujarCuadro(0.5); glPopMatrix(); glPushMatrix(); glTranslatef(0.0, -2.0, 0.0); dibujarCuadro(0.5); glPopMatrix(); ...

Con esto" hemos dibu@ado una sencilla @erar7u2a.

Gor#e .arc2a -Fardok- /$%%)1

$'

Curso de introducci,n a -pen. /v0.01

5rimer contacto con -pen.

Ji#ura *.0*. Gerar7u2a sencilla /salida del pro#rama @erar7uia-cuadro.c1

Si el procedimiento de dibu@ado se realiDa de manera recursiva" se puede obtener un fractal como el de la fi#ura:

Ji#ura *.0). Gerar7u2a fractal /pro#rama @erar7uia-cuadrorecursivo.c1

Camos a dibu@ar ahora una especie de Nfi#ura humanoideO" con un cuerpo /un cubo1" dos braDos /compuestos por tres partes" braDo" antebraDo ! manos" con dos cilindros ! un cubo respectivamente1 dos piernas /similares a los braDos1 ! una cabeDa /una esfera1. as fi#uras #eom8tricas las vamos a dibu@ar mediante funciones de la librer2a . +T.
*% >S3?>-.host

Cap2tulo *: Conceptos b9sicos sobre -pen.

Curso de introducci,n a -pen. /v0.01

>l c,di#o para el dibu@ado es el si#uiente: 0. 5rimero ale@amos la c9mara


glTranslatef(0,0,-16.0); $. Situamos el cuerpo ! lo dibu@amos. Como 7ueremos dibu@ar el cuerpo con un cubo" vamos a hacer 7ue en el e@e Y sea m9s #rande 7ue en el E" ! en el K un poco m9s... para ello lo escalamos. 5ero este escalado s,lo debe de afectar al cuerpo" por lo tanto" despu8s de dibu@ar el cuerpo" desharemos el escalado" utiliDando #l5ushBatri< ! #l5opBatri<. as medidas del cuerpo" las definimos como 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(); *. A partir del centro del cuerpo" situamos el braDo derecho. Va! 7ue tener en cuenta 7ue un cubo se dibu@a partir de su centro. ?espu8s vamos a rotar el braDo *% #rados alrededor del e@e E... si lo #iramos directamente" estaremos #irando el braDo por el centro... pero un braDo #ira por su parte superior... para ello" trasladamos el pivote de #iro a la parte superior del braDo" lo #iramos" ! devolvemos el pivote a su sitio" aplicamos el escalado" ! !a podemos dibu@ar el braDo a partir de un cubo. 5ara dibu@ar la mano" trasladamos hacia aba@o" aplicamos el escalado" ! dibu@amos. >n la mano" no hemos aplicado el pushBatri<" por7ue su escalado no va a afectar a nada 7ue se dibu@e despu8s" pero en caso contrario" deber2amos 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 mano glTranslatef(0,-(ARM_HEIGHT+ARM_WIDTH)/2,0); glColor3f(1,0.6,0.6); glScalef(ARM_WIDTH,ARM_WIDTH,ARM_LENGTH); glutSolidCube(1); glPopMatrix(); ). ?ibu@amos el resto del cuerpo de manera an9lo#a /ver c,di#o fuente en el ane<o1.

&. Jinalmente" dibu@amos la cabeDa" 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(); >l resultado del pro#rama es el si#uiente:

Gor#e .arc2a -Fardok- /$%%)1

*0

Curso de introducci,n a -pen. /v0.01

5rimer contacto con -pen.

Ji#ura *.0&. Salida del pro#rama Msimple#u!M

Camos a estudiar m9s detalladamente el #iro del braDo" !a 7ue puede resultar dif2cil de ver:

*$

>S3?>-.host

Cap2tulo *: Conceptos b9sicos sobre -pen.

Curso de introducci,n a -pen. /v0.01

Ji#ura *.0A. Hotaci,n del braDo /simple#u!1

>n el primer recuadro" tenemos el cuerpo @unto con el braDo" sin rotar. ?esplaDamos el braDo de manera 7ue su centro de #iro se encuentre en la posci,n sobre la 7ue ori#inalmente 7uer2amos pivotar el braDo. .iramos el braDo el 9n#ulo deseado" ! ahora" con ese #iro desplaDamos el braDo hacia aba@o" se#Ln su e@e de coordenadas" la misma distancia 7ue lo hab2amos desplaDado antes.

Gor#e .arc2a -Fardok- /$%%)1

**

Cap2tulo ): Animaciones

Curso de introducci,n a -pen. /v0.01

Captulo /: 0ni+aciones

Cabe canem (proverbio latino)

>n este cap2tulo vamos a describir de manera mu! breve c,mo animar las escenas 7ue creamos con -pen. . >n un principio" animar una fi#ura es al#o mu! sencillo. Fasta con: 0. actualiDar los datos de la fi#ura $. borrar la pantalla *. dibu@ar la fi#ura ). volver al punto 0

+.1 Los .ectores para animar ,iguras


>n muchos casos" dependiendo del tipo de animaci,n" es mu! recomendable el uso de vectores para representar hacia d,nde se mueve un ob@eto ! con 7u8 velocidad. 3ma#inemos 7ue tenemos un ob@eto 7ue se mueve a lo lar#o del e@e K" a la velocidad de 0 unidad por frame" ! 7ue actualmente est9 en la posici,n /-*"*"%1. 5odemos representar 7ue el ob@eto se encuentra situado por un vector de traslaci,n /-*"*"%1" de esta manera:

Gor#e .arc2a -Fardok- /$%%)1

*&

Curso de introducci,n a -pen. /v0.01

os vectores para animar fi#uras

$/412123 ./0"1"123

Ji#ura ).0. Hepresentaci,n de la posici,n ! velocidad con vectores

5 es el vector de posci,n" ! C el de direcci,n. Si despu8s de dibu@ar un frame" sumamos al vector de posci,n el de direcci,n" tenemos 7ue en el si#uiente frame el vector de posci,n ser9 5/-$"*"%1" con lo 7ue la fi#ura habr9 avanDado por el e@e K a la velocidad antes especificada. Si 7ueremos cambiar el movimiento" podemos variar la direcci,n del vector C" con lo 7ue se modificar9 la direcci,n del movimiento" o su m,dulo" con lo 7ue se modificar9 la velocidad del movimiento. Camos con un e@emplo. >l pro#rama 7ue vamos a elaborar va a consistir en una esfera 7ue se va a mover dentro de un cubo" de manera 7ue cuando lle#ue a una de las paredes va a rebotar:

Ji#ura ).$. Comportamiento del pro#rama MrebotesM

>l es7uema del dibu@ado ser9 el si#uiente:

Comprobar 7ue la esfera no est8 en el l2mite del cubo

S2 est9: invertir la componente del vector de direcci,n correspondiente al lado con el 7ue ha rebotado /p. e@. si hemos lle#ado al l2mite por la derecha" el valor de la K se volver9 ne#ativo...1

Sumar el vector de direcci,n al vector de posici,n de la esfera


>S3?>-.host

*A

Cap2tulo ): Animaciones

Curso de introducci,n a -pen. /v0.01

?ibu@ar la esfera Colver al comienDo del bucle

5ara este pro#rama vamos a definir una clase 7ue se encar#ue de representar la esfera" ! 7ue #uardar9 su posici,n ! velocidad. os m8todos 7ue proporciona esta clase se definen en la si#uiente tabla:
Mtodos Funcin

Tsphere (float maxpos, float Crea una instancia de la clase. a esfera speed); rebotar9 si lle#a a la posci,n I-Oma<posO" ! tendr9 una velocidad NspeedO. Su situaci,n ! direcci,n iniciales son aleatorias. void test();

Comprueba 7ue la fi#ura est8 dentro de los m9r#enes" ! si no le est9" corre#ir9 su direcci,n. ?espu8s" actualiDa su posci,n -btiene un vector con la posci,n de la esfera /en la posici,n %" la coord. K" en la 0 la Y ! en la $ la E1

void modifySpeed(float inc); 3ncrementa la velocidad en NincO float * getPosv();

Tabla ).0. B8todos de la clase TSphere

5ara las animaciones vamos a utiliDar varias funciones de . +T. 5or un lado" #lut?ispla!Junc/1" 7ue como !a hemos visto" dibu@a un frame" ! #lut3dleJunc/1" 7ue especifica la operaci,n 7ue se realiDar9 entre dos frames. Adem9s" a#ruparemos todas las llamadas a -pen. previas al dibu@ado de cual7uier frame en una funci,n de inicialiDaci,n. Con esto" el c,di#o 7uedar9 de la si#uiente manera: Camos a utiliDar una variable #lobal para indicar la posici,n de la esfera" ! otra para apuntar a la propia esfera:
float * pos; TSphere * sphere;

a inicialiDaci,n de -pen.

la vamos a realiDar en una funci,n 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); }

>n esta inicialiDaci,n vamos a hacer todo lo relativo a -pen. 7ue s,lo tiene 7ue hacerse una Lnica veD: establecer el color de fondo" habilitar el
Gor#e .arc2a -Fardok- /$%%)1 *4

Curso de introducci,n a -pen. /v0.01

os vectores para animar fi#uras

modo de perspectiva" ale@ar la c9mara" ! de paso" crear la esfera" 7ue se va a mover en el ran#o R-&"&S con una velocidad de 0. 5ara ale@ar la c9mara" utiliDaremos la funci,n N#lu ookAtO. >sta funci,n posiciona la c9mara" ahorrando la realiDaci,n de #iros ! traslaciones manuales" de la si#uiente manera: recibe tres ternas: la posci,n de la c9mara en el espacio" la posici,n hacia la 7ue est9 mirando" ! un vector 7ue seQala a la parte superior de la escena... en este caso:

5op

Ji#ura ).*. 5osici,n de la c9mara en el e@emplo Msphere-rebotesM

a c9mara se situa por delante" ! li#eramente por encima del e@e de coordenadas" ! al#o desplaDada en el e@e K. >st9 mirando hacia el centro de coordenadas" ! la parte superior de la escena est9 apuntada por el vector NtopO. a si#uiente funci,n ser9 la funci,n de dibu@ado de cada frame" su cuerpo ser9 el si#uiente:
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(); }

5or cada frame" se borra la pantalla" se dibu@a el cubo" se dibu@a la esfera /deshaciendo su transformaci,n" para no tener 7ue rehacer la transformaci,n de la c9mara en cada pasada1. Jinalmente vamos a crear una funci,n llamada NidleO 7ue va a e@ecutar la actualiDaci,n de la esfera entre dos frames" ! va a esperar ** milise#undos para dibu@ar el si#uiente foto#rama:
void idle(void) { sphere->test(); usleep(33);
*; >S3?>-.host

Cap2tulo ): Animaciones

Curso de introducci,n a -pen. /v0.01

glutPostRedisplay(); }

a Lltima llamada a #lut5ostHedispla!/1 hace 7ue tras la actualiDaci,n se dibu@e el si#uiente frame. 5ara re#istrar estas funciones hacemos" en el pro#rama principal:
initgl(); glutDisplayFunc(display); glutIdleFunc(idle);

5ero si e@ecutamos el pro#rama" vemos un pe7ueQo problema al visualiDar: ha! parpadeo /flickerin#1. >sto se debe a 7ue la pantalla est9 continuamente borr9ndose /se pone a ne#ro1 ! redibu@ando la im9#en. 5ara 7ue esto no ocurra hemos de utiliDar el llamado Ndoble bufferin#O.

+.2 'l doble bu,,ering


>l doble bufferin# es una t8cnica mu! simple" 7ue dibu@a la escena en un buffer fuera de la pantalla" mientras 7ue la im9#en de la pantalla no se toca para nada. +na veD 7ue la im9#en se ha dibu@ado en el buffer de fondo" se intercambia por el de la pantalla" de manera 7ue eliminamos el parpadeo. >l si#uiente frame lo dibu@aremos en lo 7ue antes era el buffer de pantalla /ahora oculto1" ! lue#o se cambiar9" ! as2 sucesivamente. Activar el doble bufferin# es al#o mu! sencillo. Vemos de indicar a . +T 7ue vamos a utiliDar doble bufferin# al crear la pantalla con . +TP?-+F >" en lu#ar de . +TPS3N. >:
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);

Y despu8s de dibu@ar un frame hemos de cambiar el buffer oculto por el activo con:
glutSwapBuffers();

+na veD aQadido esto" el c,di#o 7uedar2a como el 7ue se encuentra en el ane<o. >l resultado del pro#rama es el si#uiente:

Gor#e .arc2a -Fardok- /$%%)1

*'

Curso de introducci,n a -pen. /v0.01

>l doble bufferin#

Ji#ura ).). Salida del pro#rama Msphere-rebotesM

Y con una pe7ueQa modificaci,n /sphere-rebotes-multi1 podemos conse#uir una locura como esta:

)%

>S3?>-.host

Cap2tulo ): Animaciones

Curso de introducci,n a -pen. /v0.01

Ji#ura ).&. Salida del pro#rama Msphere-rebotesmultiM

Gor#e .arc2a -Fardok- /$%%)1

)0

Cap2tulo &: 3luminaci,n

Curso de introducci,n a -pen. /v0.01

Captulo 2: Ilu+inacin

Ratones: Los roedores durante muchos aos han estado "compartiendo" el alimento del hombre, son omnvoros, aunque muestran preferencia por las semillas de los cereales y productos derivados. Cuando stas faltan pueden comer las cosas ms extraas que nos podamos imaginar : jabn, cuero, cera, plsticos o papel etc (www.amezdy.com/ratones.htm)

a iluminaci,n nos permitir9 crear escenas m9s realistas con -pen. . Cada implementaci,n de -pen. puede mantener un nLmero de luces ma!or o i#ual a ; /nunca menor1" aun7ue no se recomienda abusar de 8stas" !a 7ue el consumo de C5+ por la utiliDaci,n de luces es mu! #rande.

-.1 'l modelo de iluminacin en

pen!L

a iluminaci,n de -pen. se basa en luces ! materiales. +na luD es una fuente de iluminaci,n para la escena. >mite un haD de luD de un color determinado" dividido en las tres componentes de color H.F. +n material determina la cantidad de cada color 7ue refle@a un ob@eto determinado. 5or e@emplo" si un ob@eto tiene un material de color ro@o -H.F/0"%"%1-" es decir" refle@a todo el color ro@o" ! es iluminado por una luD blanca -H.F /0"0"01-" refle@ar9 toda la componente de color ro@o" pero nada de la verde ! aDul" por lo 7ue se ver9 de color ro@o. Si este mismo ob@eto fuese iluminado por una luD verde -H.F/%"0"%1-" se ver2a de color ne#ro" al no tener nada de luD ro@a 7ue poder refle@ar. Adem9s" dependiendo del tipo de luD" el color
Gor#e .arc2a -Fardok- /$%%)1 )*

Curso de introducci,n a -pen. /v0.01

>l modelo de iluminaci,n en -pen.

final con el 7ue se vea el ob@eto puede verse afectado por el 9n#ulo de incidencia de la luD" la distancia a 8sta" etc.

2.1.1 Luces
Como se ha dicho" una luD aporta iluminaci,n a una escena" se#Ln unas determinadas componentes de color. A partir de ahora distin#uiremos entre fuente de luD" como entidad 7ue proporciona luD a una escena" ! luD" como aportaci,n de esa fuente a la iluminaci,n de la escena. +na fuente puede emitir tipos diferentes de luD" 7ue son complementarias" ! pueden darse a la veD para un cierto tipo de luD. os tipos de luD son:

N>mittedO /emitida1: es la luD emitida por un ob@eto. No se ve afectada por nin#Ln otro tipo de luD. 5or e@emplo" un fue#o emite una determinada luD" ! si lo miramos" lo veremos de ese color" independientemente del color de las luces 7ue est8n apuntando al fue#o. N?iffuseO /difusa1: es la luD 7ue indice sobre un ob@eto" ! proviene de un determinado punto. a intensidad con la 7ue se refle@a en la superficie del ob@eto puede depender del 9n#ulo de incidencia" direcci,n" etc. +na veD incide sobre un ob@eto se refle@a en todas direcciones. NSpecularO /especular1: es la luD 7ue" al incidir sobre un ob@eto" se ve refle@ada con un 9n#ulo similar al de incidencia. 5odemos pensar 7ue es la luD 7ue produce los brillos. NAmbientO /ambiental1: podemos considerarlo como los restos de luD 7ue aparecen defido a la refle<i,n residual de una luD 7ue !a se ha refle@ado sobre muchos ob@etos" ! es imposible determinar su procedencia. >s al#o as2 como la iluminaci,n #lobal de una escena.

2.1.2 5ateriales
+n material define" para un determinado ob@eto" 7u8 componentes refle@a de cada tipo de luD. 5or e@emplo" un pl9stico ro@o" emitir9 toda la componente ro@a de las luces ambiental ! difusa" pero #eneralmente emitir9 brillos de color blanco ba@o una luD blanca" por lo 7ue su componente especular ser9 de color blanco. ?e este modo" la componente de emisi,n ser9 ne#ra" puesto 7ue un plastico no emite luD /aun7ue si es un pl9stico radioactivo" puede emitir un leve destello fantasmal U-1 >n un modelo con iluminaci,n" el color de un ob@eto se define por su material" no por el color de sus v8rtices" tal ! como hemos visto hasta ahora.

2.1.(

or+ales
se calcula a nivel de v8rtice" es decir" por cada
>S3?>-.host

a iluminaci,n en -pen.
))

Cap2tulo &: 3luminaci,n

Curso de introducci,n a -pen. /v0.01

v8rtice" se calcula su color a partir del material activo" las luces activas" ! c,mo estas luces inciden sobre el v8rtice. 5ara saber c,mo incide una luD sobre un v8rtice" empleamos la normal del v8rtice" un vector" 7ue" #eneralmente" ser9 perpendicular a la cara 7ue estemos dibu@ando" aun7ue podremos variarlo para conse#uir distintos efectos. >n la fi#ura" podemos ver c,mo incide la misma luD en el mismo ob@eto" pero con las normales cambiadas.

L'z

L'z

Ji#ura &.0. >fecto de las normales en la iluminaci,n

-.2 #tili/ando iluminacin en 2.2.1 Luces

pen!L
es

>l primer paso para utiliDar la iluminaci,n en una aplicaci,n -pen. activarla" mediante la llamada

glEnable(GL_LINGHTING); +na veD activada" hemos de establecer las propiedades de cada luD en la escena" ! activarlas. a especificaci,n inicial de -pen. comtempla 7ue" al menos" cada implementaci,n debe de poder definir ; luces" identificadas por las constantes . P 3.VTn" d,nde ^n^ es el nLmero de la luD" comenDando por %.

5ara establecer las propiedades de una luD utiliDaremos llamadas a las funciones del tipo #l i#htZ/1. as propiedades de toda luD son las si#uientes:

5osici,n/?irecci,n:
)&

Gor#e .arc2a -Fardok- /$%%)1

Curso de introducci,n a -pen. /v0.01

+tiliDando iluminaci,n en -pen.

3ndica la posici,n/direcci,n de la luD" ! especifica si 8sta es una luD posicional o direccional. +na luD posicional tiene una posici,n concreta en el espacio" mientras 7ue una luD direccional consiste en un con@unto de haces de luD paralelos. +n e@emplo de luD posicional es una lampara" mientras 7ue" debido a su distancia" podr2amos considerar al sol como una fuente de luD direccional. as luces posicionales pueden ser de dos tipos: luces puntuales" 7ue emiten luD a su alrededor de manera radial" ! en todas direcciones" ! luces focales" 7ue emiten luD en una direcci,n concreta" en un radio de acci,n con forma de cono /como un foco1. 5odemos ver los diferentes tipos de luces en la si#uiente fi#ura:

L'z p'nt'al

L'z fo al
Ji#ura &.$. Tipos de luces

L'z dire

ional

5ara establecer esta propiedad utiliDaremos la llamada:


glLightfv(GL_LIGHTn,GL_POSITION,val_ptr); NvalPprtO es un puntero a un vector de cuatro componentes de tipo float" de la forma /<"!"D"w1. >n el caso de 7ue w sea 0" estaremos ante una luD posicional" ! su posci,n est9 determinada por /<"!"D1. Si w es %" la luD es direccional" ! su direcci,n es el vector /<"!"D1.

?irecci,n del foco: >n el caso de una luD focal" debemos establecer su direcci,n. >sto lo haremos con la llamada:
glLightfv(GL_LIGHTn,GL_SPOT_DIRECTION,val_prt); NvalPptrO es un puntero a un vector con la direcci,n" en formato /<"!"D1.

Apertura del foco: >l 9n#ulo de apertura del foco se define mediante:
glLightf(GL_LIGHTn,GL_SPOT_CUTOFF,val); NvalO e<presa en #rados la mitad del 9n#ulo de apertura del foco.

Atenuaci,n del foco: a atenuaci,n del foco /de#radaci,n de la intensidad a medida 7ue nos acercamos al borde1 se define mediante:

glLightf(GL_LIGHTn,GL_SPOT_EXPONENT,val); 3ntensidad de la luD:

)A

>S3?>-.host

Cap2tulo &: 3luminaci,n

Curso de introducci,n a -pen. /v0.01

?efine el color ambiental" difuso ! especular de la luD. Se define mediante la llamada:


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

Atenuaci,n de la luD ?efine la p8rdida de intensidad de la luD a medida 7ue nos ale@amos del foco /no afecta a las luces direccionales1. Se establece mediante: #l i#htf/. P 3.VTn". PRC-NSTANT_ 3N>AH_=+A?HAT3CS PATT>N+AT3-N"val1U >l factor de atenuaci,n de la luD se calcula se#Ln la f,rmula:

1 k c k l d k 2 q
+na veD establecidas las propiedades de una determinada luD" las activaremos con la llamada:
glEnable(GL_LIGHTn);

2.2.2 5ateriales
Tras definir las luces" antes de dibu@ar un ob@eto" hemos de definir su material. 5ara ello" estableceremos los valores de las diversas caracter2sticas del mismo" mediante las funciones del tipo #lBaterialZ/1. >stas funciones reciben tres par9metros: 0. Caras del pol2#ono a las 7ue se aplica el material. 5odemos aplicar el material a la cara frontal /. PJH-NT1 o a ambas caras del pol2#ono /. PJH-NTPAN?PFACT1. $. Caracter2stica 7ue definimos" mediante su correspondiente constante. *. Calor de la caracter2stica. as diferentes caracter2sticas son:

Color del material: ?efine el comportamiento del material para los distintos tipos de luD descritos anteriormente. >l color ambiental" difuso ! especular definen los colores del espectro 7ue este material refle@a de las luces 7ue recibe. >l color emitido es el tipo de luminosidad 7ue posee el material" intedependientemente de la luD 7ue le afecte. Se define mediante la llamada:
glMaterialfv(GL_FRONT[_AND_BACK],[GL_AMBIENT|GL_DIFUSSE| GL_AMBIENT_AND_DIFUSSE|GL_SPECULAR],val_ptr); NvalPptrO es un puntero a un con@unto de valores H.FA 7ue especifica el

Gor#e .arc2a -Fardok- /$%%)1

)4

Curso de introducci,n a -pen. /v0.01

+tiliDando iluminaci,n en -pen.

color de la componente espec2fica. Como antes se ha comentado" es habitual 7ue el comportamiento ante la luD difusa ! la ambiental sea el mismo" por lo 7ue es posible establecer ambos al mismo tiempo.

Frillo de los refle@os: a intensidad del brillo puede definirse a trav8s de la llamada:

glMaterialf(GL_FRONT[_AND_BACK],GL_SHININESS,val); Adem9s" podemos cambiar al#uno de los valores establecidos para los colores de un material mediante la funci,n #lColorBaterial/1. Bediante esta funci,n" 7ue debemos activar" podemos cambiar al#uno de los colores del material.

>sta opci,n se activa mediante:


glEnable(GL_COLOR_MATERIAL); ! una veD activada" establecemos la propiedad 7ue 7ueremos cambiar mediante: glColorMaterial(GL_FRONT[_AND_BACK],[GL_AMBIENT|GL_DIFUSSE| GL_AMBIENT_AND_DIFUSSE|GL_SPECULAR]); ! cambiamos el color refle@ado de ese tipo de luD mediante" por e@emplo: glColor3f(r_val,g_val,b_val); 5ara evitar complicaciones" debemos desactivar esta opci,n al terminar de usarla. Ceremos la utilidad de esta opci,n al#o m9s adelante" con un e@emplo.

2.2.( 1,e+plo: ilu+inacin direccional sobre una super*icie


Camos a ver c,mo se ha realiDado el e@emplo con el 7ue comprobamos el efecto de las normales sobre la iluminaci,n. 3nicialmente vamos a definir una serie de arra!s para los colores 7ue vamos a emplear: >l color ambiental ! difuso del material:
GLfloat mat_color [] = {0.0,1.0,1.0,1.0}; >l color difuso ! especular de la luD: GLfloat light_color [] = {1.0,1.0,1.0,1.0}; >l color ambiental de la luD /si al#o est9 fuera de la luD" no es iluminado1: GLfloat light_ambient [] = {0.0,0.0,0.0,1.0}; >l valor de las normales /como el cuadrado est9 en el plano /<"D1" las normales van hacia arriba1. GLfloat normal [] = {0.0,1.0,0.0}; >l valor de la direcci,n de la luD /es una luD situada en el e@e Y" en el infinito" lue#o sus ra!os ir9n hacia aba@o en el e@e Y1: GLfloat light_dir [] = {0.0,1.0,0.0,0.0}; Seleccionamos el color de fondo" ! borramos la pantalla:
); >S3?>-.host

Cap2tulo &: 3luminaci,n

Curso de introducci,n a -pen. /v0.01

glClearColor(0.0,0.0,0.0,0.0); glClear(GL_COLOR_BUFFER_BIT); Activamos la luD" ! sus caracter2sticas" e<cepto la direcci,n: 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); >stablecemos la perspectiva ! 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); >stablecemos la direcci,n de la luD: glLightfv(GL_LIGHT0,GL_POSITION,light_dir); >sta direcci,n la establecemos despu8s de la transformaci,n de la c9mara" por7ue 7ueremos 7ue" en este caso" est8 tambi8n sometida a la transformaci,n de la c9mara /por e@emplo" si dibu@amos una lampara" su posici,n en la escena ser9 relativa a d,nde est8 el espectador de la escena1.

?ibu@amos el cuadrado" ! antes de cada vertice" establecemos su normal. >n el caso de 7ue el s2mbolo NS3N. >PN-HBA O est8 definido" la normal ser9 siempre la misma. >n caso contrario" los v8rtices 0 ! * tendr9n una normal distinta" para lo#rar el efecto 7ue se muestra en la fi#ura &.0:
glBegin(GL_QUADS); #ifdef SINGLE_NORMAL glNormal3fv(normal); #else glNormal3f(1.0,1.0,-1.0); #endif glVertex3f(-1.0,0.0,-1.0); glNormal3fv(normal); glVertex3f(-1.0,0.0,1.0); #ifdef SINGLE_NORMAL glNormal3fv(normal); #else glNormal3f(-1.0,1.0,-1.0); #endif glVertex3f(1.0,0.0,1.0); glNormal3fv(normal); glVertex3f(1.0,0.0,-1.0); glEnd(); Jinalmente" forDamos el dibu@ado" esperamos" ! salimos del pro#rama: glFlush(); sleep(20); exit(0);

Gor#e .arc2a -Fardok- /$%%)1

)'

Curso de introducci,n a -pen. /v0.01

+tiliDando iluminaci,n en -pen.

2.2./ 1,e+plo: +oviendo un *oco alrededor de una es*era


>n este e@emplo vamos a mover un foco alrededor de una esfera" ! vamos a ver c,mo afectan los distintos tipos de luD. 5ara ello utiliDaremos dibu@ado con doble buffer" ! DFuffer. >l dibu@ado se har9 de este modo:

3nicialmente definimos las caracter2sticas de la luD:


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; as caracter2sticas 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; Camos a poner un pe7ueQo cono cu!o material ten#a una Nemisi,nO similar al color de la luD" 7ue nos indicar9 d,nde est9 el foco. >ste es su color de Nemisi,nO:

float focus_emission [] = {0.8,0.8,0.8,1.0}; ?efinimos un par de variables 7ue indican la rotaci,n del foco:

float rot_angle_y = 0.0; float rot_angle_x = 0.0; Vabilitamos el DFuffer ! establecemos el color de fondo: glEnable(GL_DEPTH_TEST); glClearColor(0.0,0.0,0.0,0.0); Activamos las luces ! sus caracter2sticas. a primera llamada establece 7ue las caras traseras de los pol2#onos no se iluminar9n: 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); >stablecemos 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); >stablecemos la perspectiva ! trasladamos la c9mara: glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0,1.0,1.0,100.0); glMatrixMode(GL_MODELVIEW); glTranslatef(0.0,0.0,-5.0);
&% >S3?>-.host

Cap2tulo &: 3luminaci,n

Curso de introducci,n a -pen. /v0.01

Todos los pasos anteriores se en#loban en lo 7ue ser2a la funci,n de inicialiDaci,n.

A continuaci,n tenemos el bucle de dibu@ado /#lut?ispla!Junc1. >n 8l" una veD borrada la pantalla" rotamos la luD" la posicionamos" ! establecemos su direcci,n" 7ue ser9n relativas a su rotaci,n. ?espu8s" dibu@amos un cono en la posici,n de la luD. >ste cono tendr9 como color de emisi,n el definido como tal. >l cambio lo hacemos con #lColorBaterial/1. +na veD dibu@ado" deshacemos estas transformaciones" dibu@amos la esfera" dibu@amos ! 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(); Jinalmente" definimos 7ue" entre frame ! frame /#lut3dleJunc1" la acci,n a realiDar ser9 actualiDar la rotaci,n 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 + ROT_INC/ (2*3.1416); glutPostRedisplay(); Y a7u2 tenemos un frame de la animaci,n 7ue hemos creado:

Gor#e .arc2a -Fardok- /$%%)1

&0

Curso de introducci,n a -pen. /v0.01

+tiliDando iluminaci,n en -pen.

Ji#ura &.*. Salida del pro#rama MlitsphereM

+n efecto curioso es el hecho de observar los refle@os de color ro@o 7ue se emiten desde los bordes de la esfera" #racias a 7ue hemos definido este color como el color NespecularO del material. Como puede observarse" en todos estos e@emplos ha! #ran cantidad de troDos de c,di#o 7ue se repiten. 5or ello" es conveniente la a#rupaci,n de estas llamadas en funciones de motores #r9ficos.

2.2.2 1,ercicio propuesto


Como final de este cap2tulo se propone un e@ercicio" consistente en una modificaci,n del pro#rama Nsphere-rebotes-multiO" de manera 7ue la escena est8 iluminada por una luD direccional" blanca" situada en el infinito" en una posici,n apuntada por el vector /0"0"01" ! cada esfera ten#a su propio color /aleatorio1 definido por las caracter2sticas ambiental ! difusa del material. >l cubo no debe de verse afectado por la luD al dibu@arse. >l resultado deber2a de ser parecido al si#uiente:

&$

>S3?>-.host

Cap2tulo &: 3luminaci,n

Curso de introducci,n a -pen. /v0.01

Ji#ura &.). Salida del pro#rama Ml-sphererebotes-multiM

+na soluci,n a este e@ercicio aparece en el ane<o A" ba@o el ep2#rafe Nlsphere-rebotes-multi.cppO.

Gor#e .arc2a -Fardok- /$%%)1

&*

Cap2tulo A: Te<turas

Curso de introducci,n a -pen. /v0.01

Captulo 3: =e#turas

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

as te<turas permiten personaliDar aLn m9s el material de un ob@eto" ! nos permiten obtener im9#enes mucho m9s realistas en nuestras escenas. 5or e@emplo" si 7ueremos dibu@ar una pared de ladrillo" tenemos dos opciones: dibu@ar cada ladrillo" definiendo su material con colores" ! dibu@ar el cemento entre los ladrillos" a base de pol2#onos" definiendo tambi8n su material" o dibu@ar un Lnico cuadrado con la e<tensi,n de la pared" ! hacer 7ue su material" sea" por e@emplo" la foto de una pared de ladrillo.

0.1 Las coordenadas de te%tura


5ara saber 7u8 partes de una im9#en se dibu@an en un pol2#ono /por e@emplo un tri9n#ulo1" utiliDamos lo 7ue se denominan coordenadas de te<tura" o coordenadas +C. >stas coordenadas est9n representadas por nLmeros reales de % a 0" de la si#uiente manera:

Gor#e .arc2a -Fardok- /$%%)1

&&

Curso de introducci,n a -pen. /v0.01

as coordenadas de te<tura

(0,0)

(1,0)

(0,1)
Ji#ura A.0. Coordenadas de te<tura

(1,1)

?e esta manera" si 7ueremos dibu@ar un tri9n#ulo con una te<tura" ! aplicacamos a cada v8rtice las coordenadas de te<tura indicadas en la fi#ura" tenemos el si#uiente resultado:

(0,0)

(1,0)

(0.5,0)

+
(0,1) (1,1) (0,1) (1,1)
Ji#ura A.$. Bapeado de te<tura

0.2 Aplicar las te%turas


5ara aplicar una te<tura tenemos 7ue se#uir una serie de pasos mu! definidos: 0. Creamos la te<tura $. ?efinimos las condiciones en 7ue se va a aplicar la te<tura *. Vabilitar la aplicaci,n de te<turas ). ?ibu@ar las escenas" proporcionando las coordenadas de te<tura Como e@emplo sencillo" vamos a ir viendo c,mo se ha creado el e@emplo del mapeado de te<turas:

Creaci,n de la te<tura RT>KTS: 5rimero hemos de obtener un identificador para la te<tura. 5ara ello pedimos a -pen. 7ue nos devuelva un identificador de te<tura libre:
int texture; glGenTextures(1,&texture);

&A

>S3?>-.host

Cap2tulo A: Te<turas

Curso de introducci,n a -pen. /v0.01

Activamos la te<tura como te<tura activa:


glBindTexture(GL_TEXTURE_2D,texture);

Creamos la te<tura. >l modo m9s sencillo de hacerlo es a trav8s de una funci,n de . + 7ue crea la te<tura ! sus variaciones a aplicar se#Ln la distancia a la 7ue se encuentre:
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 par9metro indicamos el tipo de te<tura. >n este caso /. PT>KT+H>P$?1 es una te<tura $?. os si#uentes par9metros indican el nLmero de b!tes por cada pi<el" 7ue depender9n de la im9#en /p. e@. * para H.F ! ) para H.FAU en este caso" la im9#en es de tipo H.F1" su anchura ! altura /7ue han de ser pares" ! mu! recomendable" mLltiplos de $1" el formato de los datos /. PH.F" . PH.FA"...1" el tipo de los datos" 7ue en nuestro caso vendr9 dado por b!tes sin si#no" por lo 7ue usaremos la constante . P+NS3.N>?PFYT>" ! finalmente" un puntero a los datos. >n este e@emplo" hemos utiliDado una estructura para #enerar la im9#en con el si#uiente formato:
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, [...] }

>ste formato de datos es producido de manera autom9tica por el pro#rama N.impO al #rabar una im9#en como un archivo en NcO.

?efinir las condiciones en 7ue se va a aplicar la te<tura: >stas condiciones se establecen a trav8s de la funci,n #lTe<>nvf/1.
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

>n nuestro caso" hemos especificado 7ue la te<tura se va a fundir con el color de fondo del pol2#ono /. PB-?+ AT>1" aun7ue bien podr2a sustituirlo /usando . PH>5 AC>1. a fusi,n con el color de fondo se utiliDa para aplicar la iluminaci,n a un ob@eto con te<tura. >n el e@emplo vemos c,mo se visualiDa un ob@eto iluminado" con la te<tura aplicada mediante . PB-?+ AT>" ! mediante . PH>5 AC>:

Gor#e .arc2a -Fardok- /$%%)1

&4

Curso de introducci,n a -pen. /v0.01

Aplicar las te<turas

Ji#ura A.*. ?iferencias entre . PH>5 AC> ! . PB-?+ AT>

Vabilitar la aplicaci,n de te<turas: Bediante:


glEnable(GL_TEXTURE_2D);

?ibu@ar la #eometr2a proporcionando las coordenadas de te<tura de cada v8rtice:


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 al#Ln momento 7ueremos cambiar la te<tura activa" tan s,lo hemos de indicar 7u8 te<tura 7ueremos activar mediante la llamada:
glBindTexture(GL_TEXTURE_2D,texture);

Nte<tureO es el identificador de la te<tura 7ue 7ueremos activar. >l c,di#o completo de los e@emplos utiliDados puede verse en el ane<o A.

3.2.1 >epeticin de te#turas


3ma#inemos 7ue 7ueremos dibu@ar una pared de ladrillos @unto a un cesped" ! tenemos estas dos te<turas" para la pared ! el suelo:

&;

>S3?>-.host

Cap2tulo A: Te<turas

Curso de introducci,n a -pen. /v0.01

Ji#ura A.). Te<turas para suelo ! pared

>l suelo va a ser u cuadrado" ! la pared un rect9n#ulo" ! vamos a mapear las es7uinas del suelo ! de la pared con las es7uinas de de las te<turas /c,di#o completo en el ane<o A1:
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(); +n aspecto a resaltar es 7ue la operaci,n #lFindTe<ture" para seleccionar cu9l es la te<tura activa en este momento" tiene 7ue realiDarse fuera del conte<to de #lFe#in/#l>nd" o de lo contrario no funcionar9.

>l resultado de dibu@ar esto es el si#uiente:

Gor#e .arc2a -Fardok- /$%%)1

&'

Curso de introducci,n a -pen. /v0.01

Aplicar las te<turas

Ji#ura A.&. Salida del pro#rama Mte<ture-no-clampM

Como podemos observar" los ladrillos de la pared salen demasiado alar#ados" ! el suelo demasiado distorsionado" por el hecho de 7ue estamos a#randando las te<turas para acomodarlas al tamaQo de los ob@etos. 5ero" 6! si repetimos las te<turas: 5or e@emplo" podr2amos repetir la te<tura de la en * divisiones verticales" ! la del suelo *A veces /A horiDontales < A verticales1. 5ara ello" debemos especificar 7ue 7ueremos repetir las te<turas con las si#uientes llamadas a funci,n:
glTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); a primera permite 7ue las te<turas se repitan en horiDontal" ! la se#unda" en vertical.

Con este cambio" podr2amos mapear las te<turas con coordenadas ma!ores a 0" de manera 7ue las te<turas se repetir2an" 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);
A% >S3?>-.host

Cap2tulo A: Te<turas

Curso de introducci,n a -pen. /v0.01

glVertex3f(-6.0,0.0,-6.0); glTexCoord2d(3.0,1.0); glVertex3f(6.0,0.0,-6.0); glTexCoord2d(3.0,0.0); glVertex3f(6.0,4.0,-6.0); glEnd(); a te<tura de la pared ha sido mapeada entre /%"%1 ! /*"01" para repetirla * veces horiDontalmente" ! la te<tura del suelo entre /%"%1 ! /A"A1. >l resultado es sensiblemente distinto:

Ji#ura A.A. Salida del pro#rama Mte<ture!es-clampM

Gor#e .arc2a -Fardok- /$%%)1

A0

Cap2tulo 4: 3nteracci,n b9sica con . +T

Curso de introducci,n a -pen. /v0.01

Captulo 4: Interaccin b)sica con GL!=

'Esto es to..., esto es to..., esto es todo amigos! (Porky)

Como Lltimo apartado" vamos a comentar de manera breve c,mo interactuar con las ventanas utiliDando . +T. Ya se ha comentado anteriormente 7ue . +T traba@a #eneralmente a trav8s de funciones CA FACT. >n la ma!or parte de los casos" tendremos 7ue re#istrar en . +T a 7u8 funci,n 7ueremos 7ue se llame cuando se produDca cierto evento sobre la ventana /pulsaci,n de una tecla" movimiento del rat,n...1.

1.1 2nteraccin con el teclado


5ara mostrar esto vamos a realiDar un e@emplo" consistente en modificar el pro#rama Nlit-sphereO de manera 7ue seamos nosotros 7uienes controlemos el movimiento de la luD. >sta estar9 7uiera" ! cuando to7uemos las teclas derecha/iD7uierda se mover9" rotando alrededor del centro de la esfera" alrededor del e@e Y" ! cuando pulsemos arriba/aba@o" lo har9 alrededor del e@e K. a funci,n 7ue nos permite re#istrar este evento es #lutSpecialJunc" 7ue se encar#a de mane@ar la pulsaci,n de teclas NespecialesO" como los cursores. a declaraci,n de esta funci,n es:
glutSpecialFunc(void (*func)(int key, int x, int y));
Gor#e .arc2a -Fardok- /$%%)1 A*

Curso de introducci,n a -pen. /v0.01

3nteracci,n con el teclado

>s decir" recibe un puntero a funci,n" 7ue no devuelve nada" ! recibe tres enteros: la tecla pulsada" ! la posci,n K e Y del rat,n en la pantalla. a rotaci,n alrededor de los e@es K e Y la vamos a controlar mediante dos variables #lobales /rotPan#leP<" rotPan#leP!1. >l c,di#o de la funci,n a la 7ue ha! 7ue llamar al pulsar al#una tecla NespecialO ser9 el si#uiente:
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 rotaci,n se#Ln la tecla pulsada. Adem9s" para facilitar la salida del pro#rama" vamos a aQadir 7ue" al pulsar la tecla N>sc.O" el pro#rama termine. 5ara ello utiliDaremos la funci,n #lutTe!boardJunc/1" 7ue recibir9 como par9metro un puntero a la si#uiente funci,n:
static void keys(unsigned char key, int x, int y) { switch (key) { case 27: exit(0); break; } glutPostRedisplay(); }

>l resto del pro#rama es pr9cticamente id8ndico al comentado en el cap2tulo de iluminaci,n /la funci,n idle se hace innecesaria" ! ha! 7ue dar de alta los dos nuevos mane@adores de eventos aQadiendo al pro#rama principal:
glutSpecialFunc(specialKeys); glutKeyboardFunc(keys);

1.2 3edimensionado de la .entana


Jinalmente" comentaremos 7ue es posible redimensionar la ventana ! su contenido mediante la funci,n de CA FACT #lutHeshapeJunc/1" a la 7ue se llama cada veD 7ue la ventana cambia de tamaQo" ! 7ue recibe el nuevo tamaQo de la ventana. >n caso de 7ue esto ocurra" tendremos 7ue volver a a@ustar la perspectiva /la relaci,n ancho/alto1 ! establecer el tamaQo de la nueva ventana de
A) >S3?>-.host

Cap2tulo 4: 3nteracci,n b9sica con . +T

Curso de introducci,n a -pen. /v0.01

visualiDaci,n:
void reshape(int width, int height) { GLfloat h = (GLfloat) height / (GLfloat) width; glViewport(0, 0, (GLint) width, (GLint) height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0,1.0,1.0,100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0,0.0,-5.0); glutPostRedisplay(); }

#lCiewport/1 nos permitir9 establecer 7u8 porci,n de la ventana ser9 el 9rea visualiDable. >n este caso" establecemos 7ue el 9rea visualiDable ser9 toda la ventana con su nuevo tamaQo. Adem9s" vamos a hacer 7ue" al pulsar la tecla NfO pasemos a pantalla completa/modo ventana de manera alternativa. 5ara ello" aQadiremos una variable #lobal 7ue indi7ue el modo actual de la pantalla" ! el tratamiento para la pulsaci,n de la tecla NfO" 7ue ser9:
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. >n caso contrario" se reposiciona ! reforma la ventana" para pasar de nuevo a modo ventana.

Gor#e .arc2a -Fardok- /$%%)1

A&

Cap2tulo ;: Hecursos de inter8s

Curso de introducci,n a -pen. /v0.01

Captulo ?: >ecursos de inter&s

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

>n este Lltimo ep2#rafe" me #ustar2a comentar al#unos recursos /libros ! p9#inas web1 7ue considero de #ran inter8s:

>l libro ro@o de -pen. /The Hed Fook1: es un libro b9sico para cual7uier persona 7ue 7uiera empeDar a pro#ramar con -pen. . Tambi8n se conoce como Nla biblia de -pen. O. NThe -pen. +tilit! Toolkit /. +T1 5ro#rammin# 3nterfaceO: contiene todo lo necesario para la utiliDaci,n de la librer2a . +T. os tutoriales de NneheO /nehe.#amedev.net/1: estos tutoriales tienen una #ran cantidad de informaci,n destinada" en #ran parte" a la pro#ramaci,n de @ue#os.

Buchas #racias por tu inter8s en este curso. 5ara cual7uier duda o su#erencia" no dudes en contactar conmi#o en Nshadow@bardok.netO.

Gor#e .arc2a -Fardok- /$%%)1

A4

Cap2tulo ;: Hecursos de inter8s

Curso de introducci,n a -pen. /v0.01

0ne#o 0: Cdi.o de los pro.ra+as de e,e+plo

Ja ja ja! Con este libro, tengo el poder de controlar hasta los rboles, y la propia ordenacin de todos los elementos...! (Bardok, en 1 de carrera, con el libro de EDA en la mano...)

A.a m&,irstopenglprogram.c
#include <GL/glut.h> 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(); glFlush();

Gor#e .arc2a -Fardok- /$%%)1

A'

Curso de introducci,n a -pen. /v0.01

Hecursos de inter8s

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 quadort4o.c
#include <GL/glut.h> 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 cuadrado glVertex3f(-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); } int main(int argc, char ** argv) { glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); glutInitWindowPosition(20,20); glutInitWindowSize(500,500); glutCreateWindow(argv[0]); glutDisplayFunc(display); glutMainLoop();
4% >S3?>-.host

Cap2tulo ;: Hecursos de inter8s

Curso de introducci,n a -pen. /v0.01

return 0; }

A.c quadpersp.c
#include <GL/glut.h> 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 distancia mnima 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 cuadrado glVertex3f(-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); 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; }

Gor#e .arc2a -Fardok- /$%%)1

40

Curso de introducci,n a -pen. /v0.01

Hecursos de inter8s

A.d /bu,,er5&es.c
#include <GL/glut.h> void display(void) { glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); // Activamos el el Z-Buffer glClearColor(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 distancia mnima 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 cuadrado glVertex3f(-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 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;
4$ >S3?>-.host

Cap2tulo ;: Hecursos de inter8s

Curso de introducci,n a -pen. /v0.01

A.e simplegu&.c
#include <GL/glut.h> #include <unistd.h> // Medidas del cuerpo #define #define #define #define #define #define #define #define #define #define BODY_HEIGHT BODY_WIDTH BODY_LENGTH ARM_HEIGHT ARM_WIDTH ARM_LENGTH LEG_HEIGHT LEG_WIDTH LEG_LENGTH HEAD_RADIUS 4.0 2.5 1.0 3.5 1.0 1.0 4.5 1.0 1.0 1.1

void display(void) { glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); // Activamos el el Z-Buffer glClearColor(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 distancia mnima es z=1.0, y la distancia mxima es z=100.0 glMatrixMode(GL_MODELVIEW); glTranslatef(0.0,0.0,-16.0); // Dibujamos el cuerpo glTranslatef(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 derecho glPushMatrix(); 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();
Gor#e .arc2a -Fardok- /$%%)1 4*

Curso de introducci,n a -pen. /v0.01

Hecursos de inter8s

// ya tenemos el brazo... la mano glTranslatef(0,-(ARM_HEIGHT+ARM_WIDTH)/2,0); glColor3f(1,0.6,0.6); glScalef(ARM_WIDTH,ARM_WIDTH,ARM_LENGTH); glutSolidCube(1); glPopMatrix(); // Dibujamos el brazo izquierdo glColor3f(0.0,0.3,0.8); glPushMatrix(); 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 brazo... la mano glTranslatef(0,-(ARM_HEIGHT+ARM_WIDTH)/2,0); glColor3f(1,0.6,0.6); glScalef(ARM_WIDTH,ARM_WIDTH,ARM_LENGTH); glutSolidCube(1); glPopMatrix(); //Dibujamos la pierna derecha glColor3f(0.0,0.3,0.8); glPushMatrix(); glTranslatef(-(BODY_WIDTH-LEG_WIDTH)/2,(BODY_HEIGHT+LEG_HEIGHT)/2,0); glPushMatrix(); glScalef(LEG_WIDTH,LEG_HEIGHT,LEG_LENGTH); glutSolidCube(1); glPopMatrix(); // ahora el pe glTranslatef(0,-(LEG_HEIGHT+LEG_WIDTH)/2,LEG_LENGTH); glColor3f(0.3,0.4,0.4); glScalef(LEG_WIDTH,LEG_WIDTH,LEG_LENGTH*2); glutSolidCube(1); glPopMatrix(); //Dibujamos la pierna izquierda glColor3f(0.0,0.3,0.8); glPushMatrix(); glTranslatef((BODY_WIDTH-LEG_WIDTH)/2,(BODY_HEIGHT+LEG_HEIGHT)/2,0); glPushMatrix(); glScalef(LEG_WIDTH,LEG_HEIGHT,LEG_LENGTH); glutSolidCube(1); glPopMatrix(); // ahora el pe glTranslatef(0,-(LEG_HEIGHT+LEG_WIDTH)/2,LEG_LENGTH); glColor3f(0.3,0.4,0.4); glScalef(LEG_WIDTH,LEG_WIDTH,LEG_LENGTH*2); glutSolidCube(1); glPopMatrix(); // Dibujamos la cabeza glColor3f(1,0.6,0.6); glPushMatrix(); glTranslatef(0,BODY_HEIGHT/2 + HEAD_RADIUS*3/4,0); glutSolidSphere(HEAD_RADIUS,10,10); glPopMatrix(); glFlush();
4) >S3?>-.host

Cap2tulo ;: Hecursos de inter8s

Curso de introducci,n a -pen. /v0.01

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., 6erarquia5cuadro.c
#include "GL/glut.h" void dibujarCuadro(float tam) { glBegin(GL_QUADS); glVertex3f(-tam/2.0,tam/2.0,0.0); glVertex3f(-tam/2.0,-tam/2.0,0.0); glVertex3f(tam/2.0,-tam/2.0,0.0); glVertex3f(tam/2.0,tam/2.0,0.0); glEnd(); } void display() { glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0,1.0,1.0,100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0,0.0,-6.0); glColor4f(1.0,0.0,0.0,1.0); dibujarCuadro(1.0); glPushMatrix(); glTranslatef(0.0, 2.0, 0.0); dibujarCuadro(0.5); glPopMatrix(); glPushMatrix(); glTranslatef(0.0, -2.0, 0.0); dibujarCuadro(0.5); glPopMatrix(); glPushMatrix(); glTranslatef(2.0, 0.0, 0.0); dibujarCuadro(0.5); glPopMatrix();

Gor#e .arc2a -Fardok- /$%%)1

4&

Curso de introducci,n a -pen. /v0.01

Hecursos de inter8s

glPushMatrix(); glTranslatef(-2.0, 0.0, 0.0); dibujarCuadro(0.5); glPopMatrix(); glFlush(); } 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.g 6erarquia5cuadro5recursi.o.c
#include "GL/glut.h" void dibujarCuadro(float tam) { glBegin(GL_QUADS); glVertex3f(-tam/2.0,tam/2.0,0.0); glVertex3f(-tam/2.0,-tam/2.0,0.0); glVertex3f(tam/2.0,-tam/2.0,0.0); glVertex3f(tam/2.0,tam/2.0,0.0); glEnd(); } void dibujarCuadroRecursivo(float tam) { if (tam > 0.005) { dibujarCuadro(tam); glPushMatrix(); glTranslatef(0.0, tam * 2.0, 0.0); dibujarCuadroRecursivo(tam / 2.0); glPopMatrix(); glPushMatrix(); glTranslatef(0.0, -tam * 2.0, 0.0); dibujarCuadroRecursivo(tam / 2.0); glPopMatrix(); glPushMatrix(); glTranslatef(tam * 2.0, 0.0, 0.0); dibujarCuadroRecursivo(tam / 2.0); glPopMatrix(); glPushMatrix(); glTranslatef(-tam * 2.0, 0.0, 0.0); dibujarCuadroRecursivo(tam / 2.0); glPopMatrix(); } }

4A

>S3?>-.host

Cap2tulo ;: Hecursos de inter8s

Curso de introducci,n a -pen. /v0.01

void display() { glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0,1.0,1.0,100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0,0.0,-6.0); glColor4f(1.0,0.0,0.0,1.0); dibujarCuadroRecursivo(1.0); glFlush(); } 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.4 sp4ere5rebotes.cpp
///////////////////////////////////////////////////////// // Fichero sphere-rebotes.cpp ///////////////////////////////////////////////////////// #include <GL/glut.h> #include <unistd.h> #include "sphere.h" float * pos; TSphere * sphere = NULL; 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); // Proyeccin perspectiva. El ngulo de visualizacin es de 60 grados, la razn ancho/alto es 1 (son inguales), la distancia mnima es z=1.0, y la distancia mxima es z=100.0 sphere = new TSphere(5,0.1);
Gor#e .arc2a -Fardok- /$%%)1 44

Curso de introducci,n a -pen. /v0.01

Hecursos de inter8s

glMatrixMode(GL_MODELVIEW); gluLookAt(3,3,14,0,0,0,0,1,0); } 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(); } void idle(void) { sphere->test(); usleep(33); glutPostRedisplay(); } int main(int argc, char ** argv) { glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH); glutInitWindowPosition(20,20); glutInitWindowSize(500,500); glutCreateWindow(argv[0]); initgl(); glutDisplayFunc(display); glutIdleFunc(idle); glutMainLoop(); return 0; } ///////////////////////////////////////////////////////// // Fichero sphere.h ///////////////////////////////////////////////////////// #ifndef sphere_h #define sphere_h #include <stdlib.h> #include <time.h> #include <math.h> typedef class TSphere { private: float maxpos; float pos[3]; float dir[3]; float speed; public: TSphere(float maxpos, float speed); void test(); void modifySpeed(float inc);
4; >S3?>-.host

Cap2tulo ;: Hecursos de inter8s

Curso de introducci,n a -pen. /v0.01

float * getPosv(); } TSphere; #endif ///////////////////////////////////////////////////////// // Fichero sphere.cpp ///////////////////////////////////////////////////////// #include "sphere.h" int pass=0; TSphere::TSphere(float maxpos, float speed) { this->maxpos = maxpos; if (!pass) { srandom(time(NULL)); pass = 1; } pos[0] = (random() % (int)maxpos) - maxpos/2; pos[1] = (random() % (int)maxpos) - maxpos/2; pos[2] = (random() % (int)maxpos) - maxpos/2; dir[0] = random(); dir[1] = random(); dir[2] = random(); float dirmod = sqrt(dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir [2]); dir[0] /= dirmod; dir[1] /= dirmod; dir[2] /= dirmod; dir[0] *= speed; dir[1] *= speed; dir[2] *= speed; } void TSphere::test() { ((pos[0] < -maxpos) || (pos[0] > maxpos))?dir[0]*=-1:0; ((pos[1] < -maxpos) || (pos[1] > maxpos))?dir[1]*=-1:0; ((pos[2] < -maxpos) || (pos[2] > maxpos))?dir[2]*=-1:0; pos[0] += dir[0]; pos[1] += dir[1]; pos[2] += dir[2]; } void TSphere::modifySpeed(float inc) { float factor = (speed+inc)/speed; speed += inc; dir[0] *= factor; dir[1] *= factor; dir[2] *= factor; }

Gor#e .arc2a -Fardok- /$%%)1

4'

Curso de introducci,n a -pen. /v0.01

Hecursos de inter8s

float * TSphere::getPosv() { return pos; }

A.i sp4ere5rebotes5multi.cpp
#include #include #include #include #define #define <GL/glut.h> <unistd.h> "sphere.h" <math.h> NUM_SPHERES SPHERE_RADIUS 50 0.3

float * pos; TSphere * sphere[NUM_SPHERES]; 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); for (int i=0;i<NUM_SPHERES;i++) sphere[i] = new TSphere(5,((random() % 10)/(float)20)+0.1); glMatrixMode(GL_MODELVIEW); gluLookAt(3,3,14,0,0,0,0,1,0); } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(1.0,1.0,1.0); glutWireCube(10); for (int i=0;i<NUM_SPHERES;i++) { glPushMatrix(); glColor3f(0.0,0.0,1.0); pos = sphere[i]->getPosv(); glTranslatef(pos[0],pos[1],pos[2]); glutSolidSphere(SPHERE_RADIUS,10,10); glPopMatrix(); sphere[i]->test(); } glFlush(); glutSwapBuffers(); } void idle(void) { usleep(33); glutPostRedisplay(); } int main(int argc, char ** argv) { glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); glutInitWindowPosition(20,20);
;% >S3?>-.host

Cap2tulo ;: Hecursos de inter8s

Curso de introducci,n a -pen. /v0.01

glutInitWindowSize(500,500); glutCreateWindow(argv[0]); initgl(); glutDisplayFunc(display); glutIdleFunc(idle); glutMainLoop(); return 0; }

A.6 normals5perp.c
#include <GL/glut.h> #include <stdlib.h> //#define SINGLE_NORMAL

void display(void) { GLfloat mat_color [] = {0.0,1.0,1.0,1.0}; GLfloat light_color [] = {1.0,1.0,1.0,1.0}; GLfloat light_ambient [] = {0.0,0.0,0.0,1.0}; GLfloat normal [] = {0.0,1.0,0.0}; GLfloat light_dir [] = {0.0,1.0,0.0,0.0}; glClearColor(0.0,0.0,0.0,0.0); glClear(GL_COLOR_BUFFER_BIT); 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); glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_color); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0,1.0,1.0,100.0); glMatrixMode(GL_MODELVIEW); glTranslatef(-0.3,-0.6,-4.0); glLightfv(GL_LIGHT0,GL_POSITION,light_dir); glBegin(GL_QUADS); #ifdef SINGLE_NORMAL glNormal3fv(normal); #else glNormal3f(1.0,1.0,-1.0); #endif glVertex3f(-1.0,0.0,-1.0); glNormal3fv(normal); glVertex3f(-1.0,0.0,1.0); #ifdef SINGLE_NORMAL glNormal3fv(normal); #else glNormal3f(-1.0,1.0,-1.0);
Gor#e .arc2a -Fardok- /$%%)1 ;0

Curso de introducci,n a -pen. /v0.01

Hecursos de inter8s

#endif glVertex3f(1.0,0.0,1.0); glNormal3fv(normal); glVertex3f(1.0,0.0,-1.0); glEnd(); glFlush(); sleep(20); 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.7 lit5sp4ere.c
#include <GL/glut.h> #include <unistd.h> #define float float float float float float float float float float ROT_INC 1.0

light_ambient [] = {0.0,0.2,0.0,1.0}; light_diffuse_specular [] = {0.8,0.8,0.8,1.0}; light_pos [] = {0.0,0.0,2.0,1.0}; spot_dir [] = {0.0,0.0,-1.0}; spot_cutoff = 30.0; spot_exponent = 1.0; mat_ambient_diffuse [] = {0.0,0.8,1.0,1.0}; mat_specular [] = {0.7,0.0,0.0,1.0}; mat_emission [] = {0.0,0.0,0.0,1.0}; mat_shininess = 0.4;

float focus_emission [] = {0.8,0.8,0.8,1.0}; float rot_angle_y = 0.0; float rot_angle_x = 0.0; void initgl() { glEnable(GL_DEPTH_TEST); glClearColor(0.0,0.0,0.0,0.0); 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);
;$ >S3?>-.host

Cap2tulo ;: Hecursos de inter8s

Curso de introducci,n a -pen. /v0.01

glEnable(GL_LIGHT0); glMaterialfv (GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_ambient_diffuse); glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular); glMaterialf(GL_FRONT,GL_SHININESS,mat_shininess); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0,1.0,1.0,100.0); glMatrixMode(GL_MODELVIEW); glTranslatef(0.0,0.0,-5.0); } void idle(void) { 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 + ROT_INC/ (2*3.1416); glutPostRedisplay(); } void display(void) { 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(); } int main(int argc, char ** argv) { glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); glutInitWindowPosition(20,20); glutInitWindowSize(350,350); glutCreateWindow(argv[0]); initgl(); glutDisplayFunc(display); glutIdleFunc(idle); glutMainLoop(); return 0; }

Gor#e .arc2a -Fardok- /$%%)1

;*

Curso de introducci,n a -pen. /v0.01

Hecursos de inter8s

A.l l5sp4ere5rebotes5multi.cpp
///////////////////////////////////////////////////////// // Fichero l-sphere.h ///////////////////////////////////////////////////////// #ifndef l_sphere_h #define l_sphere_h #include <stdlib.h> #include <time.h> #include <math.h> typedef class TSphere { private: float maxpos; float pos[3]; float dir[3]; float color[3]; float speed; public: TSphere(float maxpos, float speed); void test(); void modifySpeed(float inc); float * getPosv(); float * getColor(); } TSphere; #endif ///////////////////////////////////////////////////////// // Fichero l-sphere.cpp ///////////////////////////////////////////////////////// #include "l-sphere.h" int pass=0; TSphere::TSphere(float maxpos, float speed) { this->maxpos = maxpos; if (!pass) { srandom(time(NULL)); pass = 1; } pos[0] = (random() % (int)maxpos) - maxpos/2; pos[1] = (random() % (int)maxpos) - maxpos/2; pos[2] = (random() % (int)maxpos) - maxpos/2; dir[0] = random(); dir[1] = random(); dir[2] = random(); color[0] = (random() % 1001)/1000.0; color[1] = (random() % 1001)/1000.0; color[2] = (random() % 1001)/1000.0; float dirmod = sqrt(dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir [2]);
;) >S3?>-.host

Cap2tulo ;: Hecursos de inter8s

Curso de introducci,n a -pen. /v0.01

dir[0] /= dirmod; dir[1] /= dirmod; dir[2] /= dirmod; dir[0] *= speed; dir[1] *= speed; dir[2] *= speed; } void TSphere::test() { ((pos[0] < -maxpos) || (pos[0] > maxpos))?dir[0]*=-1:0; ((pos[1] < -maxpos) || (pos[1] > maxpos))?dir[1]*=-1:0; ((pos[2] < -maxpos) || (pos[2] > maxpos))?dir[2]*=-1:0; pos[0] += dir[0]; pos[1] += dir[1]; pos[2] += dir[2]; } void TSphere::modifySpeed(float inc) { float factor = (speed+inc)/speed; speed += inc; dir[0] *= factor; dir[1] *= factor; dir[2] *= factor; } float * TSphere::getPosv() { return pos; } float * TSphere::getColor() { return color; } ///////////////////////////////////////////////////////// // Fichero l-sphere-rebotes-multi.cpp ///////////////////////////////////////////////////////// #include <GL/glut.h> #include <unistd.h> #include "l-sphere.h" #include <math.h> #define #define NUM_SPHERES SPHERE_RADIUS 75 0.3

float light_color [] = {1.0,1.0,1.0,1.0}; float light_pos [] = {1.0,1.0,1.0,0.0}; float * pos; TSphere * sphere[NUM_SPHERES]; void initgl() { glEnable(GL_DEPTH_TEST); glClearColor(0.0,0.0,0.0,0.0); glLightfv(GL_LIGHT0,GL_DIFFUSE,light_color);
Gor#e .arc2a -Fardok- /$%%)1 ;&

Curso de introducci,n a -pen. /v0.01

Hecursos de inter8s

glLightfv(GL_LIGHT0,GL_SPECULAR,light_color); glEnable(GL_LIGHT0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0,1.0,1.0,100.0); for (int i=0;i<NUM_SPHERES;i++) sphere[i] = new TSphere(5,((random() % 10)/(float)20)+0.1); glMatrixMode(GL_MODELVIEW); gluLookAt(3,3,14,0,0,0,0,1,0); glLightfv(GL_LIGHT0,GL_POSITION,light_pos); } void idle(void) { usleep(33); glutPostRedisplay(); } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_LIGHTING); glColor3f(1.0,1.0,1.0); glutWireCube(10); glEnable(GL_LIGHTING); glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE); glEnable(GL_COLOR_MATERIAL); for (int i=0;i<NUM_SPHERES;i++) { glPushMatrix(); glColor4fv(sphere[i]->getColor()); pos = sphere[i]->getPosv(); glTranslatef(pos[0],pos[1],pos[2]); glutSolidSphere(SPHERE_RADIUS,10,10); glPopMatrix(); sphere[i]->test(); } glDisable(GL_COLOR_MATERIAL); glFlush(); glutSwapBuffers(); } int main(int argc, char ** argv) { glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); glutInitWindowPosition(20,20); glutInitWindowSize(400,400); glutCreateWindow(argv[0]); initgl(); glutDisplayFunc(display); glutIdleFunc(idle); glutMainLoop(); return 0; }

A.m triang5te%ture.c
#include <GL/glut.h>
;A >S3?>-.host

Cap2tulo ;: Hecursos de inter8s

Curso de introducci,n a -pen. /v0.01

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, ">@2>@2@B4@B4?A3>@2<>0;=/=?1@B4<>0CE7CE7DF8FH:HJ<LJ=OM@OM@NL>LJ >IG:GE8FE8" [... image data ...] "\6\22\23\16\11\12\5", }; void display(void) { int texture; glGenTextures(1,&texture); glBindTexture(GL_TEXTURE_2D,texture); glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); gluBuild2DMipmaps( GL_TEXTURE_2D, gimp_image.bytes_per_pixel, gimp_image.width, gimp_image.height,GL_RGB, GL_UNSIGNED_BYTE, gimp_image.pixel_data ); glEnable(GL_TEXTURE_2D); 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); glMatrixMode(GL_MODELVIEW); glTranslatef(0.0,0.0,-2.0); 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(); glFlush(); sleep(20); exit(0); } int main(int argc, char ** argv) { glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); glutInitWindowPosition(20,20); glutInitWindowSize(300,300); glutCreateWindow(argv[0]); glutDisplayFunc(display); glutMainLoop(); return 0; }

Gor#e .arc2a -Fardok- /$%%)1

;4

Curso de introducci,n a -pen. /v0.01

Hecursos de inter8s

A.n normals5perp5te%ture.c
#include <GL/glut.h> #include <stdlib.h> 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, ">@2>@2@B4@B4?A3>@2<>0;=/=?1@B4<>0CE7CE7DF8FH:HJ<LJ=OM@OM@NL>LJ >IG:GE8FE8" [... image data ...] "\6\22\23\16\11\12\5", }; void display(void) { GLfloat mat_color [] = {0.5,1.0,1.0,1.0}; GLfloat light_color [] = {1.0,1.0,1.0,1.0}; GLfloat light_ambient [] = {0.2,0.2,0.2,1.0}; GLfloat normal [] = {0.0,1.0,0.0}; GLfloat light_dir [] = {0.0,1.0,0.0,0.0}; int texture; glGenTextures(1,&texture); glBindTexture(GL_TEXTURE_2D,texture); glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); // Descomentar esta lnea y comentar la anterior en el caso // de querer utilizar GL_REPLACE //glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); gluBuild2DMipmaps( GL_TEXTURE_2D, gimp_image.bytes_per_pixel, gimp_image.width, gimp_image.height,GL_RGB, GL_UNSIGNED_BYTE, gimp_image.pixel_data ); glEnable(GL_TEXTURE_2D); glClearColor(0.0,0.0,0.0,0.0); glClear(GL_COLOR_BUFFER_BIT); 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); glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_color); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0,1.0,1.0,100.0); glMatrixMode(GL_MODELVIEW); glTranslatef(-0.3,-0.6,-4.0); glRotatef(90.0,1.0,0.0,0.0); glLightfv(GL_LIGHT0,GL_POSITION,light_dir); glBegin(GL_QUADS); glNormal3f(1.0,-1.0,1.0);
;; >S3?>-.host

Cap2tulo ;: Hecursos de inter8s

Curso de introducci,n a -pen. /v0.01

glTexCoord2d(0.0,0.0); glVertex3f(-1.5,0.0,-1.5); glNormal3fv(normal); glTexCoord2d(0.0,1.0); glVertex3f(-1.5,0.0,1.5); glNormal3f(1.0,-1.0,1.0); glTexCoord2d(1.0,1.0); glVertex3f(1.5,0.0,1.5); glNormal3fv(normal); glTexCoord2d(1.0,0.0); glVertex3f(1.5,0.0,-1.5); glEnd(); glFlush(); sleep(20); exit(0); } int main(int argc, char ** argv) { glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); glutInitWindowPosition(20,20); glutInitWindowSize(350,350); glutCreateWindow(argv[0]); glutDisplayFunc(display); glutMainLoop(); return 0; }

A.o te%ture5no5clamp.c 8 te%ture5&es5clamp.c


#include <GL/glut.h> // Los dos siguientes includes tienen las definiciones de las // imgenes en sendas estructuras de c. #include "grass_texture.c" #include "brick_texture.c" void display(void) { int texture_floor; int texture_wall; glGenTextures(1,&texture_floor); glBindTexture(GL_TEXTURE_2D,texture_floor); gluBuild2DMipmaps( GL_TEXTURE_2D, grass_texture.bytes_per_pixel, grass_texture.width, grass_texture.height,GL_RGB, GL_UNSIGNED_BYTE, grass_texture.pixel_data ); glGenTextures(1,&texture_wall); glBindTexture(GL_TEXTURE_2D,texture_wall); gluBuild2DMipmaps( GL_TEXTURE_2D, brick_texture.bytes_per_pixel, brick_texture.width, brick_texture.height,GL_RGB, GL_UNSIGNED_BYTE, brick_texture.pixel_data ); glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
Gor#e .arc2a -Fardok- /$%%)1 ;'

Curso de introducci,n a -pen. /v0.01

Hecursos de inter8s

// En caso de no querer repetir las texturas, comentar estas // dos lneas glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); glEnable(GL_TEXTURE_2D); glClearColor(0.1,0.6,1.0,0.0); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0,1.0,1.0,100.0); glMatrixMode(GL_MODELVIEW); gluLookAt(-0.0,3.0,6.0,0.0,2.0,0.0,0.0,1.0,0.0); // En caso de no querer repetir las texturas, mapearlas // entre 0 y 1 (sustituir 6 por 1 en glTexCoord2d). 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(); // En caso de no querer repetir las texturas, mapearlas // entre 0 y 1 (sustituir 3 por 1 en glTexCoord2d). 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); glVertex3f(6.0,0.0,-6.0); glTexCoord2d(3.0,0.0); glVertex3f(6.0,4.0,-6.0); glEnd(); glFlush(); sleep(20); exit(0); } int main(int argc, char ** argv) { glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); glutInitWindowPosition(20,20); glutInitWindowSize(300,300); glutCreateWindow(argv[0]); glutDisplayFunc(display); glutMainLoop(); return 0; }
'% >S3?>-.host

Cap2tulo ;: Hecursos de inter8s

Curso de introducci,n a -pen. /v0.01

A.p lit5sp4ere57e&b.c
#include <GL/glut.h> #include <unistd.h> #include <stdio.h> #define ROT_INC 1.0

float rot_angle_y = 0.0; float rot_angle_x = 0.0; int windowed = 1; 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(); } static void keys(unsigned char key, int x, int y) { switch (key) { case 27: exit(0); break; case 'f': if (windowed == 1) {glutFullScreen(); windowed = 0;} else{ glutPositionWindow(20,20); glutReshapeWindow(350,350); windowed = 0; } break; } glutPostRedisplay(); } static void display(void) { float light_pos [] = {0.0,0.0,2.0,1.0}; float spot_dir [] = {0.0,0.0,-1.0}; float mat_emission [] = {0.0,0.0,0.0,1.0}; float focus_emission [] = {0.8,0.8,0.8,1.0}; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); 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);
Gor#e .arc2a -Fardok- /$%%)1 '0

Curso de introducci,n a -pen. /v0.01

Hecursos de inter8s

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(); } void glInit() { float light_ambient [] = {0.0,0.2,0.0,1.0}; float light_diffuse_specular [] = {0.8,0.8,0.8,1.0}; float spot_cutoff = 30.0; float spot_exponent = 1.0; 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_shininess = 0.4; glEnable(GL_DEPTH_TEST); glClearColor(0.0,0.0,0.0,0.0); 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); glMaterialfv (GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_ambient_diffuse); glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular); glMaterialf(GL_FRONT,GL_SHININESS,mat_shininess); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0,1.0,1.0,100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0,0.0,-5.0); } void reshape(int width, int height) { GLfloat h = (GLfloat) height / (GLfloat) width; glViewport(0, 0, (GLint) width, (GLint) height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0,1.0,1.0,100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0,0.0,-5.0); glutPostRedisplay(); } int main(int argc, char ** argv)
'$ >S3?>-.host

Cap2tulo ;: Hecursos de inter8s

Curso de introducci,n a -pen. /v0.01

{ glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); glutInitWindowPosition(20,20); glutInitWindowSize(350,350); glutCreateWindow(argv[0]); glInit(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutSpecialFunc(specialKeys); glutKeyboardFunc(keys); glutMainLoop(); return 0; }

Gor#e .arc2a -Fardok- /$%%)1

'*

Curso de introducci,n a -pen. /v0.01

Hecursos de inter8s

:iblio.ra*a
-5>N. : -pen. - Vi#h 5erformance $?/*? .raphics" $%%*" http://www.open#l.or# H>?F--T: Gackie Naider" Tom ?avis and Bason (oo" -pen. .uide or ^The Hed Fook^. Addison-(esle!" 0'') . +T: Bark G. Til#ard" The -pen. 3nterface" 0''A 5ro#rammin#

+tilit! Toolkit /. +T1 5ro#rammin#

B>SA: Besa Vome 5a#e" $%%*" http://www.mesa*d.or# ?H3: ?H3 - ?irect Henderin# 3nfraestructure" $%%*" http://dri.sourcefor#e.net/ T>KT: -pen. Te<ture Tutorial" $%%*" http://www.nullterminator.net/#lte<ture.html

')

>S3?>-.host

También podría gustarte