Manual de OpenGL

27
Facultad de Ingeniería de Sistemas e Informática UNMSM Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I 1 Manual de OpenGL CURSO DE COMPUTACIÓN GRÁFICA

description

Manual OpenGL UNMSM

Transcript of Manual de OpenGL

Page 1: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

1

Manual de OpenGL

CURSO DE COMPUTACIÓN GRÁFICA

Page 2: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

2

Indice

Introducción ........................................................................................................................................ 3

Conceptos previos ............................................................................................................................... 4

Funcionamiento de OpenGL ............................................................................................................... 6

Primitivas de dibujo ............................................................................................................................ 9

Transformaciones .............................................................................................................................. 16

Estructura de un programa OpenGL ................................................................................................. 23

Compilación OpenGL ......................................................................................................................... 26

Page 3: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

3

Introducción OpenGL es una interface de software para el hardware grafico, esta interface consiste de una larga

serie de comandos para manipulación de objetos y operaciones sobre estos los cuales permiten

controlar la implantación realizada en la forma de una maquina de estados finitos, donde cada una

de las variables que determinan el estado se aplican a partir de ese punto hasta que se indique

explícitamente el cambio, así las variables de estado de OpenGL que vamos a utilizar mas

comúnmente son:

Color (de dibujo y de borrado).

Matrices de Transformación (GL_MODELVIEW, GL_PROYECTION).

Patrones (de líneas y de relleno).

Modo de dibujo de polígonos.

Buffers de dibujo.

Buffer de Stencil.

Buffer de profundidad (z-Buffer).

Buffer de acumulacion.

Page 4: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

4

Conceptos previos

Page 5: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

5

Page 6: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

6

Funcionamiento de OpenGL Para poder trabajar con OpenGL, primero se debe crear un contexto de trabajo, este contexto

contiene el estado actual de maquina finita, así como las referencias a los diferentes buffers de

trabajo, estos buffers se pueden ver como zonas de memoria correspondiendo a la pantalla en las

cuales OpenGL va a dibujar, en general a parte del buffer de color (GL_COLOR_BUFFER) que es

el buffer en el cual se van a dibujar las primitivas, existen otro tipo de buffers mas especializados.

La configuración en memoria de estos buffers (cuantos bits representan un pixel, etc) depende de la

manera como fue creado el contexto OpenGL y de las limitaciones del hardware, por esto no se

puede acceder directamente sino solo a través de las primitivas OpenGL.

OpenGL puede funcionar adicionalmente de dos maneras, de modo directo o indirecto:

Modo directo: las primitivas se van dibujando a medida que se van definiendo.

Instruccion -> Buffer de Color = Pantalla

Modo indirecto: las primitivas se guardan en una lista y solo se dibujan cuando el usuario

decida o la lista este llena, esto permite optimizar la fase de dibujo.

Instruccion-> Pila de instrucciones-> flush -> Buffer de Color = Pantalla

En este modo cuando se desea que OpenGL pinte lo que está en la lista se utiliza la instrucción

glFlush(): esta instrucción obliga a pintar y no espera a que el hardawre termine para continuar con

el programa, análogamente la glFinish() obliga a pintar pero espera a que el hw termine antes de

continuar con el programa.

En el modo indirecto, OpenGL permite definir dos buffers de colores (doublebuffer), asi un buffer

corresponde a lo que se ve en pantalla y otro a el buffer donde se esta pintando, de esta manera una

vez que se ha pintado todo lo deseado y se quiere que esto aparezca en pantalla se intercambian los

buffers, esta instrucción depende del sistema operativo para esto se utilizara la instruccion de la

libreria portable glut: glutSwapBuffers() (esta ejecuta implicitamente glFlush o glFinish), en este

modo glFlush y glFinish obligan a pintar en el buffer de dibujo pero esto NO sera visible hasta

intercambiar buffers.

Page 7: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

7

Arquitectura gráfica:

Page 8: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

8

Page 9: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

9

Primitivas de dibujo En OpenGL solo se pueden dibujar primitivas muy simples, tales como puntos lineas, cuadrados,

triangulos y polygonos, a partir de estas primitivas es posible construir primitivas mas complejas

como arcos y circulos aproximandolos por poligonos.

Toda primitiva de dibujo se construye con un par: glBegin(tipo_de_primitiva); glVertex2f(); ...

glEnd();

Donde tipo_de_primitiva puede ser cualquiera de las siguientes:

GL_POINTS: Cada vertice es un punto

GL_LINES: Cada par de vertices sucesivos es una linea

GL_LINE_STRIP: lineas conectadas.

GL_LINE_LOOP: lineas conectadas donde el ultimo y el primer vertice indican una linea

cerrando el poligono.

GL_POLYGON: poligono (relleno o no) donde los vertices sucesivos componiendolo se

dan el sentido contrario de las manecillas del reloj.

GL_QUADS: cuadrilateros separados, cada 4 vertices hacen un quad.

GL_QUAD_STRIP: tira de cuadrados unidos, cada par de vertices sucesivos forman un

cuadrado con el par anterior.

GL_TRIANGLES: Triángulos separados, cada 3 vértices hacen un triangulo.

GL_TRIANGLE_STRIP: tira de triángulos unidos (similara quad_strip).

Page 10: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

10

GL_TRIANGLE_FAN: Grupo de triangulos con un unico vertice comun a todos.

Puntos

Un punto se define mediante la función glVertex, esta función especifica las coordenadas del punto

dentro de la ventana de visualización. Con esta función podremos definir puntos en dos y tres

dimensiones, dependiendo del número de coordenadas que se detallan. OpenGL trabaja

normalmente en coordenadas homogéneas representadas por cuatro componentes, (x, y, z, h), por lo

tanto cuando estamos definiendo puntos en dos dimensiones el valor z coge el valor cero y h el

valor 1, en tres dimensiones h coge el valor 1.

El tipo especificado de coordenadas viene determinado a partir según los sufijos que siguen a la

función glvertex. Los sufijos que pueden seguir a la función serán, d (double), indica que las

coordenadas deben especificarse en valores double, f (float), i (integer) y finalmente s (short), por lo

tanto las coordenadas deberán indicarse con valores que correspondan al sufijo. Existe la

posibilidad de definir un punto mediante un vector que contenga las coordenadas, para ello

deberemos utilizar el sufijo v indicando que es un vector de coordenadas.

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

glVertex(v);

Para definir un punto o conjuntos de puntos debemos especificar las siguientes cláusulas

glBegin(GL_POINTS) y la cláusula glEnd(), detallando entre ambas las posiciones de cada punto,

así tenemos por ejemplo:

glBegin(GL_POINTS)

glVertex2f(50.4,34.6); //Punto 2D,en punto flotante

glVertex3i(10,20 34); //Punto 3D, en enteros

glEnd();

Por lo tanto para definir un conjunto de punto sobre la ventana de visualización podemos emplear la

estructura anterior.

Una vez definido los puntos podemos modificar su tamaño empleando la sentencia

glPointSize(valor), donde valor representa el tamaño con el que deseamos dibujar el punto.

Líneas

Page 11: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

11

De la misma forma que definimos puntos podemos definir líneas. Para definir una línea se precisan

dos puntos, estos dos puntos se definen de la misma forma que al definir un punto de la pantalla, es

decir con la función glVertex.

Existen diversas formas de definir líneas dependiendo del modo en que se describa en la cláusula

glBegin(modo), modo representará el tipo de línea que deseamos.

Modo Descripción

GL_LINES Genera una serie de líneas que no se conectan entre sí. Las líneas se

definen mediante los pares de puntos sucesivos, por lo tanto el número de

vértices debe ser par, en el caso de que fuera impar se ignoraría

GL_LINE_STRIP

Genera una serie de líneas pero que se conectan entre sí, es decir el punto

final de una línea es el punto inicial de la siguiente. Con este modo se

pueden generar figuras cerradas si el punto inicial coincide con el final.

GL_LINE_LOOP

Genera una serie de líneas conectadas entre sí, es parecido al modo

anterior pero este modo conecta automáticamente el punto inicial con el

punto final.

Podemos ver el efecto de los diferentes modos en el siguiente código:

glBegin (MODO);

glVertex2f(0.0, 0.0);

glVertex2f(1.0, 0.0);

glVertex2f(1.0, 1.0);

glVertex2f(0.0, 1.0);

glEnd;

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

GL_LINES GL_LINE_STRIP GL_LINE_LOOP

Page 12: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

12

El aspecto de las líneas también pueden modificarse, pudiendo crear líneas más gruesas y con

formato punteado, para ello se utilizará los comandos:

glEnable(GL_LINE_STIPPLE);

glLineStipple( factor, mascara);

glDisable(GL_LINE_STIPPLE);

Con estos comandos podemos conseguir líneas punteadas, la primera instrucción activa el modo de

línea punteada, mientras que el segundo define el estilo de la línea, donde factor es un valor que

está comprendido entre 1 y 255, este valor define la separación entre los trozos de la línea, mientras

que máscara, es un valor de 16 bits que se describe en hexadecimal, cada máscara define un

formato de línea, los valores van comprendidos entre 0x0000 hasta 0xAAAA.

Otra posibilidad que tenemos es modificar el grosor de la línea, para ello utilizaremos la siguiente

instrucción:

glLineWidth(tamaño);

Por defecto OpenGL define las líneas con tamaño 1.0, pero podemos modificarlo mediante la

sentencia anterior. Hay que tener en cuenta que una vez activado el tamaño hay que volver a

establecer si deseamos líneas con el tamaño por defecto.

Polígonos

OpenGL define los polígonos como secuencia de aristas, por lo tanto sigue con el mismo formato

especificado en los puntos anteriores.

Para generar polígonos tenemos los siguientes modos para la sentencia glBegin(modo), estos son:

Modo Descripción

GL_POLYGON Genera un simple poligono relleno con los vertices especificados.

Para generar un poligono debemos tener en cuenta que se debe

(0,1) (1,1)

(1,0) (0,0)

(0,1) (1,1)

(1,0) (0,0)

(0,1) (1,1)

(1,0) (0,0)

Page 13: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

13

garantizar tres cosas:

Como mínimo se precisan 3 vertices.

Las líneas no deben cruzarse.

Los vertices deben formar un poligono convexo, en

caso contrario OpenGL ignorará el vertice.

GL_TRIANGLES

Genera una serie de triangulos rellenos que no se conectan entre sí.

El número de vertices debe ser multiplo de 3, si el total de vertices es

menor de tres, OpenGL ignora los vertices que no forma un

triángulo.

GL_TRIANGLE_STRIP

Genera una serie de triángulos rellenos conectados entre sí, es decir

dos de los vertices de un triángulo son los vertices del siguiente

triángulo. Debemos saber que con N vertices se pueden crear N-2

triángulos. De igual forma que anteriormente el número de vertices

debe ser multiplo de tres, si no lo es se ignora aquellos que sobran.

GL_TRIANGLE_FAN

Genera un conjunto de triángulos rellenos conectados entre sí, con la

caracteristica de que todos los triángulos tiene un vertice en común.

El primer triángulo defien el vertice comun a todos los triángulos.

De igual forma que los anteriores el número de vertices debe ser

múltiplo de 3, si no lo es se ignora aquellos vertices que sobran.

GL_QUADS

Genera un conjunto de cuadrilateros rellenos sin conectar entre ellos.

El número de vertices que se requiere es multiplo de cuatro, si no se

verifica esto entonces OpenGL ignora los vertices que sobran. Cada

cuatro veretices se describe un cuadrilatero.

GL_QUAD_STRIP

Genera un conjunto de cuadrilateros rellenos que se conectan entre

sí, es decir dos vertices de un cuadrado se utilizan para generar el

siguiente cuadrilatero. Hay que tener en cuenta que si tenemos un

total de N vertices podremos obtener un total de N/2-1 cuadrados. El

número de vertices debe ser multiplo de cautro, si no se verifica

entonces los vertices que sobran son ignorados.

Gráficamente podemos ver las diferencias entre los modos para genera polígonos:

Page 14: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

14

Dentro del par glBegin, glEnd solo pueden ir instrucciones OpenGL para definir objetos tales como

vértices, y colores (existen otras mas complejas como normales y materiales) y no transformaciones

ni cambios de estado (diferentes a los especificados), adicionalmente dentro del par pueden ir

instrucciones de programación del lenguaje tales que ciclos, condicionales, llamados a funciones,

etc. Siempre y cuando no usen alguna de las funciones OpenGL no permitidas, i.e.:

v5

v2

v4

v1

vo

GL_POLYGON

v5 v4

v0

v1

v2

v3

GL_QUAD_STRIP

GL_TRIANGLES

v0 v1

v2

v4

v3

v5

GL_TRIANGLE_STRIP

v0

v1

v2

v3

GL_QUADS

v0

v1

v2

v3 v4

v5 v6

v7 v0

v1

v2

v3

v4

GL_TRIANGLE_FAN

Page 15: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

15

Muchas primitivas básicas tienen sufijos indicando el tipo del valor o variable que se le pasan como

parámetro, asi como el número de parámetros, asi una instrucción como p.ej. glVertex puede tener

2,3 o 4 parámetros, así comor recibir tipos enteros, flotantes, etc. O un vector conteniendo esos

parámetros Entonces en los manuales se escribe como: glVertex[234][sifd][v] quiere decir que se le

pueden pasar 2,3 ó 4 parametros mas el tipo o un vector, como minimo debe tener el numero de

parámetros y el tipo i.e.:

glVertex2f(1.0,0.0). o si se usa un vector v Glfloat v[3]={1.0,0.5} entonces seria glVertex2fv(v);

los tipos de datos también se pueden usar para definir variables, estos son:

Las primitivas más básicas de dibujo son entonces:

glRect[sid][v]: dibuja un rectángulo, NO puede estar en bloque glBegin/glEnd

glColor3[f][v]: para cambiar el color actual de dibujo, puede estar en bloque glBegin/glEnd

glVertex[234][sifd][v]: vértice de un punto, línea o polígono, SOLO puede estar entre

glBegin/glEnd

Variables de estado que afectan las primitivas anteriores (NO puede estar en bloque

glBegin/glEnd):

glPointSize(size): size= flotante indicando el tamaño de dibujo de un punto > 0.0, 1.0 por defecto.

glLineWidth(size): size= flotante indicando el ancho de dibujo de una línea > 0.0, 1.0 por defecto.

glLineStipple(factor,patron): factor = entero indicando un factor de escalamiento, patrón= short

sin signo conteniendo el patrón de bits par pintar la línea (punteado,etc..)..

glPolygonMode(cara,modo): cara corresponde al lado del polígono, si el que esta hacia el usuario

(pantalla) (GL_FRONT) o hacia el otro lado (GL_BACK) o los dos (GL_FRONT_AND_BACK),

el modo puede ser: relleno (GL_FILL), solo los vértices (GL_POINT), o solo el borde (GL_LINE).

Page 16: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

16

Otras funciones y variables de estado:

glClearColor(r,g,b): r,g,b son flotantes y definen el color de borrado de la pantalla (fondo).

glClear(mask): mask = GL_COLOR_BUFFER_BIT borra el buffer de dibujo con el color de

fondo definido.

Transformaciones

Una vez que tenemos definida la ventana donde realizaremos la escena debemos definir como va a

ser la visualización de esta escena, es decir, deberemos definir aspectos tales como, posición de la

cámara, a que punto mirara la cámara, que tipo de proyección utilizará,... etc.

En este apartado se mostrará como podemos manipular la cámara virtual, es decir el punto desde

donde vemos la imagen, junto con las transformaciones de visualización. Estos dos puntos nos

permitirán definir una visión de los objetos más realista. Otro de los apartados de esta sección será

manipular las transformaciones de proyección, y poder ver los efectos sobre la imagen.

Matriz de visualización

Para poder manipular los objetos de la escena debemos tener definida una matriz de visualización,

esta matriz será de cuatro por cuatro, es decir coordenadas normalizadas. Esta matriz se utiliza tanto

en dos como en tres dimensiones, la diferencia esta en la coordenada z, en el caso de dos

dimensiones z siempre tomará el valor cero, mientras que en tres dimensiones podrá tomar

diferentes valores.

OpenGl, facilita maneras para poder manipular la matriz de visualización. Antes de manipular la

matriz directamente debemos inicializar el modo para la matriz de operaciones, esto se consigue

con la función:

glMatrixMode(GL_MODELVIEW);

Una vez definido el modo de la matriz podemos asignarle un valor con las siguientes funciones:

glLoadIdentity()

Inicializada la matriz de transformaciones con la identidad.

glLoadMatrix(M)

Esta sentencia nos permite inicializar la matriz con un valor dado, especificado por el valor de M.

M puede ser definido como una matriz de cuatro por cuatro o bien por un vector de dieciséis

elementos, (m1, m2, m3,...). Hay que tener en cuenta que los valores de la matriz se especifica por

Page 17: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

17

columnas, es decir la primera columna corresponde a los valores del vector m1, m2, m3, m4, la

segunda columna corresponderá a los valores m5, m6, m7, m8, y así sucesivamente.

Como vemos estas dos sentencias nos permiten inicializar la matriz de transformaciones, para poder

realizar operaciones precisamos la siguiente instrucción:

glMultMatrix(M)

Esta sentencia nos permitirá multiplicar matrices, teniendo en cuenta que multiplicará la matriz

definida con una de las sentencias anteriores por la matriz M que definimos en este punto.

Vistas

OpenGl permite utilizar diferentes expresiones para definir la posición de la cámara y hacía donde

mira dicha cámara.

En OpenGl la representación de los ejes e coordenadas se describe en el siguiente gráfico.

Existe la posibilidad de manipular estos ejes cambiando la posición relativa de cada uno de ellos,

para ello OpenGl utiliza una serie de sentencias que nos definen como vamos a ver los ejes de

coordenadas y en consecuencia como se visualizará el objeto tridimensional.

gluLookAt()

Esta sentencia permite definir de forma especifica donde se situará la cámara, hacía donde mirara

está y cual va a ser el orden de los ejes de coordenadas.

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

z

y

x

Page 18: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

18

Esta sentencia tiene nueve argumentos que describen tres puntos, los valores de x0, y0, z0,

representa el punto hacia donde mira la cámara virtual, este punto normalmente se identifica en el

origen de coordenadas (0,0,0), ahora bien podemos definir nosotros el punto que más propicio sea

para nuestra escena.

Los siguientes tres argumentos representan el punto donde se situará la cámara de visualización,

estas coordenadas no deben coincidir con el punto al cual miramos.

Las últimas tres coordenadas representa el vector de vista hacía arriba, es decir indica cual será el

vector cuya dirección será hacia arriba, “apuntará hacia la parte superior del monitor”.

Para entender este caso podemos ver una serie de ejemplos donde se especifica cual es el vector y

como que da definido los ejes de coordenadas:

Como podemos ver según sea el valor del vector de vista hacia arriba el objeto que visualizaremos

tendrá un aspecto u otro. Normalmente para simplificar la visualización el vector de vista hacia

arriba se hace coincidir con uno de los ejes de coordenadas, como es el caso del primer gráfico.

glOrtho()

Se utiliza para especificar una proyección ortográfica. Este tipo de proyección define un volumen

de vista rectangular, concretamente define un paralelepípedo de tamaño infinito, este hecho nos

lleva a definir una serie de planos de corte para detallar con exactitud el volumen de vista.

OpenGl define la sentencia como:

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

z

y

x

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

z

y

x

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

Page 19: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

19

Estos seis argumentos definen la ventana de visualización y los planos de corte tanto cercano como

lejano.

Para definir la ventana de visualización es suficiente definir las coordenadas de dos esquinas de la

ventana, con estos dos valores queda totalmente definida.

Los valores de pcerca y plejos representan el plano cercano y el plano lejano. Hay que tener en

cuenta que el objeto a visualizar debe encontrarse dentro de ambos planos, si sobrepasan estos dos

planos el objeto se recortará automáticamente.

El objeto se visualizará entre los dos planos de recorte, en el caso que sobrepase estos planos se

recortará, y si el objeto es tan grande que la ventana de visualización esta dentro de él, no se

visualizará nada quedando la pantalla en negro.

Hay que tener en cuenta que si el plano de corte es negativo esté se encontrará detrás de la ventana

de visualización.

glFrustum()

Este comando se utiliza para definir una proyección perspectiva, se define de forma similar a la

proyección ortográfica pero con la diferencia que la proyección perspectiva define como volumen

de vista una pirámide, en consecuencia el objeto a visualizar tiene un aspecto mucho más realista.

La sentencia que utiliza OpenGl es:

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

Como vemos esta sentencia se define de forma similar a la utilizada para definir proyecciones

paralelas, de igual forma que anteriormente definimos planos de corte para limitar el volumen de

vista, que en este caso al ser una proyección perspectiva definirá un tronco piramidal.

(xwmax, ywmax)

(xwmin, ywmin)

Plano de corte lejano

Plano de corte cercano

pcerca

plejos

Page 20: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

20

Como vemos ambas sentencias se define de forma similar pero determina vistas muy diferentes

entre sí.

gluPerpespective()

Esta sentencia es una alternativa a la función glFrustum, la diferencia entre ambas está en la forma

de definir la ventana de visualización. Si en la sentencia glFrustum definimos los dos vértices

necesarios de la ventana, en la sentencia glPerpestive solamente definiremos el ángulo de apertura

de la cámara y la relación entre el largo y ancho del plano cercano de corte.

La sentencia en OpenGl será pues de la forma:

gluPerpective(apertura, aspect, pcerca, plejos);

Apertura corresponde al ángulo de apertura de la cámara virtual, este ángulo puede tomar valores

comprendidos entre 0º y 180º. El valor de aspect, vendrá dado por la relación entre el alto y ancho

del plano de corte, por lo tanto aspect toma el valor de alto plano dividido entre largo plano.

Los valores de pcerca y plejos corresponden a los plano de corte cercano y lejano, de forma similar

que en los casos anteriores.

(xwmax, ywmax)

(xwmin, ywmin)

Plano de corte lejano

Plano de corte cercano

pcerca

plejos

Punto de vista

Page 21: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

21

Las transformaciones se realizan multiplicando por las matrices y se aplican en sentido inverso al

que se escriben, esto es si quiero rotar y luego trasladar un objeto en el código, primero traslado,

luego roto y luego si pinto mi objeto (es también en sentido inverso al que se lee el código),

OpenGL trabaja con dos matrices diferentes:

GL_MODELVIEW: es la matriz donde se trabajan con las transformaciones.

GL_PROJECTION: es donde se define la relación mundo viewport.

Para cambiar de matriz a utilizar se usa la instrucción:

glMatrixMode(modo): es uno de los dos modos de matriz.

Adicionalmente, la matriz en uso se puede guardar y eliminar de una pila:

glPushMatrix(): coloca la matriz en la pila.

glPopMatrix(): quita la matriz de la pila.

La pila de la matriz de proyección tiene un límite máximo de 2 en la mayoria de las

implementaciones. Para trabajar con la matriz directamente se tiene:

Plano de corte lejano

Plano de corte cercano

pcerca

plejos

Punto de vista

Apertura

Page 22: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

22

glLoadIdentity(): inicializa la matriz actual con una matriz identidad.

glMultMatrix(matriz): matriz = vector de 16 flotantes con el que multiplica la matriz actual.

glLoadMatrix(matriz): matriz = vector de 16 flotantes con el que reemplaza la matriz actual.

glGetFloatv(modo,m): modo = uno de los modos de matriz.

matriz = vector de 16 flotantes en el que se recupera la matriz actual de OpenGL.

Para no tener que generar sus propias matrices, se proveen instrucciones de tranformacion:

glRotate[fd](a,x,y,z): rota un angulo a alrededor del vector x,y,z

glTranslate[fd](x,y,z): traslada una cantidad x,y,z.

glScale[fd](sx,sy,sz): multiplica cada coordenada por el valor de escalamiento correspondiente.

Page 23: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

23

Estructura de un programa OpenGL Para la creacion de programas OpenGL se va a utilizar la libreria GLUT, esta libreria permite

olvidarse de los problemas especificos de cada plataforma, La estructura general de un programa

utilizando la libreria GLUT es la siguiente (en C o C++ es las funciones de opengl son las mismas):

Page 24: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

24

Manejo de Buffers

Para utilizar los diferentes tipos de buffers de OpenGL estos se deben crear al crear el contexto

OpenGL, en el caso de la utilización de la libreria glut, al llamar la funcion: glutInitDisplayMode

(buffers), buffers es una combinación de valores indicando que buffers se deben crear i.e. para crear

un contexto con doble buffer rgba y z-buffer buffers seria = GLUT_RGBA | GLUT_DOUBLE |

GLUT_DEPTH, los valores para crear otro tipos de buffers son:

GLUT_STENCIL = buffer de stencil.

GLUT_ACCUM = buffer de acumulación.

Todos los buffers deben ser activados o desactivados dependiendo de la utilizacion con el comando

glEnable(param) o glDisable(param), donde param corresponde al tipo de test que se activa, i.e

param= GL_STENCIL_TEST para el buffer de stencil, o param=GL_DEPTH_TEST para el buffer

de profundidad (activado por defecto).

Los buffers de stencil, acumulacion y profundidad funcionan aplicando una serie de operaciones y

funciones sobre los valores que se van a escribir en el buffer, asi para manejar la funcion del buffer

de profundidad se utiliza la funcion glDepthFunc(funcion), donde funcion indica cuando pasa el

test de profundidad (GL_EQUAL, GL_LESS, GL_LEQUAL (por defecto), GL_NOTEQUAL,

GL_GREATER, GL_GEQUAL). En el caso de la funcion de test, se define glStencilFunc(funcion,

mascara), donde funcion son las mismas que para la profundidad, y mascara indica que bits del

stencil se utilizan. Adicionalmente a la funcion de stencil, se utiliza la operacion de stencil

glStencilOp(fallo,zfallo,zpaso) que especifica como se modifica el buffer de stencil dependiendo de

si la funcion del buffer stencil y z fallaron o pasaron, pueden ser GL_KEEP,GL_ZERO,

GL_REPLACE, GL_INCR, GL_DECR, GL_INVERT.

Manejo de Animacion y Timers

Opengl no maneja animacion ni timers directamente ya que esto depende del sistema operativo,

OpenGL solo se preocupa de colocar poligonos en la pantalla, y solo seria cuestion de ordenarle de

manera ciclica el repintar la pantalla con paramentros nuevos, el problema se encuentra cuando se

desea que la animacion se no bloqueante, la libreria GLUT nos facilita el manejo de la animacion de

dos maners independientemente del Sistema operativo de manera no bloqueante:

a. Función de animacion Idle, GLUT nos permite manejar la animacion definiendo una

funcion de animacion con la funcion glutIdleFunc(funcname), donde funcname es el

nombre de la funcion que se va a llamar para realizar la animacion, esta funcion no recibe

ni retorna parametro alguno, esta funcion se debe encargar de calcular los parametros de la

animacion y luego llamar la funcion de dibujo, esta no se debe llamar directamente sino con

Page 25: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

25

la funcion glutPostRedisplay() que quiere decir que solo se llama una vez se acabe de

calcular la funcion idle, esta funcion idle no se ejecuta de manera regular, solo se ejecuta

una vez se hallan procesado todos los eventos que recibe la aplicacion tales como teclado,

repintar, etc. Por lo tanto la velocidad de la animacion resultante puede no ser constante.

b. Funciones de Timers, para evitar el problema de la velocidad de animacion irregular y para

tener mas control sobre el tiempo de ejecucion de la funcion de animacion, glut nos permite

definir timers de a los cuales le asignamos una funcion que se debe ejecutar cada cierto

tiempo definido por el timer, para definir estos timers se utiliza la funcion:

glutTimerFunc(tiempo,funciontimer,valor), donde tiempo es el tiempo en milisegundos del

timer, funciontimer es la funcion a llamar la cual no devuelve nada pero recibe un

parametro entero (valor), valor es el parametro que se le va a pasar a la funcion. Esta

funcion se ejecuta dentro del tiempo determinado y termina, si se desea que se vuelva a

llamar, al final de la funcion se debe instalar de nuevo el timer. El valor sirve para

seleccionar diferentes acciones la proxima vez que se llame el timer, como estas funciones

no reciben parametros, cualquier resultado debe ser devuelto por una variable global.

Page 26: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

26

Compilación OpenGL

Compilacion de aplicaciones OpenGL en Windows

Para compilar un programa OpenGL suponiendo que se está en un sistema operativo MS-Windows,

con el compilador VisualC++, se debe recuperar la librería glut para windows (glut.h glut32.lib y

glut32.dll), los archivs .h y . lib se deben colocar en el directorio respectivo para includes y librerias

del VisualC, el archivo glut32.dll se debe colocar en el directorio system32 de windows idealmente

o en su defecto en el directorio donde va a quedar el ejecutable.

En el VisualC se debe crear un proyecto nuevo de tipo win32 o win32 consola (si se va a utilizar

GLUT NO! se debe crear proyecto de tipo MFC) En las opciones de compilacion del proyecto, en el

tabulador de encadenamiento, se debe adicionar las siguientes librerias en este orden especifico:

glut32.lib glu32.lib opengl32.lib.

Pero también se pueden utilizar distintos lenguajes de programación, como por ejemplo: C++

Builder o Delphi.

Compilacion de aplicaciones OpenGL en Linux

Para compilar un programa OpenGL suponiendo que se está en sistema operativo UNIX o Linux

con las librerias instaladas en lugares estandar se debe dar el siguiente comando suponiendo que

todo el programa está en un solo archivo:

Programa esta en C:

gcc -o nombre_ejecutable nombre_programa.c –lglut –lGLU –lGL lm

Programa esta en C++:

g++ -o nombre_ejecutable nombre_programa.c –lglut –lGLU –lGL lm

Si el programa esta compuesto por varios modulos C o C++ se debe realizar un archivo llamado:

Makefile, este archivo debe ser de la manera siguiente:

Page 27: Manual de OpenGL

Facultad de Ingeniería de Sistemas e Informática UNMSM

Escuela académico profesional de Ingeniería de Software Ciclo 2015 – I

27

Las identaciones en el archivo son tabulador no espacios en blanco!.

Solo se debe cambiar nombre programa por el nombre del archivo que contiene la funcion main, y

modulo1, modulo2, etc por los nombres de los otros archivos conteniendo otras funciones del

programa, para compilar solo basta dar en la linea de comandos el comando:

make

Para correr el programa ya sea que se haya compilado con la ayuda de make o directamente a mano

con gcc/g++ solo basta dar el comando:

./nombredeprograma

Para mas informacion sobre el comando make dar el comando: man make ,o en caso que este

falle:

info make

Para mas informacion sobre opciones gcc/g++ dar el comando: man gcc ,o: man g++