Intro OpenGL
Transcript of Intro OpenGL
Programación 3D con OpenGL bajo GNU/Linux
Roberto Garrido Martín (Ro)e-ghost
ESIDE's GNU Hi-tech and Open Source Team
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Índice
1. Introducción2. OpenGL y GNU/Linux3. Conceptos básicos sobre OpenGL4. Animaciones5. Iluminación6. Texturas7. Interacción con el teclado
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Introducción
● Objetivo del cursillo● ¿A quién va dirigido?● Recursos del cursillo
Roberto Garrido (Ro) - ESIDE e-ghost 2006
OpenGL y GNU/Linux
● La librería OpenGL– Estándar creado por Silicon Graphics en 1992– Versión 2.0
Roberto Garrido (Ro) - ESIDE e-ghost 2006
OpenGL y GNU/Linux
● La librería OpenGL– Tres partes funcionales
● La librería OpenGL● La librería GLU● GLX● Además, GLUT
Roberto Garrido (Ro) - ESIDE e-ghost 2006
OpenGL y GNU/Linux
● GNU/Linux y OpenGL– La librería Mesa
● Es Libre● Es una implementación software, excepto para ciertas
tarjetas, que usan el driver Mesa/Glide:– Voodoo1, Voodoo2, Voodoo Rush, Voodoo Banshee, Voodoo3
● Versión 6.5, que implementa OpenGL 1.5 (la implementación de especificación 2.0 está en camino)
Roberto Garrido (Ro) - ESIDE e-ghost 2006
OpenGL y GNU/Linux
● GNU/Linux y OpenGL– Xlibmesa
● Proporciona acceso a la aceleración gráfica por hardware, a través de DRI y si la tarjeta lo permite
– Este modo de acceso es usado por tarjetas 3dfx, Intel, Matrox, ATI
● DRI está presente en las implementaciones del servidor Xfree86 a partir de la versión 4, y hoy en las de Xorg
– Tarjetas NVIDIA, con su propia implementación de la librería OpenGL
● Se usa conjuntamente con Mesa (GLU)
Roberto Garrido (Ro) - ESIDE e-ghost 2006
OpenGL y GNU/Linux
● GNU/Linux y OpenGL(en resumen):
Roberto Garrido (Ro) - ESIDE e-ghost 2006
OpenGL y GNU/Linux
● ¿Qué necesitamos para programar con OpenGL bajo GNU/Linux?– Binarios de la librería OpenGL (Mesa, xlibmesa, o
drivers propietarios)– Paquetes de desarrollo de estas librerías (código
fuente de Mesa, xlibmesa-dev, para drivers propietarios, depende (nvidia-glx-dev))
– Compilador de C/C++ (gcc, g++)– Editor de texto (kate, gedit, vim, nano, ...)
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● OpenGL como máquina de estados– Activar y desactivar opciones y realizar acciones,
que tendrán como objetivo una representación en pantalla
– No es lo mismo dibujar un triángulo y activar una textura, que activar una textura y dibujar un triángulo
– Rotar y transladar algo, es distinto que transladarlo y rotarlo
● El orden en OpenGL es crítico en la mayoría de los casos
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● OpenGL como máquina de estados● En general, para dibujar un objeto:
1Activar opciones persistentes a la escena (luces, posicionar cámara)
2Activar las opciones de un objeto específico (su posición, textura)
3Dibujar el objeto
4Desactivar las opciones del objeto (volver a la posición anterior, desactivar su textura)
5Y volver al punto 2 hasta haber dibujado todos los objetos (siguiendo una jerarquía)
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● El espacio 3D– Cuatro dimensiones (x,y,z,w)
– Sistema de coordenadas inicial
Y
X
Z
1 0 0 00 1 0 00 0 1 00 0 0 1
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● El espacio 3D– Transformaciones de objetos
● Translación
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● El espacio 3D– Transformaciones de objetos
● Rotación
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● El espacio 3D– Transformaciones de objetos
● Escalado
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● El espacio 3D– Transformaciones de objetos
● Toda transformación construye una matriz de cuatro dimensiones que se multiplicará por la matriz de transformación actual
● Al transladar un objeto 3 unidades en el eje X:
1 0 0 30 1 0 00 0 1 00 0 0 1
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL● El espacio 3D
– Transformaciones de objetos● Si aplicamos dicha transformación a la transformación
inicial, obtenemos:
● Si ahora dibujamos el punto (1,0,0), quedará desplazado, de la siguiente forma:
1 0 0 00 1 0 00 0 1 00 0 0 1
1 0 0 30 1 0 00 0 1 00 0 0 1
1 0 0 30 1 0 00 0 1 00 0 0 1
1 0 0 30 1 0 00 0 1 00 0 0 1
4001
1 0 0 1
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● El espacio 3D– Las coordenadas homogéneas
● Varias razones:– Uniformidad de operaciones con matrices– Conceptos relativos a profundidad
● Son cuatro coordenadas, de forma que:– El punto 3D (1, 2, 3) es traducido a (1, 2, 3, 1.0)– El punto 2D (1, 2) es traducido a (1, 2, 0.0, 1.0)– En general, el punto (x,y,z,w) en coordenadas homogéneas es
equivalente al punto 3D (x/w,y/w,z/w)● Si w=0, punto en el infinito con dirección (x,y,z)
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Sobre Glut– Funciones para la creación de ventanas
independiente de plataforma– Lo veremos en los ejemplos– Funciones de callback
● Las funciones básicas de OpenGL– Activación/Desactivación de opciones
● glEnable(<OPTION>), glDisable(<OPTION>)– glEnable(GL_LIGHTING)
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Las funciones básicas de OpenGL– Las matrices y OpenGL
● Transformación de objetos: matriz de visualización/modelado
● Matriz de proyección: información de la “cámara”● Cambiar modo de matriz:
– glMatrixMode(GL_PROJECTION)– glMatrixMode(GL_MODELVIEW)
● Guardar y restaurar valores en la pila– glPopMatrix() y glPushMatrix()
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Las funciones básicas de OpenGL– Las matrices y OpenGL
● Para dibujar jerarquías de objetos
● glLoadIdentity() carga la matriz unidad
<transformación común para la escena>glPushMatrix();
<transformación propia del elemento 1><dibujado del elemento 1>
glPopMatrix(); // Volvemos a la transformación comúnglPushMatrix();
<transformación propia del elemento 2><dibujado del elemento 2>
glPopMatrix(); // Volvemos a la transformación común...
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Las funciones básicas de Opengl– El dibujado en OpenGL
● Para dibujar en OpenGL:– Habilitar modo de dibujado– Establecer opciones de dibujado de cada vértice– Dibujar cada vértice– Finalizar el modo de dibujado
● glBegin(<MODO_DE_DIBUJADO>)
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGLParámetro Descripción
GL_POINTS Se dibujan vértices separadosGL_LINES Cada par de vértices se interpreta como una líneaGL_POLYGON Los vértices describen el contorno de un polígonoGL_TRIANGLES Cada triplete de vértices de interpreta como un triánguloGL_QUADS Cada cuarteto de vértices se interpreta como un
cuadriláteroGL_LINE_STRIP Líneas conectadasGL_LINE_LOOP Líneas conectadas, con unión entre el primer y último
vérticeGL_TRIANGLE_STRIP Se dibuja un triángulo, y cada nuevo vértice se interpreta
con un triángulo entre los dos anteriores vértices y el nuevoGL_TRIANGLE_FAN Se dibujan triángulos con un vértice comúnGL_QUAD_STRIP Igual que el TRIANGLE_STRIP, con cuadriláteros
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Las funciones básicas de Opengl– El dibujado en OpenGL
● Establecer atributos de cada vértice:– Color: glColor*– Normal: glNormal*– Coordenadas de textura: glTexCoor*
● Dibujado de vértices:– glVertex*
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Las funciones básicas de Opengl– El color en OpenGL
● Modos RGBA e Indexado– La orientación de las caras en OpenGL
● Cara delantera: orden antihorario
1
3
2
4
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Las funciones básicas de Opengl– Las transformaciones en OpenGL
● Operaciones que permiten situar objetos en el espacio:– glTranslate*: transladar un objeto en el espacio– glRotate*: rotar un objeto– glScale*: escalar un objeto– glMultMatrix: multiplicar la matriz actual por una dada
● NO es lo mismo rotar y luego transladar, que transladar y luego rotar
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Las funciones básicas de Opengl● La proyección en OpenGL
● Cómo afecta la posición de un objeto a su visualización● Proyección ortográfica
● glOrtho(Xmin, Xmax, Ymin, Ymax, Znear, Zfar);
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Las funciones básicas de Opengl– La proyección en OpenGL
● Proyección perspectiva● gluPerspective()
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Primer contacto con OpenGL ;)– Mi primer programa en OpenGL
● Includes#include <GL/glut.h>
● Función mainint main(int argc, char * argv){
glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);glutInitWindowPosition(20,20);glutInitWindowSize(500,500);glutCreateWindow(argv[0]);
glutDisplayFunc(display);glutMainLoop();return 0;
}
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Mi primer programa en OpenGL– Función display
void display(void){glClearColor(0.0,0.0,0.0,0.0);// Color de fondo: negroglClear(GL_COLOR_BUFFER_BIT);// Boramos la pantallaglMatrixMode(GL_PROJECTION);// Modo proyecciónglLoadIdentity();// Cargamos la matriz identidadglOrtho(-1.0,1.0,-1.0,1.0,-1.0,1.0);// Proyección ortográfica, dentro del cubo señaladoglMatrixMode(GL_MODELVIEW);// Modo de modelado
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Mi primer programa en OpenGL– Función display
glBegin(GL_TRIANGLES);// Dibujamos un triánguloglColor3f(1.0,0.0,0.0);// Color del primer vértice: rojoglVertex3f(0.0,0.8,0.0);// Coordenadas del primer vérticeglColor3f(0.0,1.0,0.0);// Color del segundo vértice: verdeglVertex3f(-0.6,-0.2,0.0);// Coordenadas del segundo vérticeglColor3f(0.0,0.0,1.0);// Color del tercer vértice: azúlglVertex3f(0.6,-0.2,0.0);// Coordenadas del tercer vértice
glEnd();// Terminamos de dibujarglFlush();// Forzamos el dibujadosleep(10);// Esperamos 10 segundosexit(0);// Salimos del programa}
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Mi primer programa en OpenGL– glClearColor: color del buffer al ser borrado– glClear(GL_COLOR_BUFFER_BIT): borrar el buffer– glOrtho– Dibujamos el triángulo– Compilamos:
– Ejecutamos:
roberto@garridocuarto:~$gcc myfirstopenglprogram.c -lglut -lGL -lGLU -o myfirstopenglprogram
roberto@garridocuarto:~$./myfirstopenglprogram
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Mi primer programa en OpenGL
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Primer contacto con OpenGL– Visualizando en perspectiva...
● Código de dibujadoglBegin(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 vértice (superior-izquierda) glVertex3f(-0.5,-0.5,0.5); // Coordenadas del segundo vértice (inferior-izquierda) glVertex3f(0.5,-0.5,0.5); // Coordenadas del primer vértice (inferior-derecha) glVertex3f(0.5,0.5,-0.5); // Coordenadas del primer vértice (superior-derecha)glEnd();// Termina
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Visualizando en perspectiva...– Guardamos y ejecutamos
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Visualizando en perspectiva...– Primera modificación
– Segunda modificación
gluPerspective(60.0,1.0,1.0,100.0);// Proyección perspectiva. El ángulo de visualización es de 60 grados, la razón ancho/alto es 1 (son inguales), la distancia mínima es z=1.0, y la distancia máxima es z=100.0
glTranslatef(0.0,0.0,-2.0);// Alejamos el cuadrado del observador dos unidades en el eje Z
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Visualizando en perspectiva...
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Primer contacto con OpenGL– Ocultación de objetos (Z-Buffer)
● Añadimos el triángulo (0.0, 0.5, 0.0), (-0.7, -0.5, 0.0),(0.7, -0.5, 0.0)
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Ocultación de objetos (Z-Buffer)– Añadimos antes del dibujado
– Con glEnable(GL_DEPTH_TEST) habilitamos la comprobación de profundidad en el dibujado
– Con glDepthFunc(GL_LEQUAL) se dibuja el pixel si está a igual o menor distancia al observador
– Con glClearDepth(1.0) cada vez que se borra el z-buffer, se inicializan sus posiciones al valor 1.0
glDepthFunc(GL_LEQUAL);glEnable(GL_DEPTH_TEST);glClearDepth(1.0);
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Ocultación de objetos (Z-Buffer)– Al borrar la pantalla inicializamos el z-buffer
● glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
– Al iniciar el programa, reservamos espacio para el z-buffer
● glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Ocultación de objetos (Z-Buffer)
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Primer contacto con OpenGL– Jerarquías
● El ejemplo del cuerpo humano● Se usan pilas de matrices
1. Se sitúa el elemento principal
2. Se dibuja el elemento principal3. Se apila la matriz actual (glPushMatrix)4. Se sitúa el primer elemento secundario con respecto al primero5. Se dibuja el primer elemento secundario6. Vuelta a la situación del elemento principal (glPopMatrix)7. Se repite para los demás elementos secundarios
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Jerarquías– Programa que dibuja un cuadrado y cuatro
secundarios– Función dibujarCuadrado
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();}
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL● Jerarquías
– Para dibujar la jerarquía, 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();...
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Jerarquías
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Jerarquías– De manera recursiva
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Jerarquías– Figura humanoide a base de cubos ;)
● Primero, alejamos la cámara– glTranslatef(0,0,-16.0);
● Situamos el cuerpo y lo dibujamosglTranslatef(0,BODY_HEIGHT/2,0);glPushMatrix(); glScalef(BODY_WIDTH,BODY_HEIGHT,BODY_LENGTH); glColor3f(0.0,0.3,0.8); glutSolidCube(1);glPopMatrix();
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● A partir del centro del cuerpo, situamos el brazo derecho
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();
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Dibujamos el resto del cuerpo de la misma forma (ver código anexo)
● Y finalmente, dibujamos la cabeza, como una esfera
glColor3f(1,0.6,0.6);glPushMatrix(); glTranslatef(0,BODY_HEIGHT/2 + HEAD_RADIUS*3/4,0); glutSolidSphere(HEAD_RADIUS,10,10);glPopMatrix();
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Conceptos básicos sobre OpenGL
● Jerarquías– Figura humanoide
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Animaciones
● Para animar una figura
1 Actualizar los datos de la figura
2 Borrar la pantalla
3 Dibujar la figura
4 Volver al punto 1
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Animaciones
● Los vectores para animar figuras– Objeto que se mueve en el eje X a 1 ud por frame– Tiene un vector de posición y otro de dirección
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Animaciones
● Ejemplo de la esfera que rebota dentro de un cubo
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Animaciones
● Esquema de dibujado– Comprobar que la esfera no esté en el límite del
cubo● Si está: invertir la componente del vector de dirección
correspondiente al lado con el que ha rebotado– Sumar el vector de dirección al vector de posición
de la esfera– Dibujar la esfera– Volver al comienzo del bucle
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Animaciones
● Definición de la clase TSphereMétodos Función
TSphere (float maxpos, float speed); Crea una instancia de la clase. La esferarebotará si llega a la posción +-”maxpos”,y tendrá una velocidad “speed”. Susituación y dirección iniciales sonaleatorias
void test(); Comprueba que la figura esté dentro delos márgenes, y si no le está, corregirá sudirección. Después, actualiza su posción
void modifySpeed(float inc); Incrementa la velocidad en “inc”float * getPosv(); Obtiene un vector con la posición de la
esfera (en la posición 0, la coordenada X,en la 1 la Y, y en la 2 la Z)
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Animaciones
● Funciones de glut– glutDisplayFunc()– glutIdleFunc()
● Variables globales– float * pos;– TSphere * sphere;
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Animaciones
● Función de inicialización initgl
● gluLookAt: posición de la cámara + posición a la que apunta, parte superior de la escena
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,0.1);glMatrixMode(GL_MODELVIEW);gluLookAt(3,3,14,0,0,0,0,1,0);
}
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Animaciones
● Función displayvoid 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();}
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Animaciones
● Función idle
● Registramos estas funciones en la función main
void idle(void){ sphere->test(); usleep(33); glutPostRedisplay();}
initgl();glutDisplayFunc(display);glutIdleFunc(idle);
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Animaciones
● El doble buffering– Dibujar la escena en un buffer fuera de la pantalla,
mientras la imágen de la pantalla no se toca– Intercambio de buffers al final de cada frame– Al activar el modo de la pantalla
● glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
– Y al final de la función display● glutSwapBuffers();
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Animaciones
● Sphere-rebotes con doble buffering
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Animaciones
● Con una pequeña modificación
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Permite crear escenas más realistas● Cada implementación al menos 8 luces● No es recomendable abusar de éstas
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● El modelo de iluminación en OpenGL– Se basa en
● Luces: fuente que emite un haz de luz de un determinado color
● Materiales: determina la cantidad de cada color que refleja un objeto determinado
– El tipo de luz afecta al color
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Luces– Una fuente de luz puede emitir diferentes tipos de
luz● “Emitted” (emitida): luz emitida por un objeto● “Diffuse” (difusa): luz que incide sobre un objeto, y
proviene de un determinado punto● “Specular” (especular): luz que, al incidir sobre un objeto,
se ve reflejada con un ángulo similar al de incidencia● “Ambient” (ambiental): algo así como la iluminación
global de una escena
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Materiales– Definen qué cantidad refleja un objeto de cada tipo
de luz– El color de un objeto se define por su material, no
por el color de sus vértices● Normales
– Para saber cómo incide una luz sobre un vértice– Vector generalmente perpendicular a la cara que
estamos dibujando
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Misma luz, mismo objeto, normales cambiadas
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Utlizando la iluminación en OpenGL– Luces
● Primer paso, activar la iluminación– glEnable(GL_LINGHTING);
● Ahora establecemos las propiedades de cada luz, y las activamos
● Cada luz se identifica por una constante GL_LIGHTn, donde 'n' empieza desde cero
● Las propiedades se establecen con funciones de tipo glLight*()
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Luces– Propiedades de las luces
● Posición/Dirección– Puntuales– Focales
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Posición/Dirección– glLightfv(GL_LIGHTn,GL_POSITION,val_ptr);
● val_ptr es un puntero a un array de 4 dimensiones de tipo float (x,y,z,w). Si w=1 es posicional, si es 0, direccional
● Dirección del foco– glLightfv(GL_LIGHTn,GL_SPOT_DIRECTION,val_prt);
● Apertura del foco– glLightf(GL_LIGHTn,GL_SPOT_CUTOFF,val);
● val está expresado en grados
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Atenuación del foco– glLightf(GL_LIGHTn,GL_SPOT_EXPONENT,val);
● Intensidad de la luz– Define el color ambiental, difuso y especular– glLightfv(GL_LIGHTn,GL_[AMBIENT|DIFFUSE|
SPECULAR],val_ptr);● val_ptr es puntero a vector de 4 componentes RGBA
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Atenuación de la luz– Pérdida de intensidad de la luz a medida que nos
alejamos del foco– glLightf(GL_LIGHTn,GL_[CONSTANT|LINEAR|
QUADRATIC]_ATTENUATION,val);– El factor de atenuación se calcula mediante:
– Una vez establecidas las propiedades de una luz● glEnable(GL_LIGHTn);
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Materiales– Características del material: glMaterial*(), 3
parámetros● Caras del polígono a las que afecta: GL_FRONT,
GL_BACK, GL_FRONT_AND_BACK● Característica que estamos definiendo (color, brillo)● Valor de la característica
– Color del material● Define su comportamiento ante los tipos distintos de luz● Color ambiental, difuso y especular● Color emitido
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Color del material– glMaterialfv(GL_FRONT[_AND_BACK],[GL_AMBIE
NT|GL_DIFUSSE|GL_AMBIENT_AND_DIFUSSE|GL_SPECULAR],val_ptr);
– val_ptr es un puntero a un vector de componentes RGBA
● Brillo de los reflejos de los materiales– glMaterialf(GL_FRONT[_AND_BACK],GL_SHININE
SS,val);
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Materiales– Podemos cambiar estos valores con la función
glColorMaterial ()● Hay que activarla con
glEnable(GL_COLOR_MATERIAL);● Establecemos la propiedad a cambiar
– glColorMaterial(GL_FRONT[_AND_BACK],[GL_AMBIENT|GL_DIFUSSE|GL_AMBIENT_AND_DIFUSSE|GL_SPECULAR]);
● Cambiamos el color reflejado de ese tipo de luz– glColor3f(r_val,g_val,b_val);
● Debemos desactivar esta opción tras utilizarla
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Ejemplo: Iluminación direccional sobre una superficie (ejemplo de las normales)
● Arrays a definir– Color ambiental y difuso del material
● GLfloat mat_color [] = {0.0,1.0,1.0,1.0};– Color difuso y especular de la luz
● GLfloat light_color [] = {1.0,1.0,1.0,1.0};– Color ambiental de la luz
● GLfloat light_ambient [] = {0.0,0.0,0.0,1.0};
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Arrays a definir– Valor de las normales
● GLfloat normal [] = {0.0,1.0,0.0};– Valor de la dirección de la luz
● GLfloat light_dir [] = {0.0,1.0,0.0,0.0};● Seleccionamos el color de fondo, y borramos la
pantallaglClearColor(0.0,0.0,0.0,0.0);glClear(GL_COLOR_BUFFER_BIT);
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Activamos la luz, y sus características, excepto la dirección
● Seleccionamos el color del material:– glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFF
USE,mat_color);
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);
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Establecemos la perspectiva y posicionamos al observador
● Establecemos la dirección de la luz– glLightfv(GL_LIGHT0,GL_POSITION,light_dir);
glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(60.0,1.0,1.0,100.0);glMatrixMode(GL_MODELVIEW);glTranslatef(-0.3,-0.6,-4.0);
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Dibujamos el cuadrado, y antes de cada vertice, establecemos su normal
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();
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Forzamos el dibujado, esperamos, y salimos del programa
● Ejemplo: moviendo un foco alrededor de una esfera– Utilizaremos dibujado con doble buffer, y zBuffer
glFlush();sleep(20);exit(0);
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Definimos las características de la luz
● Características del material de la esfera
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;
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;
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Ponemos un pequeño cono cuyo material tenga una “emisión” similar al color de la luz– float focus_emission [] = {0.8,0.8,0.8,1.0};
● Variables que indican la rotación del foco
● Habilitamos el zBuffer y establecemos el color de fondo
float rot_angle_y = 0.0;float rot_angle_x = 0.0;
glEnable(GL_DEPTH_TEST);glClearColor(0.0,0.0,0.0,0.0);
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Activamos las luces y sus características
● Establecemos el material de la esfera
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);
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Establecemos la perspectiva y trasladamos la cámara
● Estos pasos los englobamos en una función de inicialización
glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(60.0,1.0,1.0,100.0);glMatrixMode(GL_MODELVIEW);glTranslatef(0.0,0.0,-5.0);
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Bucle de dibujadoglClear(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();
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Entre frame y frame, rotamos el focorot_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();
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
● Ejercicio propuesto– Modificar “sphere-rebotes-multi”
● Luz direccional, blanca, situada en el infinito, en una posición apuntada por (1,1,1)
● Cada esfera con un color aleatorio, definido por las características ambiental y difusa del material
● El cubo no debe verse afectado por la luz al dibujarse
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Iluminación
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Texturas
● Coordenadas de textura– Permiten saber qué partes de una imagen se
dibujan en un polígono– Se representan por números reales de 0 a 1
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Texturas
● Si queremos dibujar un triángulo con una textura
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Texturas
● Aplicar las texturas
1 Creamos la textura
2 Definimos las condiciones en las que se va a aplicar la textura
3 Habilitar la aplicación de texturas
4 Dibujar las escenas, proporcionando las coordenadas de textura
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Texturas
int texture;glGenTextures(1,&texture);
gluBuild2DMipmaps( GL_TEXTURE_2D, gimp_image.bytes_per_pixel,gimp_image.width, gimp_image.height,GL_RGB, GL_UNSIGNED_BYTE,gimp_image.pixel_data );
● Aplicar las texturas (ejemplo del mapeado)– Creación de la texura
● Obtenemos un identificador para la textura
● Declaramos la textura como textura activa– glBindTexture(GL_TEXTURE_2D, texture);
● Creamos la textura
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Texturas
● Aplicar las texturas– Creación de la textura
● Hemos usado un archivo “c” del Gimp
– Definir las condiciones en las que se aplicará la textura
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, [...] }
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Texturas
● Diferencia GL_REPLACE Y GL_MODULATE
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Texturas
● Aplicar las texturas– Habilitar la aplicación de texturas
● Mediante glEnable(GL_TEXTURE_2D);– Dibujar, proporcionando las coordenadas de textura
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();
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Texturas
● Aplicar las texturas– Para cambiar la textura activa
● glBindTexture(GL_TEXTURE_2D,texture);● Repetición de texturas
– Ejemplo: Suelo y pared con estas texturas
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Texturas
● Repetición de texturas– Para el suelo
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();
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Texturas
● Repetición de texturas– Para la pared
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();
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Texturas
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Texturas
● Repetición de texturas
– El nuevo mapeo del suelo
glTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);glTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
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();
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Texturas
● Repetición de texturas– El nuevo mapeo de la pared
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();
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Texturas
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Interacción básica con Glut
● Interactuar con las ventanas● Funciones de CALLBACK● Registrar funciones en Glut
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Interacción básica con Glut
● Interacción con el teclado– Modificación de “lit-sphere”
● Registrar el evento de teclado con la función– glutSpecialFunc(void (*func)(int key, int x, int y));
● Variables globales– rot_angle_x, rot_angle_y
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Interacción básica con Glut
● Modificación de “lit-sphere”– Código de la función declarada en glutSpecialFunc
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();}
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Interacción básica con Glut
● Modificación de “lit-sphere”– Para que al pulsar Esc se salga del programa
● Utilizamos glutKeyboardFunc(), que recibe puntero a
● Damos de alta los dos nuevos manejadores de eventos
static void keys(unsigned char key, int x, int y){ switch (key) { case 27: exit(0); break; } glutPostRedisplay();}
glutSpecialFunc(specialKeys);glutKeyboardFunc(keys);
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Interacción básica con Glut
● Modificación de “lit-sphere”– Redimensionado de la ventana
● Usamos la función de CALLBACK glutReshapeFunc
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,h,1.0,100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0,0.0,-5.0); glutPostRedisplay();}
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Interacción básica con Glut
● Modificación de “lit-sphere”– Al pulsar “f” queremos pasar a modo pantalla
completa/modo ventanacase 'f': if (windowed == 1){glutFullScreen(); windowed = 0;} else{ glutPositionWindow ( 20 , 20 ); glutReshapeWindow ( 350,350); windowed = 1; } break;
Roberto Garrido (Ro) - ESIDE e-ghost 2006
Recursos de interés
● Red Book: básico para empezar● The OpenGL Utility Toolkit (GLUT)
Programming Inteface: todo sobre Glut● Los tutoriales de nehe (nehe.gamedev.net):
programación de juegos● David Henry's homepage: http://tfc.duke.free.fr/