You are on page 1of 96

UNIVERSIDAD DEL MAR

CAMPUS PUERTO ESCONDIDO


LICENCIATURA EN INFORMÁTICA
GRAFICACIÓN

MANUAL
APRENDA A GRAFICAR CON OPENGL
EN 20 PRÁCTICAS

Nivel Básico

ISIDRO MOCTEZUMA
CANTORÁN
Primera edición en español: 2008 DIRECTORIO

DR©2008, Universidad del Mar, Dr. Modesto Seara Vázquez


Campus Puerto Escondido. Ciudad Rector de la UMAR
Universitaria, Vía Sola de Vega Km. msv@huatulco.umar.mx
1.5 Carretera Puerto Escondido-
Oaxaca. San Pedro Mixtepec, M. C. Gerardo Esteban Leyte Morales
Júquila, Oaxaca, México, 71980. Vice-Rector Académico
UMAR
vicadem@angel.umar.mx
Prohibida la reproducción total o
parcial de esta obra sin L. C. E. José Luís Ramos Espinoza
autorización de los editores y/o Vice-Rector Administrativo
autor. UMAR
joseluis@angel.umar.mx
Responsable de edición
Isidro Moctezuma Cantorán M.C. Manuel A. Valdés Marrero
Jefe de Carrera de Informática
Diseño de Portada UMAR
Isidro Moctezuma Cantorán valdes@zicatela.umar.mx

Colaboradores alumnos M.C. José Edgar Lara Ramírez


Aaron José Gaspar Representante de la Academia de
Darwin Sosa Gómez Tratamiento de imágenes e IA
David Espíndola Rodríguez UMAR
Elizabeth Mendoza Velázquez mccjer@zicatela.umar.mx
José Palácios Chávez
Omar Hernández Reyes M. C. Isidro Moctezuma Cantorán
Responsable de la publicación
Edición con fines académicos moctezuma@zicatela.umar.mx

Impreso en México Pagina electrónica:


Printed in México http://www.umar.mx

Cita correcta: MANUAL APRENDA A


GRAFICAR CON OPENGL EN 20
PRÁCTICAS, Nivel Básico, Isidro
Moctezuma Cantorán, Universidad
del Mar, Campus Puerto Escondido-
Puerto Escondido, San Pedro
Mixtepec, Júquila, Oaxaca. México,
2008.
PRESENTACIÓN

El presente trabajo es el producto de algunas prácticas realizadas a lo largo de


tres cursos de la materia de graficación dirigida para alumnos de séptimo
semestre de la carrera de Informática de la Universidad Mar, con el objetivo de
auxiliar a los alumnos que quieren ser autodidactas en cursos sucesivos.

El manual está dividido en 20 prácticas, cada práctica tiene un objetivo, un listado


de acciones a realizarse, descripción de funciones de OpenGL en algunos casos,
código fuente e imágenes; resultados de dichas prácticas.

El orden de las prácticas permitirá al lector conocer funciones básicas de OpenGL


y graficar de una manera fácil y sencilla.

El Autor
PRÓLOGO

En las últimas décadas se ha notado un gran avance en el área de la graficación y


se ha estado dando a pasos agigantados, desde el manejo de las animaciones en
los videojuegos con un realismo impresionante, hasta los dibujos animados, mejor
conocidos como caricaturas, que dan una apariencia muy cercana a la realidad, ya
que el manejo de los gráficos en tres dimensiones permite realizar una infinidad de
efectos asombrosos.

Una de las inquietudes de todo programador de computadoras, es conocer como


se hacen las cosas, sobre todo aquellas que nos dejan una buena impresión, y
cuando de juegos o animaciones por computadora se trata es una de las cosas
que más llaman la atención y de las que menos se tiene información disponible.

Por fortuna, se tiene este manual de graficación con OpenGL, una herramienta de
las más utilizadas para cumplir con propósitos de animación en gráficos y una de
las mejores en su ramo. Con este manual aprenderás las bases de la graficación,
una vez que se termine de leer y hacer los ejercicios que en el vienen, bastará con
echar a andar tu imaginación y descubrir hasta donde puedes llegar en el
desarrollo de los gráficos, verás que podrás realizar cosas fascinantes, de las
cuales tu mismo te sorprenderás.

El autor de este documento, así como las personas que intervinieron para que
fuera posible su creación, invirtieron muchas horas de esfuerzo y años de
experiencia en el tema para dejar un buen sabor de boca al lector, además de
hacer todo lo posible para poner al alcance un material de alta calidad, fácil de
leer, de seguir y de entender.

Se invita por lo tanto, a todos aquellos que tengan interés en aprender a graficar,
que sigan el presente manual de principio a fin, con mucho ahínco y tenacidad,
siendo persistentes en todo momento, hasta que obtengan los resultados
deseados y cumplan con sus propias metas.

M. en C. Jorge Ochoa Somuano


Profesor/Investigador
Universidad del Mar Campus Puerto Escondido
ÍNDICE

Introducción …………………………………………………………… 6
Práctica 1: Instalación de OpenGL ………………………………… 7
Práctica 2: Color de fondo y archivos de cabecera ……………… 8
Práctica 3: Generalidades de OpenGL ……………………………. 10
Práctica 4: Dibujar un rectángulo …………………………………... 13
Práctica 5: Funciones básicas de OpenGL ………………………. 16
Práctica 6: Dibujar un punto ………………………………………… 20
Práctica 7: Tamaño de un punto …………………………………… 24
Práctica 8: Dibujar líneas ……………………………………………. 31
Práctica 9: Más de líneas …………………………………………… 34
Práctica 10: Dibujo de triángulos …………………………………… 38
Práctica 11: Profundidad y eliminación de superficies y selectiva 43
Práctica 12: Polígonos ………………………………………………. 50
Práctica 13: Relleno de polígonos …………………………………. 53
Práctica 14: Polígonos en vista de puntos, líneas y rellenos …… 57
Práctica 15: Limpiar el buffer de color …………………………….. 62
Práctica 16: Rotación, translación y escalamiento ………………. 64
Práctica 17: Proyección ortogonal y en perspectiva ……………... 68
Práctica 18: Luz ambiental, difusa y especular …………………… 72
Práctica 19: Sombras ………………………………………………... 78
Práctica 20: Transparencia …………………………………………. 84
Ejemplos ……………………………………………………………… 87
Conclusiones ………………………………………………………… 94
______________________________________________________________________________________________________________

INTRODUCCIÓN

La materia de graficación es sin duda la más dinámica, entretenida y divertida de


la carrera de informática, por la facilidad de aprender a graficar en dos
dimensiones (2D) y tres dimensiones (3D).

OpenGL (Open Graphic Library), librería de gráficos abierta, maneja 10 primitivas


básicas para graficar, que son:

GL_POINTS. Para dibujar puntos.


GL_LINES. Para dibujar líneas.
GL_LlNE_STRIP. Para dibujar líneas continúas.
GL_LINES_LOOP. Para dibujar líneas continúas, pero el último punto especificado
se une con el primer punto.
GL_TRIANGLES. Para dibujar triángulos.
GL_TRIANGLE_STRIP. Dibuja un abanico de triángulos a partir del primer
triángulo, apoyándose en los dos últimos puntos o vértices especificados del
triángulo anterior.
GL_TRIANGLES_LOOP. Para dibujar una serie de triángulos, donde todos tiene
un punto común.
GL_QUADS. Para dibujar cuadrados o rectángulos
GL_QUAD_STRIP. Para dibujar un abanico de cuadrados o rectángulos
GL_POLYGON. Para dibujar polígonos.

Para la descripción de las prácticas presentadas en este manual, se tomaron


como referencia bibliográfica los libros: OpenGL programación de Richard S.
Wringht y C++ Builder 5 de Francisco Charte, ambos de la editorial Anaya
multimedia.

Los requerimientos mínimos que debe tener el lector para el desarrollo de las
prácticas son: manejo del lenguaje de programación C ó C++, conocimientos
básicos del entorno de C++ Builder 5, manejo de MS DOS (básico), nociones de
2D y 3D, y algo indispensable; el gusto graficación por computadora.

El orden de las prácticas inicia desde instalar el componente de OpenGL en C++


Builder 5, uso de las primitivas básicas de OpenGL, descripción de funciones de
OpenGL, hasta la aplicación de algunos efectos para dar más realismos a los
gráficos.

______________________________________________________________________________________________ 6
M.C. Isidro Moctezuma Cantorán
______________________________________________________________________________________________________________

Práctica 1: Instalación de OpenGL


Objetivo: Instalar el componente en C++ Builder 5

Para iniciar esta práctica se requiere del componente de OpenGL para C++
Builder 5, el cual puede descargarse en la página: http://www.opengl.org, Guarde
los archivos en una carpeta llamada “ComponentesOpenGL”, para instalar el
componente siga los siguientes pasos:

1.-Ejecute el archivo OpenGLPanel_DP, doble clic sobre el nombre del


archivo, que se encuentra en la carpeta ComponentesOpenGL.
2.- De la carpeta ComponentesOpenGL:
• Copiar los archivos *.h a la carpeta GL de C++ Builder 5
• Copiar los archivos *.lib a la carpeta Lib de C++ Builder 5
• Copiar los archivos *.dll a la carpeta de sistem32 de Windows

Después de copiar los archivos en sus respectivas carpetas, en el Prompt del MS-
DOS ir a la carpeta de Lib de C++ Builder5 y escribir:
implib glut.lib c:\windows\system32\glut.dll
implib glut32.lib c:\windows\system32\glut32.dll

Una vez instalado OpenGL en C++ Builder 5, deberá aparecer el icono en la


pestaña en la parte derecha de la ventana de C++ Builder 5 y al ejecutar la
aplicación se mostrará la ventana o área de graficación de OpenGL, tal como se
muestra en la figura 1.

Icono de
OpenGL
Ventana
de
OpenGL

Figura 1. Ventana de OpenGL

______________________________________________________________________________________________ 7
M.C. Isidro Moctezuma Cantorán
______________________________________________________________________________________________________________

Práctica número 2: Color de fondo y archivos de cabecera


Objetivo: Asignar un color de fondo a la ventana de de OpenGL y agregar
los archivos de cabecera.

Para asignarle color de fondo a la venta de OpenGL y declarar los archivos *.h
siga los siguientes pasos:

1. Abrir un Nuevo proyecto en C++ Builder 5.

2. En el formulario agregar una ventana OpenGL de un tamaño que ocupe la


mitad del formulario.

3. En código, en la parte de declaraciones de librerías (después de


#include”Unit1.h”) agregar:

#include<gl/gl.h>
#include<gl/glu.h>.

4. Regresar al formulario, seleccionar la ventana de OpenGL, en la ventana de


inspector de Objeto (Object Inspector) seleccionar eventos, dar doble clic al
evento OnInit, y en código agregar lo siguiente: glClearColor(0.0f, 0.0f, 1.0f,
1.0f);

5. Regresar al formulario, seleccionar la ventana de OpenGL, en la ventana de


inspector de Objeto seleccionar eventos, dar doble clic al evento OnPaint, y
en código agregar lo siguiente: glClear(GL_COLOR_BUFFER_BIT);

El archivo .CPP (código) deberá ser:

#include <vcl.h> //-----------------------------------------------------------


#pragma hdrstop ----------------
void __fastcall
#include "Unit1.h" TForm1::OpenGLPanel1Paint(TObject
#include<gl/gl.h> *Sender)
#include<gl/glu.h> {
//----------------------------------------------------------- glClear(GL_COLOR_BUFFER_BIT);
---------------- //aquí se dibuja todo
#pragma package(smart_init)
#pragma link "OpenGLPanel"
#pragma resource "*.dfm" }
TForm1 *Form1; //-----------------------------------------------------------
//----------------------------------------------------------- ---------------
---------------- void __fastcall
__fastcall TForm1::TForm1(TComponent* TForm1::OpenGLPanel1Init(TObject
Owner) *Sender)
: TForm(Owner) {
{ glClearColor(0.0f,0.0f,1.0f,1.0f);
} }

______________________________________________________________________________________________ 8
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Al dar ejecutar (Run) su proyecto parecerá similar a la figura 2.

Ventana de
OpenGL con
Color de
fondo

Figura 2. Color de fondo a la ventana de OpenGL

______________________________________________________________________ 9
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Práctica número 3: Generalidades de OpenGL


Objetivo. Conocer las generalidades de OpenGL.

OpenGL

OpenGL, del inglés Open Graphic Library (Librería de Gráficos Abierta o Libre)
no es un Lenguaje es una API (Interfaz de Programación de Aplicación).
Cuando se hace mención que una aplicación esta hecho en OpenGL, quiere decir
que está hecho en algún lenguaje de programación: C, C++, Visual C++ Builder
C++, Visual Basic, Java, etc., y que el lenguaje es el que llama a una o más
bibliotecas de OpenGL.

En este caso el lenguaje a utilizado es C++ Builder 5.

En el encabezado en la parte de código se deben declarar las siguientes librerías


básicas de OpenGL:

#include <gl/gl.h>
#include <gl/glu.h>

Tipos de datos de OpenGL


OpenGL maneja sus propios tipos de datos, los cuales son:

Tipos de datos Representación Tipo definido


OpenGL interna como C
GLbyte Entero de 8 dígitos Signed char
GLshort Entero de 16 bits Short
GLint, GLsizei Entero de 32 bits Long
GLfloat, GLclampf Punto flotante de 32 bits float
GLdouble, GLclamp Punto flotante de 64 bits double
GLubyte, GLboolean Entero de 8 bits sin unsigned char
signo
GLushort Entero de 16 bits sin unsigned short
signo
GLuint, GLenum, Entero de 32 bits sin Unsigned long
GLbitfield signo

Las variables GLboolean se utilizan para indicar condiciones verdaderas o falsas,


GLenum para variables enumeradas, GLbitfield para variables que contienen
campos de bits binarios.

Los apuntadores y las matrices no tienen una mención especial, debido a que
manejan similar a lenguaje C, por ejemplo:

______________________________________________________________________ 10
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

GLshort s[10];
GLdouble *d[10];

Para C++ Builder 5, puede utilizar los tipos de datos de OpenGL o C o C++.

Convenio de denominaciones de funciones de OpenGL


Formato general:
<Prefijo de biblioteca><comando raíz><cuenta opcional de argumentos><tipo
opcional de argumentos>.

Ejemplo:

glColor3f(…)
Comando Raíz Número de
Biblioteca GL argumentos Tipo de
argumentos

Por ejemplo glColor puede variar a, glColor3f, glColor4f, glColor3i, etc.,


dependiendo el número y tipo de datos que maneje.

La función glClearColor(). Esta función permite establecer el color usando para


borrar la ventana.
Formato:
glClearColor(GLclampf R, GLclampf V, GLclampf A, GLclampf Alfa), donde:
R = rojo
V = verde
A = azul
En OpenGL un color es la mezcla de los componentes rojo, verde y azul, cada
componente o color puede variar de 0 a 1, similar a la especificación en Windows
RGB (0-256).

El último componente Alfa se usa para efectos de fusión y especiales como la


translucidez. La translucidez se refiere a la capacidad de un objeto de permitir el
paso de la luz a través de él.

______________________________________________________________________ 11
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Algunos colores compuestos comunes son:

Color compuesto Rojo Verde Azul


Negro 0 0 0
Rojo 1 0 0
Verde 0 1 0
Amarillo 1 1 0
Azul 0 0 1
Magenta 1 0 1
Azul verdoso 0 1 1
Gris oscuro 0.25 0.25 0.25
Gris claro 0.75 0.75 0.75
Marrón 0.60 0.40 0.12
Naranja calabaza 0.98 0.625 0.12
Rosa pastel 0.98 0.04 0.7
Morado 0.60 0.40 0.70
Blanco 1 1 1

glClear (GL_COLOR_BUFFER_BIT) con la función glClearColor, hasta ahora


solo se ha borrado (pintando la ventana de otro color), para un borrado real se usa
glClear(GL_COLOR_BUFFER_BIT).
La función glClear (GL_COLOR_BUFFER_BIT). Borra un buffer o una
combinación de buffers determinada.
Un buffer es una zona de almacenamiento de información de imagen, los
componentes rojo, verde y azul de un dibujo normalmente se conocen
colectivamente como búfer de color o buffer de píxeles (elimina el último dibujo de
la ventana). Más adelante se dará detalle de dicha función.

______________________________________________________________________ 12
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Práctica número 4: Dibujar un rectángulo


Objetivo: Dibujar un rectángulo usando la función glRectf();

Para dibujar un rectángulo siga los siguientes pasos:

1. Abrir un nuevo proyecto en Builder


2. Agréguele un nombre al formulario (“Rectángulo”)
3. Guarde el proyecto
4. En el formulario agregue una ventana de OpenGL que cubra todo el
formulario
5. En el código, en la cabecera de librerías agregue las librerías gl.h y glu.h.
6. En el formulario seleccione la ventana de OpenGL, seleccione eventos en
la ventana de inspector de objeto, de doble clic en el evento OnInit, en
código agregue lo siguiente

int w=OpenGLPanel1->Width;
int h=OpenGLPanel1->Height;
//int nRange=OpenGLPanel1->Width/2;
GLfloat nRango;
// Evitar la división entre cero
if(h == 0)
h = 1;

// Establecer el puerto de vista para las dimensiones de la ventana


glViewport(0, 0, w, h);

// Restablece el sistema de coordenadas


glMatrixMode(GL_PROJECTION);
glLoadIdentity();

// Establecer el volumen de recorte (izquierda, derecha, inferior,


superior, cerca, lejos
nRango = (GLfloat)w / (GLfloat)h;
if (w <= h)
glOrtho (-100.0, 100.0, -100 / nRango, 100.0 / nRango, 1.0, -
1.0);
else
glOrtho (-100.0 * nRango, 100.0 * nRango, -100.0, 100.0, 1.0, -
1.0);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);

______________________________________________________________________ 13
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

7. En el formulario seleccione la ventana de OpenGL, seleccione eventos en


la ventana de inspector de objeto, de doble clic en el evento OnPaint, en
código agregue el siguiente código

// Limpiar la ventana con el color actual


glClear(GL_COLOR_BUFFER_BIT);

// Establecer el color rojo de dibujo actual


// R G B
glColor3f(1.0f, 0.0f, 0.0f);

// dibujar el rectángulo relleno con el color actual


glRectf(-25.0f, 25.0f, 25.0f, -25.0f);

Ejecute su programa (Run), Figura 3.

Figura 3. Rectángulo

El programa utiliza la función:

void glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2,);

Para dibujar un rectángulo, en la cual los cuatro argumentos representan dos


pares de coordenadas (x1, y1) y (x2, y2), el primer representa la esquina superior
izquierda del rectángulo y el segundo par la esquina inferior derecha.

La función glViewport () se usa para especificar el ancho y alto de la ventana,


también se utiliza la proyección ortogonal para el volumen de recorte con la
función glOrtho();

En el código antes de glOrtho se utilizan


glMatrixMode(GL_PROJECTION);

______________________________________________________________________ 14
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

glLoadIdentity();

La matriz de proyección se encuentra en el lugar donde realmente definimos


nuestro volumen de visualización y la llamada a glLoadIdentity() sirve para
reestablecer el sistema de coordenadas antes de ejecutarse alguna manipulación
de la matriz y
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Sirven para indicarle a OpenGL que todas las transformaciones futuras afectarán a
nuestros modelos (nuestro dibujo).

______________________________________________________________________ 15
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Práctica número 5: Funciones básicas de OpenGL


Objetivo: Conocer funciones básicas de OpenGL

• glClearColor

Finalidad: Establece los valores de color y transparencia a usar para borrar los
búferes de color.
Archivo <gl.h>
include:
Sintaxis: void glClearColor(GLclampf rojo, GLclampf verde, GLclampf azul,
GLclampf alfa);
Descripción: Esta función establece los valores de relleno que se van a utilizar
cuando se borren los búferes de rojo, verde, azul y transparencia
(denominados conjuntamente búfer de color).
Los valores especificados se ajustan al rango [0.0f, 1.0f]
Parámetros
rojo: GLclampf: componente rojo del valor de relleno.
verde: GLclampf: componente verde del valor de relleno.
azul: GLclampf: componente azul del valor de relleno.
alfa: GLclampf: componente de transparencia (alfa) del valor de relleno.
Devuelve: Nada.

• glDisable, glEnable

Finalidad: Habilita o deshabilita una característica de estado de OpenGL.

Archivo <gl.h>
include:
Sintaxis: void glDisable(GLenum característica );
void glEnable(GLenum característica );
Descripción: glDisable .- deshabilita una opción de dibujo de OpenGL
glEnable .- Habilita una opción de dibujo de OpenGL.
Parámetros
Característica: GLenum: Opción a activar o desactivar. En la especificación de
OpenGL se proporciona una lista completa de estados y crece
regularmente con las nuevas actualizaciones. (Ver tabla 1.)
Devuelve: Nada.

Tabla 1. Opciones activadas y desactivadas por glEnable /glDisable


Opción Descripción
GL_BLEND Fundido de color
GL_CULL_FACE Seleccionar polígono
GL_DEPTH_TEST Prueba detallada
GL_DITHER Tramado

______________________________________________________________________ 16
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

GL_FOG Modo de niebla de OpenGL


GL_LIGHTING Iluminación de OpenGL
GL_LIGHTx Número de luz x de OpenGL (mínimo 8)
GL_POINT_SMOOTH Suavizado de punto
GL_LINE_SMOOTH Suavizado de línea
GL_LINE_STIPPLE Punteo de línea
GL_POLYGON_SMOOTH Suavizado de polígono
GL_SCISSOR_TEST Recorte habilitado
GL_STENCIL_TEST Prueba de plantilla
GL_TEXTURE_xD Textura de xD (1, 2 ó 3)
GL_TEXTURE_CUBE_MAP Mapa de texturas de cubo
GL_TEXTURE_GEN Información de textura para x(S, T, R ó Q)

• glFinish

Finalidad: Obliga a que se completen todos los comandos anteriores de


OpenGL
Archivo <gl.h>
include:
Sintaxis: void glFinish(void)
Descripción: Normalmente los comandos de OpenGL se apilan en la cola y se
ejecutan en secuencias de comandos para optimizar el rendimiento.
El comando glFinish obliga a que se ejecuten todos los comandos
OpenGL pendientes. Al contrario que glFlush, esta función no se
devuelve hasta que hayan completado todas las operaciones de
interpretación
Parámetros ninguno
Devuelve: Nada.

• glFlush

Finalidad: Limpia las colas y los búferes de comandos OpenGL.


Archivo <gl.h>
include:
Sintaxis: void glFlush(void)
Descripción: Normalmente los comandos de OpenGL se apilan en la cola y se
ejecutan en secuencias de comandos para optimizar el rendimiento.
Algo que puede variar según el hardware, los controladores y las
implantaciones de OpenGL. El comando glFlush hace que se
ejecute cualquier comando que esté esperando a ejecutarse, algo
que se debe conseguir en tiempo finito. Básicamente es la misma
ejecución asíncrona de los comandos de gráficos porque glFlush se
devuelve inmediatamente.

Parámetros: ninguno
Devuelve: Nada.
______________________________________________________________________ 17
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

• glOrtho

Finalidad: Estable o modifica las extensiones del volumen de recorte.


Archivo <gl.h>
include:
Sintaxis: void glOrtho(GLdouble Izquierda, GLdouble Derecha, GLdouble
Abajo, GLdouble Arriba, GLdouble Cerca, GLdouble Lejos);

Descripción: Esta función describe un volumen de recorte paralelo. Esta


proyección significa que los objetos que se encuentran lejos del
espectador no parecen más pequeños (en contraste a una
proyección en perspectiva). Piense en un volumen de recorte en
función de las coordenadas cartesianas 3D, en las que izquierda y
derecha son los valores mínimo y máximo de x, abajo y arriba son
los valores mínimo y máximo de y, y cerca y lejos son los valores
mínimo y máximo de z.
Parámetros:
Izquierda: GLdouble: coordenada izquierda del volumen del recorte
Derecha: GLdouble: coordenada derecha del volumen del recorte
Abajo: GLdouble: coordenada inferior del volumen del recorte
Arriba: GLdouble: coordenada superior del volumen del recorte
Cerca: GLdouble: Distancia mínima desde el origen hacia el espectador
Lejos: GLdouble: Distancia máxima desde el origen hacia el espectador
Devuelve: Nada.

• glRect

Finalidad: Dibuja un rectángulo plano.

Archivo <gl.h>
include:
Sintaxis: void glRectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble
y2);
Variantes: void glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
void glRecti (GLint x1, GLint y1, GLint x2, GLint y2);
void glRects(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
void glRectdv(const GLdouble *v1, const GLdouble *v2);
void glRectfv(const GLfloat *v1, const GLfloat *v2);
void glRectiv(const GLint *v1, const GLint *v2);
void glRectsv(const GLshort *v1, const GLshort *v2);
Descripción: Esta función proporciona un método sencillo para especificar el
rectángulo como dos puntos de esquina. El rectángulo se dibuja en
el plano xy, siendo z=0;
Parámetros
x1, y1: Especifican las esquina superior izquierda del rectángulo

______________________________________________________________________ 18
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

x2,y2: Especifican las esquina inferior derecha del rectángulo


*v1: Matriz de dos valores que especifican la esquina superior izquierda
del rectángulo. También se podría describir como v1 [2].
*v2: Matriz de dos valores que especifican la esquina inferior derecha
del rectángulo. También se podría describir como v2 [2].
Devuelve: Nada.

• glViewport

Finalidad: Establece la parte de una ventana dentro de la cual puede dibujar


OpenGL.
Archivo <gl.h>
include:
Sintaxis: void glViewport(GLint X, GLint Y, GLsizei Ancho, GLsizei Alto);
Descripción: Esta función establece la región dentro de una ventana que se usa
para trazar las coordenadas del volumen de recorte en las
coordenadas físicas de la ventana.
Parámetros
X: GLint: número de píxeles desde la parte izquierda de la ventana
para iniciar el puerto de vista.
Y: GLint: número de píxeles desde la parte inferior de la ventana para
iniciar el puerto de vista ventana.
Ancho: GLsizei: anchura del puerto de vista en píxeles
Alto: GLsizei: altura del puerto de vista en píxeles
Devuelve: Nada.

______________________________________________________________________ 19
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Práctica número 6: Dibujar un punto

Objetivo: Graficar un punto en un espacio 2D.

Para dibujar un punto realice los siguientes pasos:

1. Abrir un proyecto nuevo en C++ Builder 5


2. Guarde el proyecto
3. Etiquete al formulario con el siguiente nombre “Dibujar un Punto”.
4. Agregue en el formulario una ventana de OpenGL
5. De clic a la ventana de OpenGL. En la ventana de de inspector de objetos
busque la propiedad Alinear (Align) asigne alClient.
6. Regrese al formulario, de clic a la ventana de OpenGL, seleccione el
inspector de objetos, elija eventos y en el evento OnInit de doble clic y en
código agregue lo siguiente
GLfloat Rango;
Rango=100; //área de volumen de visualización en el plano
//cartesiano en x, y, z
if(h == 0)
h = 1;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Estableciendo el volumen de recorte
Rango = (GLfloat)w / (GLfloat)h;
if (w <= h)
glOrtho (-Rango, Rango, -Rango*h/w, Rango*h/w, -Rango,
Rango);
else
glOrtho (-Rango*w/h, Rango*w/h, -Rango, Rango, -Rango,
Rango);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// color de fondo
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);

7. Regrese al formulario, de clic a la ventana de OpenGL, seleccione el


inspector de objeto, elija eventos y en el evento OnPaint de doble clic y en
código agregue lo siguiente:
// Limpiar la ventana
glClear(GL_COLOR_BUFFER_BIT);
//aquí se dibuja todo
// Los objetos se dibujarán con este color (verde)
glColor3f(0.0f, 1.0f, 0.0f);
Puntos();

______________________________________________________________________ 20
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

8. Habra el archivo Unith.h (según sea el nombre) declare la siguiente función


y variables:
void Puntos();
int h, w;
9. Regrese al formulario, de clic a la ventana de OpenGL, seleccione el
inspector de objetos, elija eventos y en el evento OnResize de doble clic y
en código agregue lo siguiente:
glViewport(0, 0, w, h);

10. En el evento OnCreate del Formulario de doble clic y en código inicialice


las variables de anchura y altura
w=OpenGLPanel1->Width;
h=OpenGLPanel1->Height;
11. Regrese al formulario de doble clic, en la parte inferior del archivo de
código escriba lo siguiente:

void TForm1::Puntos()
{
glBegin(GL_POINTS);
glVertex3f(0,0,0);
glEnd();
}
12. Ejecute el programa (Run), y le aparecerá un punto verde en la coordenada
(0, 0, 0), figura 4

Aquí está el
punto

Figura 4. Dibujar un punto.

______________________________________________________________________ 21
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

• Más sobre puntos

Para especificar un punto de dibujo se utiliza la función glVertex, la cual puede


soportar hasta 4 parámetros, por ejemplo para especificar la coordenada (20,10,
0), se escribe: glVertex3f(20.0f,10.0f,0.0f); en el sistema de coordenadas
específica que el punto está situado en la unidad 20 del eje x, 10 en el eje y, 0 en
el eje z, tal como se muestra en la figura 5.

(20, 10, 0)

Figura 5. Sistema de coordenadas.

Aunque el punto anterior se puede representar como: glVertex2f(20.0f, 10.0f);


especificando x, y y z toma el valor 0 por default, más adelante conocerá más
sobre como usar glVertex con más argumentos.

Los argumentos glBegin y GL_POINTS le indican a OpenGL que los siguientes


vértices se van a interpretar y dibujar como puntos, tal como se muestra a
continuación:

glBegin(GL_POINTS);
glVertex3f (0, 0, 0);
glEnd();

Dentro de glBegin y glEnd podemos listar más vértices a dibujar

Por ejemplo:

______________________________________________________________________ 22
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

glBegin(GL_POINTS);
glVertex3f (5, 10, 3);
glVertex3f (20,-15, 15);
glEnd();

Lo anterior dibuja un punto en la coordenada (5, 10, 3) y dibuja un punto en


la coordenada (20,-15,15), también puede especificarse como:
glBegin(GL_POINTS);
glVertex3f (5,10,3);
glEnd();

glBegin(GL_POINTS);
glVertex3f(20,-15,15);
glEnd();
Aunque este código se ejecutará más lentamente.

En el programa anterior muestre puntos en las siguientes coordenadas:


• (-1,1,0)
• (1,-1,0)
• (-1,-1,0)
• (0,1,2)

En este último especificamos un valor para z, pero debido a que no podemos


mover nuestro sistema de coordenada gráficamente posiblemente no se vea dicho
punto.

Debe escribir:
glBegin(GL_POINTS); y
glVertex3f(-1,1,0);
glVertex3f(1,-1,0);
glVertex3f(-1,-1,0);
glVertex3f(0,1,2);
glEnd();

______________________________________________________________________ 23
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Práctica número 7: Tamaño de un punto


Objetivo: Graficar un punto en un espacio 3D y aplicar tamaño

Para saber como graficar un punto en el espacio 3D siga los siguientes pasos:

1. Abrir un proyecto nuevo en Builder 5


2. Guarde el proyecto
3. Etiquete al formulario con el siguiente nombre “Dibujar Puntos”.
4. Agregue en el formulario una ventana de OpenGL
5. De clic a la ventana de OpenGL, en la ventana de de inspector de objetos
busque la propiedad Alinear (Align) asigne alTop.
6. En el formulario en la parte inferior agregue dos ScrollBar (Los ScrollBar
están en la pestaña de Estándar de Builder), modifique las siguientes
propiedades de los ScrollBar, las propiedades puede verlas en el inspector
de objetos.
Min=-200
Max=200
LargeChange =2
7. Regrese al formulario, de clic a la ventana de OpenGL, seleccione el
inspector de objetos, elija eventos y en el evento OnInit de doble clic y en
código agregue lo siguiente
int w=OpenGLPanel1->Width;
int h=OpenGLPanel1->Height;
GLfloat Rango = 200.0f;
if(h == 0)
h = 1;
glViewport(0, 0, w, h); //puerto de vista
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//proyección ortogonal
if (w <= h)
glOrtho (-Rango, Rango, -Rango*h/w, Rango*h/w, -Rango,
Rango);
else
glOrtho (-Rango*w/h, Rango*w/h, -Rango, Rango, -Rango,
Rango);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glClearColor(0.0f, 0.0f, 0.0f, 1.0f ); //color de fondo

8. Regrese al formulario, de clic a la ventana de OpenGL, seleccione el


inspector de objetos, elija eventos y en el evento OnPaint de doble clic y en
código agregue lo siguiente:

______________________________________________________________________ 24
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

// Limpiar ventana
glClear(GL_COLOR_BUFFER_BIT);
//aquí se dibuja todo
// color verde para los objetos
glColor3f(0.0f, 1.0f, 0.0f);

// Guardar el estado de la matriz y hacer la rotación


glPushMatrix(); //poner en la matriz
glRotatef(xRot, 1.0f, 0.0f, 0.0f); // rotar en el eje x
glRotatef(yRot, 0.0f, 1.0f, 0.0f); // rotar en el eje y
// UnPunto(); //llamada a función que dibuja un punto
// VariosPuntos(); // dibuja puntos formando una circunferencia
// VariosPuntos2(); // dibuja puntos formando un espiral
//VariosPuntos3(); // dibuja puntos de diferente tamaño
VariosPuntos4(); // dibuja puntos formando un espiral agregando tamaño a
los puntos.

// Reestablecer transformaciones
glPopMatrix();

9. Habra el archivo Unith.h (según sea el nombre) declare la siguiente función


y variables:
void UnPunto(); //dibuja un punto
void VariosPuntos(); //dibuja puntos formando una circunferencia
void VariosPuntos2(); //dibuja puntos formando un espiral
void VariosPuntos3(); //dibuja puntos de diferente tamaño
void VariosPuntos4(); //dibuja puntos formando un espiral agradando
tamaño a los puntos
float xRot,yRot,GL_PI;

10. Regrese al formulario, de clic a la ventana de OpenGL, seleccione el


inspector de objetos, elija eventos y en el evento OnResize de doble clic y
en código agregue lo siguiente:
int w=OpenGLPanel1->Width;
int h=OpenGLPanel1->Height;
glViewport(0, 0, w, h);

11. En el evento OnCreate del Formulario de doble clic y en código inicialice


las variables
xRot=0;
yRot=0;
GL_PI=3.1416;

12. Regrese al formulario de doble clic, en la parte inferior del archivo de


código agregue dos funciones: UnPunto y Varios Puntos
//---------------------------------------------------------------
void TForm1::UnPunto()
______________________________________________________________________ 25
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

{
glBegin(GL_POINTS);
glVertex3f(0,0,0);
glEnd();

}
//-------------------------------------------------------------
void TForm1::VariosPuntos()
{
GLfloat x,y,z,i;

glBegin(GL_POINTS);
z = 0;
for(i = 0.0f; i<= 360; i+= 5)
{
x = 50.0f*sin(i);
y = 50.0f*cos(i);
glVertex3f(x, y, z);
}

glEnd();
}

13. Regrese al formulario, de clic en el ScrollBar1, en el inspector de objetos,


elija eventos, de doble clic en el evento OnChage y código agregue lo
siguiente:
xRot=ScrollBar1->Position;
OpenGLPanel1->Invalidate();

14. Regrese al formulario, de clic en el ScrollBar2, en el inspector de objetos,


elija eventos, de doble clic en el evento OnChage y código agregue lo
siguiente:
yRot=ScrollBar2->Position;
OpenGLPanel1->Invalidate();

15. Regrese al formulario agregue dos etiquetas, una el rótulo Rotación X y


otra con Rotación Y, colóquelas arriba de los ScrollBar respectivamente.
16. Ejecute el programa (Run), y le aparecerá un punto verde en la
coordenada (0, 0, 0) y varios puntos alrededor formando una circunferencia,
tal como se muestra en la figura 6.

______________________________________________________________________ 26
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Figura 6. Un punto en el centro y varios puntos formando una circunferencia.

17. Agregue una función más, llámela VariosPuntos2() y agregue el siguiente


código.
GLfloat x,y,z,i;
glBegin(GL_POINTS);

z=-50;
for(i = 0.0f; i<= 360; i+= 0.1)
{
x = 50.0f*sin(i);
y = 50.0f*cos(i);
glVertex3f(x, y, z);
z+=1;
}
glEnd();

18. En el evento onPaint de OpenGL realice la llamada a VariosPuntos2() y


ejecute el programa, al rotarla mostrará un espiral, tal como se muestra en
la figura 7.

______________________________________________________________________ 27
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Figura 7. Espiral con puntos.

19. Agregue una función más, llámela VariosPuntos3() y en diferentes


coordenadas visualice puntos.
Para dar tamaño a un punto se utiliza la función glPointSize(glfloat
Tamaño), donde Tamaño puede ser un valor desde 0.5 – 10.0 en algunas
versiones de OpenGL puede variar el tamaño, verifique el tamaño mínimo y
máximo.
En esta función puede introducir este código
glPointSize(1);
glBegin(GL_POINTS);
glColor3f(1,0,0);
glVertex3f(1,1,1);
glEnd();

glPointSize(2);
glBegin(GL_POINTS);
glColor3f(1,1,0);
glVertex3f(10,10,10);
glEnd();

______________________________________________________________________ 28
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

glPointSize(3);
glBegin(GL_POINTS);
glColor3f(1,0,1);
glVertex3f(20,20,20);
glEnd();

glPointSize(4);
glBegin(GL_POINTS);
glColor3f(1,0,0);
glVertex3f(-1,-1,-1);
glEnd();

glPointSize(0.50);
glBegin(GL_POINTS);
glColor3f(1,1,0);
glVertex3f(-20,-10,10);
glEnd();

glPointSize(50);
glBegin(GL_POINTS);
glColor3f(1,0,1);
glVertex3f(-90,-20,-20);
glEnd();
20 En el evento onPaint de OpenGL realice la llamada a VariosPuntos3() y
ejecute el programa, visualizará una imagen similar a la figura 8.

Figura 8. Puntos de diferentes tamaños.

______________________________________________________________________ 29
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

21. Agregue una función más llámela VariosPuntos4() agregue el siguiente código

GLfloat x,y,z,i, Tam;


glColor3f(1,0,0);
z=-20;
Tam=0.1;
for(i = 0.0f; i<= 60; i+= 0.3)
{
glPointSize(Tam);
x = 50.0f*sin(i);
y = 50.0f*cos(i);
glBegin(GL_POINTS);
glVertex3f(x, y, z);
glEnd();
Tam+=0.1;
z+=1;
}

glPointSize(0);
nota: esta función dibuja un espiral e incrementa los tamaños de los puntos.

22. En el evento onPaint de OpenGL realice la llamada a VariosPuntos4() y


ejecute el programa, mostrará un imagen similar a la de la figura 9

Figura 9. Espiral con puntos de diferente tamaño.

______________________________________________________________________ 30
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Práctica número 8: Dibujar líneas


Objetivo: Graficar Líneas en un espacio 3D

Para dibujar líneas se utiliza la primitiva de dibujo GL_LINES, por ejemplo si se


quiere dibujar una línea en el eje x desde la coordenada (0, 0, 0) hasta (10, 0, 0).
Para que OpenGL dibuje la línea con los vértices mencionados es:
glBegin(GL_LINES);
glVertex3f(0, 0, 0);
glVertex3f(10, 0, 0);
glEnd();

1. Realice un función llamada ejes que usando OpenGL que dibuje las
siguientes líneas
Eje Coordenada Coordenada
inicial Final
x (100,0,0) (-100,0,0)
y (0,100,0) (0,-100,0)
Z (0,0,100) (0,0,-100)

2. Agregue una función (con el nombre EjesColor), tal que dibuje una línea en
cada eje con el color respectivo:

Eje Color
x Rojo
y Verde
z Azul

3. Agregue una función (Sol) que dibuje líneas alrededor del origen (0, 0,0) de
color amarillo.

• Líneas continuas
Para realizar líneas continuas se utiliza la primitiva GL_LINE_STRIP, es decir, el
vértice final sirve de inicio para la siguiente línea y así sucesivamente.
Por ejemplo el siguiente código dibuja 2 líneas continuas dados tres vértices,
figura 10.

glBegin(GL_LINE_STRIP);
glVertex3f(0,5,0);
glVertex3f(100,5,0);
glVertex3f(100,100,0);
glEnd();

______________________________________________________________________ 31
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

100,5,0

0,0,0 100,0,0

Figura 10. Esquema de dibujo de líneas.

4. Agregue una función (LineaContinua), que dibuje la figura anterior de color


gris oscuro.

• GL_LINE_LOOP
La primitiva GL_LINE_LOOP se comporta de manera similar a GL_LINE_STRIP a
diferencia de que se dibuja una línea final entre el último vértice especificado con
el primer vértice especificado, ejemplo el siguiente código:
glBegin(GL_LINE_LOOP);
glVertex3f(0,5,0);
glVertex3f(0,5,100);
glVertex3f(0,100,100);
glEnd();

Dibujaría unas líneas similares a las mostradas en figura 11.

5. Agregue una función (LineasCiclo), que dibuje la figura anterior en el eje z


de color gris oscuro.
6. Al ejecutar su programa mostrará similar a la figura 12:

______________________________________________________________________ 32
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Figura 12. Usando las primitivas de dibujo de OpenGL GL_LINES, GL_LINE_STRIP,


GL_LINE_LOOP.

Y
(100,100, 0)

X
(0,5, 0)
(100,5, 0)

Figura 11. Líneas usando GL_LINE_LOOP.

______________________________________________________________________ 33
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Práctica número 9: Más de líneas


Objetivo: Manejar el ancho y punteo de líneas.

Para dibujar líneas con ancho y punteadas siga los siguientes pasos:

1. Abrir un proyecto y en OpenGL muestre en líneas los ejes x, y y z. en color


rojo, verde y azul respectivamente.
2. Paso seguido genere una función (espiral) que realice un espiral similar al
que se realizó en la práctica 7 con los puntos.
3. Agregue el mismo código cambie la primitiva GL_POINTS por
GL_LINE_STRIP
void TForm1::Espiral()
{
GLfloat x,y,z,i;
glBegin(GL_LINE_STRIP);
z=-20;
for(i = 0.0f; i<= 360; i+= 0.1)
{
x = 50.0f*sin(i);
y = 50.0f*cos(i);
glVertex3f(x, y, z);
z+=1;
}
glEnd();
}

4. Ejecute el programa y tendrá una imagen similar a la figura 13

Figura 13. Espiral con líneas.

______________________________________________________________________ 34
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

5. Para establecer el acho de una línea se utiliza la función la función


glLineWidth, void glLineWidth(GLfloat ancho); la función acepta un solo
parámetro que específica la anchura en píxeles de una línea dibujada.
Aplique el ancho de 1 al eje x, 2 al eje y y 3 al eje z.

6. Dibuje 10 líneas paralelas al eje z, desde y=-100 hasta y=100 de diferentes


anchuras, El tamaño permitido de las líneas es de 1.0 hasta 10.0 pero
puede variar dependiendo la versión de OpenGL y plataforma de S.O
usada, una forma de dibujar es:

void TForm1::LineasParalelas()
{
GLfloat x,y,z;
x=0;
float Inc=0;
glColor3f(1,1,0);
for(y=-100.0f; y<100.0f; y+=20)
{
glLineWidth(Inc);
glBegin(GL_LINES);
glVertex3f(x,y,100);
glVertex3f(x,y,-100);
glEnd();
Inc+=2;
}
}

7. Además de la anchura también podemos establecer un patrón de punteo


en las líneas, para usar el punteo primero se tiene que habilitar el punteo,
usando la función glEnable(GL_LINE_STIPPLE);

Después la función glLineStipple establece el patrón que usan las líneas


para su dibujo.

void glLineStipple( GLint Factor, GLshort patron);

Nota: Para deshabilitar cualquier opción glEnable se usa glDisable.

El patrón es un valor de 16 bits que específica un patrón a usar cuando se


dibujan líneas. Cada bit representa una sección del segmento de la línea,
que están activados o desactivados.

De forma predeterminada cada bit se corresponde a un solo píxel, pero el


parámetro factor sirve como multiplicador para incrementar la anchura del
patrón.

______________________________________________________________________ 35
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Por ejemplo, el establecer el factor en 5, cada bit del patrón representa


cinco píxeles en una fila, que puede estar activado o desactivado

Por ejemplo:

Si patrón = 0X00FF = 255

0 0 F F
Binario = 0000 0000 1111 1111

X x x x x x x x
Patrón de línea=
Línea = |_______ ______ _______ _______|

Ejemplo:
Si el patrón es 0x5555 = 21845
Binario: 0101 0101 0101 0101

Patrón de línea: x x x x x x x x

Si factor = 5, es decir cada bit del patrón representa 5 píxeles en una fila
Línea:

8. Agregue una función (Punteo) la cual permita dibujar 10 líneas punteadas


paralelas al eje x desde y=-100 hasta y=100, con z=0.
GLfloat x,y,z;
GLint factor=1;
GLushort Patron= 0x5555;
//habilitando el punteo
glEnable(GL_LINE_STIPPLE);
z=0;
glColor3f(1,1,0);
for(y=-100.0f; y<100.0f; y+=20)
{
glLineStipple(factor, Patron);
glBegin(GL_LINES);
glVertex3f(100,y,z);
glVertex3f(-100,y,z);
______________________________________________________________________ 36
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

glEnd();
factor++;
}
//Deshabilitando el Punteo
glDisable(GL_LINE_STIPPLE);

9. Ejecute su programa y le mostrará similar a la figura 14

Figura 14. Línea con ancho y líneas punteadas.

______________________________________________________________________ 37
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Práctica número 10: Dibujo de Triángulos

Objetivo: Graficar Triángulos en 3D.

Para dibujar un triángulo en OpenGL se utiliza la primitiva GL_TRIANGLES, por


ejemplo si se quiere mostrar un triángulo en las siguientes coordenadas; (0,0, 0),
(100, 100, 0), (100, 0, 0), tiene que seguir los siguientes pasos:
1. Abrir un proyecto y en OpenGL muestre en líneas los ejes x, y y z. en color
rojo, verde y azul respectivamente.
2. Dibuje un triángulo con las coordenadas anteriores de color amarillo

glColor3f(1,1,0);
glBegin(GL_TRIANGLES);
glVertex3f(0,0,0);
glVertex3f(100,100,0);
glVertex3f(100,0,0);
glEnd();

3. Dibuje un triángulo más con las coordenadas (0,0,0), (-100,100,0), (-100,0,0) de


color verde

glColor3f(0,1,0);
glBegin(GL_TRIANGLES);
glVertex3f(0,0,0);
glVertex3f(-100,100,0);
glVertex3f(-100,0,0);
glEnd();

El triángulo amarillo de acuerdo al orden que especificaron las coordenadas Giran


en el sentido de las manecillas del reloj, el triángulo verde las coordenadas
fueron especificadas en el orden Sentido contrario a las manecillas del reloj,
OpenGL considera que los polígonos que giran en el sentido contrario de las
manecillas del reloj miran de frente, lo que significa que la figura del triángulo
verde muestra la parte frontal triángulo y la figura del triángulo amarillo muestra la
parte posterior del triángulo, figura 15 y 16.

______________________________________________________________________ 38
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Figura 15. Triángulos.

V4 V1

V3 V2
V5 V0

Figura 16. Figura derecha: triángulo dibujado en el sentido las manecillas del reloj, figura
Izquierda: triángulo dibujado en el sentido contrario a las manecillas del reloj.

______________________________________________________________________ 39
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

¿Importancia del porqué saber la parte frontal o posterior de un triángulo? En


ejercicios siguientes se aplicarán características físicas distintas en la parte frontal
y posterior de un polígono, como aplicar color y una propiedad reflectante.

Para invertir el comportamiento predeterminado de OpenGL debemos llamar a la


siguiente función:
glFrontFace (GL_CW);
El parámetro GL_CW le indica a OpenGL que los polígonos girados en el sentido
las agujas del reloj se van a considerar frontalmente, para cambiar de nuevo el
giro se usa GL_CCW

Primitiva GL_TRIANGLE_STRIP
Dibuja un triángulo, y cada nuevo vértice se interpreta como un triángulo entre los
dos anteriores vértices y el nuevo.

Dibuje un triángulo en las siguientes coordenadas usando GL_TRIANGLE_STRIP


(0,0,0), (50,0,0), (25,25,0)
Ejecute el programa, figura 17.a, agregue la siguiente coordenada (60, 25, 0) y se
formará un nuevo triángulo a partir de los dos vértices anteriores, figura 17.b,
agregue la coordenada (50, 50, 0), figura 17.c, el código para dibujar la banda de
triángulos es:
glColor3f(1,1,0);
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(0,0,0);
glVertex3f(50,0,0);
glVertex3f(25,25,0);

glColor3f(0.5,0.5,1);
glVertex3f(60,25,0);
glColor3f(0.5,0.5,0.5);
glVertex3f(50,50,0);

glEnd();

Figura 17. a.

______________________________________________________________________ 40
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Figura 17. b.

Figura 17. c.

Primitiva GL_TRIANGLE_FAN
Genera un conjunto de triángulos rellenos conectados entre sí, con la
característica de que todos los triángulos tienen un vértice en común. El primer
triángulo define el vértice común a todos los triángulos.

Dibuje una serie de triángulos a partir del vértice (0, 0, 0) usando


GL_TRIANGLE_FAN, el siguiente código genera los triángulos de la figura 18
glColor3f(1,0,0);
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0,0,0);
glVertex3f(25,-25,0);
glVertex3f(35,0,0);

glColor3f(1,1,0);
glVertex3f(35,25,0);

______________________________________________________________________ 41
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

glColor3f(1,0,0);
glVertex3f(0,35,0);

glColor3f(1,0,1);
glVertex3f(-25,25,0);

glColor3f(0,1,1);
glVertex3f(-35,0,0);

glColor3f(1,1,1);
glVertex3f(-25,-25,0);

glColor3f(0.5,1,1);
glVertex3f(0,-35,0);

glColor3f(0.5,0.5,1);
glVertex3f(25,-25,0);

glEnd();

Figura 18. Abanico de triángulos usando GL_TRIANGLE_FAN.

______________________________________________________________________ 42
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Práctica número 11: Profundidad y eliminación de superficies y


selectiva.

Objetivo: Usar el buffer de profundidad, eliminación de superficies y


eliminación selectiva.

Para usar la buffer de profundidad, eliminación de superficies y eliminación


selectiva, siga los siguientes pasos:

1. Abra un proyecto en el cual muestre los x, y, z de color diferente.


2. Aplique rotación en el eje x y y
3. En el evento OnInit de OpenGLPanel1 antes de asignar color agregue la
siguiente función glEnable(GL_DEPTH_TEST);

4. Modifique en el evento OnPaint por


glMatrixMode(GL_MODELVIEW);
glLoadIdentity();//Remplaza la matriz identidad
//aquí se dibuja todo
glColor3f(0.0f,1.0f,0.0f); //color de dibujo
glShadeModel(GL_FLAT);//Establece en plano el modelo de color de
sombra

//Polígonos con giro en el sentido de las agujas del reloj miran de frente
//se invierte porque estamos usando un abanico
glFrontFace(GL_CW);

// EjesColor(); // llamada a función que dibuja líneas de color en los ejes x,


y, z
Triangulo();

5. Declare la función “triángulo”


6. Declare la librería math.h
7. En el archivo Unit.h (según sea el nombre declare las siguientes variables
float PI;
bool iProfundidad, iContorno, iSeleccionar;

8. En el evento OnCreate del formulario inicialice

PI=3.1415;
OpenGLPanel1->Width=Form1->Width;
OpenGLPanel1->Height=Form1->Height;
iSeleccionar = 0;
iContorno = 0;
iProfundidad = 0;

______________________________________________________________________ 43
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

9. Agregue un Menú Emergente (PopupMenu), que tenga las siguientes


opciones:
a. Eliminación Selectiva
b. Profundidad
c. Posterior al Polígono

10. De clic en panel de OpenGL, seleccione la propiedad PopUpMenu elija


PopupMenu1.
11. En cada uno de los menús correspondientes agregue el código
void __fastcall TForm1::Seleccionar1Click(TObject *Sender)
{
iSeleccionar = !iSeleccionar;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Profundidad1Click(TObject *Sender)


{
iProfundidad = !iProfundidad;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::PosteriordelPoligono1Click(TObject *Sender)


{
iContorno = !iContorno;
}
//---------------------------------------------------------------------------

12. En la función “triángulo” agregue el siguiente código

GLfloat x,y,angulo; //para almacenar las coordenadas y el ángulo


int iPivote = 1; //para indicar los colores alternativos

//Limpiar la ventana y el búfer de profundidad


glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Cambiar a seleccionar si se ha establecido indicador


if(iSeleccionar)
glEnable(GL_CULL_FACE);
else
glDisable(GL_CULL_FACE);

// Activar prueba de profundidad si se ha establecido el indicador


if(iProfundidad)
glEnable(GL_DEPTH_TEST);
else
glDisable(GL_DEPTH_TEST);

______________________________________________________________________ 44
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

// Dibujar la parte posterior sólo como estructura si se ha establecido


indicador
if(iContorno)
glPolygonMode(GL_BACK, GL_LINE); //para relleno(s/n)
else
glPolygonMode(GL_BACK, GL_FILL);

// Guardar estado de matrix y realizar la rotación.


glPushMatrix();
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);

// iniciar un abanico de triángulos


glBegin(GL_TRIANGLE_FAN);

// La cúspide del cono es un vértice compartido para el abanico


// movido hacia arriba en el z para producir un como en lugar de un
circulo
glVertex3f(0.0f, 0.0f, 75.0f);

//Crear un bucle en un círculo y especificar puntos pares en el círculo


//como vértices del abanico de triángulos
for(angulo = 0.0f; angulo < (2.0f*PI); angulo += (PI/8.0f))
{
// Calcular posiciones x e y de siguiente vértice
x = 50.0f*sin(angulo);
y = 50.0f*cos(angulo);

// alternar color entre rojo y verde


if((iPivote %2) == 0)
glColor3f(0.0f, 1.0f, 0.0f);
else
glColor3f(1.0f, 0.0f, 0.0f);

// Incrementar pivote para cambiar color la próxima vez


iPivote++;

// Especificar el siguiente vértice del abanico de triángulos


glVertex2f(x, y);
}

// dibujar abanico para el cono


glEnd();

// glFrontFace(GL_CCW);
// Iniciar un nuevo abanico de triángulos para cubrir la parte inferior
______________________________________________________________________ 45
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

glBegin(GL_TRIANGLE_FAN);

// El origen se encuentra en el centro del abanico


glVertex2f(0.0f, 0.0f);
for(angulo = 0.0f; angulo < (2.0f*PI); angulo += (PI/8.0f))
{
// calcular la posición x e y del siguiente vértice
x = 50.0f*sin(angulo);
y = 50.0f*cos(angulo);

// Alternar colores entre rojo y verde


if((iPivote %2) == 0)
glColor3f(0.0f, 1.0f, 0.0f);
else
glColor3f(1.0f, 0.0f, 0.0f);
// incrementar eje para cambiar color la próxima vez
iPivote++;
// Especificar el siguiente vértice del abanico de triángulos
glVertex2f(x, y);
}
//dibujar el dibujo del abanico que cubre la parte inferior
glEnd();
//Reestablecer transformaciones
glPopMatrix();
//Limpiar comandos de dibujo
glFlush();
13. Ejecute el programa, figura 19.

Figura 19. Cono.

______________________________________________________________________ 46
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Primeramente se dibuja el Cono posteriormente la parte inferior del cono en un


plano xy.

glShadeModel(GL_FLAT);
Le especifica a OpenGL que rellene los polígonos con el color sólido del último
vértice especificado.

glShadeModel(GL_SMOOTH);
Le especifica a OpenGL que sombreará los triángulos suavemente desde cada
vértice.

• Eliminación de superficies
Verifique que el rotar el cono la parte inferior se tambalea, es decir, en OpenGL el
último objeto dibujado aparecerá sobre los anteriores, para corregir se usa una
opción denominada prueba de profundidad, figura 20.
Para activar llamamos a:
glEnable(GL_DEPTH_TEST);
En código encontrará esto:

// Activar prueba de profundidad si se ha establecido el indicador


if(iProfundidad)
glEnable(GL_DEPTH_TEST);
else
glDisable(GL_DEPTH_TEST);

Figura 20. Prueba de Eliminación de superficies

• El búfer de profundidad
Limpiar la ventana y el búfer de profundidad es análogo al de color en cuánto qué
contiene información sobre la distancia de los píxeles desde espectador, esta
información se usa para determinar si algún píxel quedó oculto por píxeles que se
encuentran más cerca del espectador.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

______________________________________________________________________ 47
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

• Eliminación selectiva: Ocultar superficies para mejorar rendimiento


En el término que usamos para describir la técnica de eliminar objetos
geométricos que sabemos que nunca vamos a ver, es una selección de partes
posteriores, en nuestro ejemplo usamos esta técnica para ocultar los objetos que
están en la parte posterior, para saber si un objeto esta en la parte frontal o
posterior es con el giro, figura 21.
En código es:
// Cambiar a seleccionar si se ha establecido indicador
if(iSeleccionar)
glEnable(GL_CULL_FACE);
else
glDisable(GL_CULL_FACE);

Figura 21. Eliminación selectiva

ƒ Modos de Polígono
No es necesario rellenar los polígonos con el color actual, de forma
predeterminada los polígono se rellenan de este color, pero puede cambiarse este
comportamiento especificando que los polígonos deben dibujarse como esquemas
o sólo puntos (sólo se tranzan los vértices).

La función glPolygonMode permite interpretar los polígonos como elementos


sólidos rellenos, como esquemas o como puntos, así como a ambos lados o sólo
la parte posterior, figura 22 y figura 23.

// Dibujar la parte posterior sólo como estructura si se ha establecido indicador


if(iContorno)
glPolygonMode(GL_BACK,GL_LINE);
else
glPolygonMode(GL_BACK,GL_FILL);

______________________________________________________________________ 48
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Figura 22. Polígono relleno.

Figura 23. Polígono (Parte) sin relleno.

______________________________________________________________________ 49
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Práctica número 12: Polígonos

Objetivo: Dibujar Polígonos usando las primitivas GL_QUADS,


GL_QUAD_STRIP y GL_POLYGON de OpenGL.

Para conocer como dibujar polígonos siga los siguientes pasos:


1. En un proyecto nuevo dibuje los ejes x, y, y z de color diferente cada uno.
2. Aplique rotación en el eje x y y
3. Para dibujar un rectángulo se utiliza la primitiva GL_QUADS, por ejemplo si
se quiere dibujar un rectángulo, similar al de la figura 24.

Vértice 2 Vértice 3

Vértice 1 Vértice 4

Figura 24. Rectángulo.

Basta con especificar dichos vértices

glColor3f(1,0,0);
glBegin(GL_QUADS);
glVertex3f(-50,-50,50);
glVertex3f(-50,50,50);
glVertex3f(50,50,50);
glVertex3f(50,-50,50);
glEnd();

4. Para realizar una banda de cuadriláteros, se utiliza la primitiva


GL_QUAD_STRIP, ejemplo si se quiere tener una banda similar a la figura
25 deben especificarse los vértices de la siguiente manera.

//banda de cuadriláteros
glColor3f(1,1,0);
glBegin(GL_QUAD_STRIP);
glVertex3f(-50,-50,-50);
glVertex3f(-50,50,-50);
glVertex3f(50,-50,-50);
glVertex3f(50,50,-50);

______________________________________________________________________ 50
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

glColor3f(0,1,1);
glVertex3f(100,-50,-50);
glVertex3f(100,50,-50);

glColor3f(1,1,1);
glVertex3f(150,-50,-50);
glVertex3f(150,50,-50);
glEnd();

Vértice 2 Vértice 3 Vértice 2 Vértice 4 Vértice 6

Vértice 1 Vértice 4 Vértice 1 Vértice 3 Vértice 5

Figura 25. Banda de cuadriláteros.

Y al ejecutar el programa, mostrará similar a la figura 26

Figura 26. Usando las primitivas GL_QUADS y GL_QUAD_STRIP.

5. Para dibujar un polígono con cualquier número de lados, figura 27, se utiliza
la primitiva GL_POLYGON, Para dibujar un polígono similar al de figura 27
con el siguiente código:

//polígonos

______________________________________________________________________ 51
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

glColor3f(0,1,0);
glBegin(GL_POLYGON);
glVertex3f(-50,50,0);
glVertex3f(40,40,0);

glVertex3f(50,30,0);
glVertex3f(50,-50,0);
glVertex3f(-50,-50,0);
glEnd();

Vértice 1 Vértice 2

Vértice 3

Vértice 4
Vértice 6

Figura 27. Polígono.

______________________________________________________________________ 52
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Práctica número 13: Relleno de polígonos

Objetivo: Conocer como rellenar polígonos con punteo.

Cuando genera un polígono, éste se rellena de forma sólida con el último color
especificado, tal como se vio en la práctica 12, para rellenar un polígono en forma
de punteo siga los siguientes pasos:
1. Abrir un proyecto en el cual muestre los ejes x, y y z de color diferente.
2. Aplique rotación en el x, y y z.
3. Dibuje un polígono con 8 lados de igual tamaño

Patrón de Relleno
Para rellenar un polígono existen dos formas: texturas (no incluye en este manual)
y un patrón de punteo, similar al de líneas realizado en la práctica nueve.
Un patrón de punteo de polígonos es un mapa de bits de 32 x 32 que usa para el
patrón de relleno.

Para habilitar el punteo se utiliza

glEnable(GL_POLYGON_STIPPLE)

Y enseguida se llama a

glPolygonStipple(pBitmap);

donde:
pBitmap es un apuntador a un área de datos que contiene el patrón de punteo. A
partir de ese momento todos los polígonos se rellenarán con el patrón de punteo
especificado por pBitmap (GLubyte *).

4. Dibuje una firma o iniciales en cuadricula de 32 X 32, ejemplo figura 28


5. Defina una matriz de tipo byte

GLubyte Firma[]= {0x00, 0x00, 0x00, 0x00


0x00, 0x00, 0x00, 0x00
.
.
.
0x80, 0x00, 0xF0, 0x20
.
.
.
}
Cada fila de la figura corresponderá a una fila de la matriz, la primera fila de la
matriz corresponde a la última fila de la figura, los números de la matriz son en
hexadecimal.

______________________________________________________________________ 53
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Cada línea de la figura tiene 32 píxeles (cuadros), este se divide en grupos de 8


elementos, formando 4 grupos. Cada grupo representa un número en hexadecimal
de dos cifras y cada numero se obtiene si la línea (cuadro) de la figura está
marcado o no.
8 4 2 1 8 4 2 1 8 4 2 1 8 4 2 1 8 4 2 1 8 4 2 1 8 4 2 1 8 4 2 1

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

1 6 3 1 8 4 2 1 1 6 3 1 8 4 2 1 1 6 3 1 8 4 2 1 1 6 3 1 8 4 2 1
2 4 2 6 2 4 2 6 2 4 2 6 2 4 2 6
8 8 8 8
Figura 28. Firma en una cuadrícula.

Tomando una línea (marcada con x, figura 29) de la figura 28, los valores en
hexadecimal corresponden a la tabla 1.

______________________________________________________________________ 54
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Figura 29. Línea de la cuadricula

Tabla 1. Valores en hexadecimal correspondiente a la figura 29.

0x80 0x00 0xF0 0x20

Los cuatro Los cuatro Los cuatro Los primeros


cuadros cuadros cuadros cuatro cuadros
siguientes, siguientes, siguientes, (derecha a
marcados con marcados con marcados con izquierda),
X, no están X, no están X, no están marcados con
rellenos, por lo rellenos, por lo rellenos, por lo X, no están
tanto, tanto, tanto, rellenos por lo
corresponde un corresponde corresponde un tanto,
0. un 0. 0. corresponde un
Los siguientes valor
cuatro Los siguientes Los siguientes hexadecimal 0.
marcados con cuatro cuatro
X, sólo, está marcados con marcados con Los siguientes
relleno el X, no están X, están cuatro cuadros,
tercero, por lo rellenos, por lo rellenos, por lo marcados con
tanto, tanto, tanto, X, el segundo
corresponde a corresponde corresponde a cuadro está
un 8. un 0. F. relleno o pasa
Por la siguiente parte de la
razón. firma, por lo
cuadro 1 = 1, tanto,
cuadro 2 = 2, corresponde un
cuadro 3 = 4 y 2.
cuadro 4 = 8.
sumando
1 + 2+4+8 = 15
15 = F.

y así sucesivamente se realiza para las demás líneas.

6. Declare la matriz
GLubyte fuego[128] = { 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,

______________________________________________________________________ 55
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

0x00, 0x00, 0x00, 0x00,


0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xc0,
0x00, 0x00, 0x01, 0xf0,
0x00, 0x00, 0x07, 0xf0,
0x0f, 0x00, 0x1f, 0xe0,
0x1f, 0x80, 0x1f, 0xc0,
0x0f, 0xc0, 0x3f, 0x80,
0x07, 0xe0, 0x7e, 0x00,
0x03, 0xf0, 0xff, 0x80,
0x03, 0xf5, 0xff, 0xe0,
0x07, 0xfd, 0xff, 0xf8,
0x1f, 0xfc, 0xff, 0xe8,
0xff, 0xe3, 0xbf, 0x70,
0xde, 0x80, 0xb7, 0x00,
0x71, 0x10, 0x4a, 0x80,
0x03, 0x10, 0x4e, 0x40,
0x02, 0x88, 0x8c, 0x20,
0x05, 0x05, 0x04, 0x40,
0x02, 0x82, 0x14, 0x40,
0x02, 0x40, 0x10, 0x80,
0x02, 0x64, 0x1a, 0x80,
0x00, 0x92, 0x29, 0x00,
0x00, 0xb0, 0x48, 0x00,
0x00, 0xc8, 0x90, 0x00,
0x00, 0x85, 0x10, 0x00,
0x00, 0x03, 0x00, 0x00,
0x00, 0x00, 0x10, 0x00 };

7. Agregue las funciones para habilitar el patrón de punteo antes de llamar a


su función que dibuja el polígono.

// Activar el punteo del polígono


glEnable(GL_POLYGON_STIPPLE);

// Especifica un patrón de punteo especificado


glPolygonStipple(fuego);

glColor3f(1.0f,0.0f,0.2f); //rojo
Poly() ; // función que dibuja un polígono

8. Ejecute su programa y el polígono dibujado estará relleno con el patrón de


punteo (fuego), figura 30.

9. En un rectángulo especifique un patrón de punteo de una firma o iniciales.


10. En un Triángulo especifique un patrón de punteo de un ojo.
______________________________________________________________________ 56
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Práctica número 14: Polígonos en vista de puntos, líneas y


rellenos

Objetivo: Conocer como dibujar polígonos válidos, así como en forma de


líneas, puntos y rellenos.

En OpenGL para dibujar un polígono debe seguir las siguientes reglas:


• Los polígonos deben ser planos (los vértices del polígono deben
encontrarse en un solo plano)
• Los polígonos no pueden girarse o doblarse en el espacio (razón para la
cual se usan los triángulos)
• Los bordes no deben intersecarse (cuando se cruzan sus líneas) y deben
ser convexos (no pueden tener sangrías), es decir, dado un polígono y se
traza una línea, esta no debe cruzar más de dos veces sobre el contorno
del polígono, figura 31.

Polígonos Válidos Polígonos No Válidos

Figura 31. Polígonos válidos y no válidos

Ejemplo, si se quiere dibujar una estrella se puede dibujar usando varios


polígonos, siga los siguientes pasos:

1. Abrir un proyecto nuevo


2. Agregue 2 ScrollBars, para rotar los ejes x y y.
3. Agregue una función llamada “triangulo”, agregue código tal que dibuje un
triángulo.

______________________________________________________________________ 57
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

bool bContorno=1;
// guardar el estado de la matriz y hacer la rotación

glRotatef(xRot, 1.0f, 0.0f, 0.0f);


glRotatef(yRot, 0.0f, 1.0f, 0.0f);
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);

glBegin(GL_TRIANGLES);

glEdgeFlag(bContorno);
glVertex2f(-20.0f, 0.0f);
glEdgeFlag(0);
glVertex2f(20.0f, 0.0f);
glVertex2f(0.0f, 40.0f);
glEnd();

La función glPolygonMode permite cambiar el esquema de un polígono


relleno a uno en líneas y con la función glEdgeFlag(); que admite un sólo
parámetro (Falso o verdadero), nos permitirá indicar que si contorno o línea debe
mostrarse o no.

4. defina las siguientes constantes en la cabecera del archivo .cpp


#define MODO_SOLIDO 0
#define MODO_LINEA 1
#define MODO_PUNTO 2
5. declare las siguientes variables (después de TForm1 *Form1;)
int iModo = MODO_SOLIDO;
boolean bContorno = TRUE;
6. agregue un menú emergente con los siguientes submenús

7. En código agregue el código correspondiente


/---------------------------------------------------------------------------

void __fastcall TForm1::MODOSOLIDO1Click(TObject *Sender)


{
iModo = MODO_SOLIDO;
}
//-----------------------------------------------------

______________________________________________________________________ 58
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

void __fastcall TForm1::MODOLINEA1Click(TObject *Sender)


{
iModo = MODO_LINEA;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::MODOPUNTO1Click(TObject *Sender)


{
iModo = MODO_PUNTO;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::OpenGLPanel1MouseDown(TObject


*Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
PopupMenu1->Popup(X, Y);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Si1Click(TObject *Sender)


{
bContorno = TRUE;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::No1Click(TObject *Sender)


{
bContorno = FALSE;
}
//---------------------------------------------------------------------------
8. Agregue una función denominada Estrella, con el siguiente código
//---------------------------------------------------------------------------
void TForm1::ESTRELLA()
{
// limpiar ventana
glClear(GL_COLOR_BUFFER_BIT);
// Dibujar el polígono de acuerdo a la bandera
if(iModo == MODO_LINEA)
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);

if(iModo == MODO_PUNTO)
glPolygonMode(GL_FRONT_AND_BACK,GL_POINT);

if(iModo == MODO_SOLIDO)
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
______________________________________________________________________ 59
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

// Guardar el estado de la matriz y hacer la rotación


glPushMatrix();
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);

glBegin(GL_TRIANGLES);

glEdgeFlag(bContorno);
glVertex2f(-20.0f, 0.0f);
glEdgeFlag(TRUE);
glVertex2f(20.0f, 0.0f);
glVertex2f(0.0f, 40.0f);

glVertex2f(-20.0f,0.0f);
glVertex2f(-60.0f,-20.0f);
glEdgeFlag(bContorno);
glVertex2f(-20.0f,-40.0f);
glEdgeFlag(TRUE);

glVertex2f(-20.0f,-40.0f);
glVertex2f(0.0f, -80.0f);
glEdgeFlag(bContorno);
glVertex2f(20.0f, -40.0f);
glEdgeFlag(TRUE);

glVertex2f(20.0f, -40.0f);
glVertex2f(60.0f, -20.0f);
glEdgeFlag(bContorno);
glVertex2f(20.0f, 0.0f);
glEdgeFlag(TRUE);

// Centro es un cuadrado formado con dos triángulos


glEdgeFlag(bContorno);
glVertex2f(-20.0f, 0.0f);
glVertex2f(-20.0f,-40.0f);
glVertex2f(20.0f, 0.0f);

glVertex2f(-20.0f,-40.0f);
glVertex2f(20.0f, -40.0f);
glVertex2f(20.0f, 0.0f);
glEdgeFlag(TRUE);
glEnd();
glPopMatrix();
}

______________________________________________________________________ 60
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

9. Ejecute el programa, figura 32.

a) b)

c) d)
Figura 32. a) Polígono relleno, b) Polígono en modo línea, c) Polígono en modo puntos y d)
Polígono en modo línea con contorno.

______________________________________________________________________ 61
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Práctica número 15: Limpiar el buffer de color

Objetivo: Conocer como limpiar el buffer de color en un determinado


momento

El buffer es una memoria donde se guarda los colores de la ventana de OpenGL,


para limpiar dicho buffer se utiliza la función: glClear(GL_COLOR_BUFFER_BIT),
en el ejemplo siguiente se limpia el buffer cuando se cumple una condición.
1. Abrir un proyecto nuevo
2. En el evento OnPaint de OpenGL agregue el siguiente código, el cual dibuja un
espiral con puntos:

//aquí se dibuja todo


glColor3f(1.0f,0.0f,0.0f);

//limpiando la ventana de azul


glClearColor(0.0f, 0.0f, 1.0f, 1.0f );

if (angulo<=0.2)
glClear(GL_COLOR_BUFFER_BIT); // limpiar buffer
glPointSize(3);
glBegin(GL_POINTS);
glVertex2d(radio*cos(angulo), radio*sin(angulo));
glEnd();

if(angulo>20)
{
radio=1;
angulo=0;
}

En la condición
if (angulo<=0.2)
glClear(GL_COLOR_BUFFER_BIT);
Se manda a limpiar el buffer cuando esta condición se cumple

3. Declare las siguientes variables en el archivo .h


GLdouble radio;
GLdouble angulo;
4. Inicialícelas en OnCreate del formulario
radio =0.1;
angulo =0.1;
5. Agregue un timer y actualice las variables
radio+=0.5;
angulo+=0.1;
OpenGLPanel1->Invalidate();

______________________________________________________________________ 62
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

6. Ejecute su programa, figura 33

Figura 33. Limpiar buffer

______________________________________________________________________ 63
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Práctica número 16: Rotación, Translación y Escalamiento


Objetivo: Aplicar Rotación, Translación y Escalamiento a objetos.

El formato de Rotación, Translación y Escalamiento es el siguiente:

Rotación
void glRotatef(GLfloat angulo, GLfloat x, GLfloat y, GLfloat z);
Realiza un giro alrededor del eje especificado (x, y y z). El ángulo de giro se
encuentra en la dirección contraria a las agujas del reloj, medidos en grados y
especificados en el argumento ángulo.

Translación
void glTranslatef(GLfloat x, GLfloat y, GLfloat z);
Acepta como parámetros la cantidad de translación a los largo de los ejes x, y y z.

Escalado
glScalef(GLfloat x, GLfloat y, GLfloat z);
Expande o reduce los objetos a lo largo de distintas direcciones en los ejes x, y y
z.

1. En un proyecto nuevo dibuje un cubo


2. Agregue un ScrollBars, figura 34, para modificar el valor de cada uno de los
argumento de las tres funciones, utilice el evento OnChange de cada ScrollBar
puede modificar el valor de cada argumento.

void __fastcall
void __fastcall TForm1::ScrollBar4Change(TObject
TForm1::ScrollBar2Change(TObject *Sender)
*Sender) {
{ zRot=ScrollBar4->Position;
xRot=ScrollBar2->Position; OpenGLPanel1->Invalidate();
OpenGLPanel1->Invalidate(); }

} void __fastcall
//------------------------------------------------- TForm1::ScrollBar5Change(TObject
*Sender)
void __fastcall {
TForm1::ScrollBar3Change(TObject xEsc=ScrollBar5->Position;
*Sender) OpenGLPanel1->Invalidate();
{ }
yRot=ScrollBar3->Position; //-------------------------------------------------
OpenGLPanel1->Invalidate(); --------------------------
}
//-------------------------------------------------

______________________________________________________________________ 64
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

void __fastcall
TForm1::ScrollBar6Change(TObject
*Sender)
{
yEsc=ScrollBar6->Position;
OpenGLPanel1->Invalidate();
}
//-------------------------------------------------

void __fastcall
TForm1::ScrollBar7Change(TObject
*Sender)
{
zEsc=ScrollBar7->Position;
OpenGLPanel1->Invalidate();
}
//-------------------------------------------------

void __fastcall
TForm1::ScrollBar8Change(TObject
*Sender)
{
xTra=ScrollBar8->Position;
OpenGLPanel1->Invalidate();
}
//-------------------------------------------------
void __fastcall
TForm1::ScrollBar9Change(TObject
*Sender)
{
yTra=ScrollBar9->Position;
OpenGLPanel1->Invalidate();
}
//-------------------------------------------------

void __fastcall
TForm1::ScrollBar10Change(TObject
*Sender)
{
zTra=ScrollBar10->Position;
OpenGLPanel1->Invalidate();
}

______________________________________________________________________ 65
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Figura 34. Scrollbars para Rotación, Translación y Escalamiento.

3. En código antes de dibujar el cubo llame las funciones para rotar, trasladar y
escalar

glRotatef(xRot,1,0,0);
glRotatef(yRot, 0,1,0);
glRotatef(zRot,0,0,1);
glScalef(xEsc,yEsc,zEsc);
glTranslatef(xTra,yTra,zTra);

4. Ejecute su programa, figura 35.

a) b)
Figura 35. a) Cubo, b) cubo con rotación, translación y escalamiento.

Actividad: Dibujar el sistema solar, figura 36.

______________________________________________________________________ 66
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Figura 36. Sistema Solar.

______________________________________________________________________ 67
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Práctica número 17: Proyección Ortogonal y en Perspectiva

Objetivo: Aplicar la proyección Ortogonal y en Perspectiva

Proyección se define como la forma de visualizar los objetos en un plano


tridimensional, existen dos formas de proyección:

La primera es la forma ortogonal, este tipo de proyección define un volumen de


vista rectangular, concretamente define un paralelepípedo de tamaño infinito,
figura 38, para entender esta forma dibuje una caja rectangular, similar a la figura
37, como puede observar la caja no pierde tamaño en su forma al ser proyectada
en 3D, esta forma es utilizada para visualizar edificios, planos, los cuales se
requiere que conserven la forma a pesar de la distancia del observador, la función
que permite visualizar los objetos en forma ortogonal es glOrtho, su formato:
glOrtho(xmin,ymin, xmax,ymax, cerca, lejos);

donde:
xmin y ymin, representan la esquina inferior de una vista rectangular
xmax y ymax, representan la esquina superior de una vista rectangular
cerca y lejos son los planos de recorte de la vista rectangular, cerca y lejos
respectivamente del observador.

Nota: los objetos dibujados deben estar dentro de las coordenadas de los planos
cerca y lejos, de lo contrario, si un objeto es dibujado fuera de este rango no se
visualizará.
Hasta aquí todos lo ejemplos mostrados se han graficado usando la proyección
ortogonal, la función glOrtho() se encuentra especificada en el evento OnInit() de
la ventana de OpenGL.

Figura 37. Proyección ortogonal de una caja.

______________________________________________________________________ 68
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

//---------------------------------------------------------------------------
void __fastcall TForm1::OpenGLPanel1Init(TObject *Sender)
{

int h=OpenGLPanel1->Height;
int w=OpenGLPanel1->Width;
GLfloat Rango = 140.0f;
if(h == 0)
h = 1;
glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

if (w <= h)
glOrtho (-Rango, Rango, -Rango*h/w, Rango*h/w, -Rango*2.0f, Rango*2.0f);
else
glOrtho (-Rango*w/h, Rango*w/h, -Rango, Rango, -Rango*2.0f, Rango*2.0f);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

Figura 38. Proyección ortogonal.

La segunda proyección es la perspectiva, esta proyección permite visualizar los


objetos que están más lejos se vean más chicos que los que están más cerca, es
utilizada para cuando se grafican escenas de paisajes, así por ejemplo, una
montaña aunque físicamente es más grande que una que está más cerca, se ve
más chica que la que está más cerca del espectador, para visualizar la caja

______________________________________________________________________ 69
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

dibujada de la figura 37 en perspectiva en el código del evento On Init modifíquelo


por:

int h=OpenGLPanel1->Height;
int w=OpenGLPanel1->Width;
GLfloat Aspecto;
if(h == 0)
h = 1;
glViewport(0, 0, w, h);
Aspecto = w/h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Produce la proyección de perspectiva
gluPerspective(70.0f, Aspecto, 1.0, 400.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

Al ejecutar su programa, se visualizará como la figura 40, la función que se utiliza


es: gluPerspective(apetura, aspecto, pcerca plejos);

donde:
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 planos de corte cercano y
lejano.
La proyección en perspectiva gráficamente se representa como la figura 39.

Figura 39. Proyección en Perspectiva.

______________________________________________________________________ 70
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Figura 40. Proyección en Perspectiva de una caja.

Ejercicio: Al sistema solar graficado en la práctica 16, modifique su proyección a


perspectiva.

______________________________________________________________________ 71
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Práctica número 18: Luz ambiental, difusa y especular

Objetivo: Aplicar luz ambiental, difusa y especular a los gráficos


La luz permite dar una apariencia más real de los objetos, OpenGL maneja tres
tipos de luz que son luz ambiental, difusa y especular.

Luz Ambiental. Es la luz que proviene de muchas partes y que permite iluminar a
un objeto, por ejemplo, la luz que existe en un cuarto cerrado, por tal motivo se
llama ambiental, porque es la que existe en un ambiente, figura 41 a.
Luz difusa. Es luz que proviene de un reflejo, que puede ser un ventana, un
espejo, etc., figura 41 b.
Luz especular. Es la luz que proviene de una fuente en específico, tal como, un
foco, el sol, etc., figura 41 c.

a b c

Figura 41 a. Luz ambiental, c. Luz difusa, c. Luz especular.

La combinación de las luces produce efectos sobre los objetos (materiales), tales
como brillo y color, los cuales se les denomina reflectancia. La intensidad de
iluminación de cada punto de las superficies de los materiales dependerá de:
Intensidad= Luz ambiente + Luz difusa + Luz especular.
OpenGL tiene las siguientes funciones para especificar la luz tanto de los
materiales como de iluminación que son: glLightModelfv() y glLightfv().

Para dar una iluminación plana a los materiales se utiliza la función: glShadeModel
(GL_FLAT ) y para una iluminación suave se utiliza la función: glShadeModel
(GL_SMOOTH ) ;

Para visualizar una esfera, figura 42, con iluminación el código fuente es el
siguiente:

En el archivo .cpp de c++ builder 5


#include <vcl.h>
#pragma hdrstop

______________________________________________________________________ 72
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "OpenGLPanel"
#pragma resource "*.dfm"
TForm1 *Form1;
// Rotación
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;
// valores y coordenadas de la luz
GLfloat PosicionLuz[] = { 0.0f, 0.0f, 75.0f, 1.0f };
GLfloat LuzEspecular[] = { 1.0f, 0.0f, 0.0f, 1.0f};
GLfloat Reflectancia[] = { 1.0f, 1.0f, 1.0f, 1.0f};

a)

b)
Figura 42. a) Iluminación en modo plano. b) Iluminación en modo suave.

______________________________________________________________________ 73
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

GLfloat LuzAmbiente[] = { 0.5f, 0.5f, 0.5f, 1.0f};


GLfloat DirPunto[] = { 0.0f, 0.0f, -1.0f };
// banderas para efectos
#define MODO_PLANO 1
#define MODO_SUAVE 2
int Forma = MODO_PLANO;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{}
//---------------------------------------------------------------------------
void __fastcall TForm1::OpenGLPanel1Resize(TObject *Sender)
{
glViewport(0,0,OpenGLPanel1->ClientWidth,OpenGLPanel1-
>ClientHeight);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OpenGLPanel1Paint(TObject *Sender)
{
glEnable(GL_DEPTH_TEST); // Eliminar superficie oculta
// glFrontFace(GL_CCW); // Polígonos que miran en el sentido contrario al
de las //agujas del reloj
// glEnable(GL_CULL_FACE); // no intentar mostrar los lados
posteriores
// activar iluminación
glEnable(GL_LIGHTING);
// Establecer y activar 0 de luz
//suministrar una ligera luz ambiente para poder ver los objetos
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, LuzAmbiente);
//La luz esta compuesta solamente de luz ambiente y especular
glLightfv(GL_LIGHT0,GL_DIFFUSE,LuzAmbiente);
glLightfv(GL_LIGHT0,GL_SPECULAR,LuzEspecular);
glLightfv(GL_LIGHT0,GL_POSITION,PosicionLuz);
//Especificar efectos de puntos
//el ángulo de corte es de 60 grados
glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,50.0f);
//Activar esta luz en concreto
glEnable(GL_LIGHT0);
// Activar registro de color
glEnable(GL_COLOR_MATERIAL);
//activar las propiedades de color que siguen a glcolor
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
//a partir de ahora todos los materiales tienen una reflectancia
//especular plena de un alto brillo
glMaterialfv(GL_FRONT, GL_SPECULAR,Reflectancia);
glMateriali(GL_FRONT, GL_SHININESS,128);
// Fondo color negro
______________________________________________________________________ 74
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

glClearColor(0.0f, 0.0f, 1.0f, 1.0f );


//función
LuzPunto();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OpenGLPanel1Init(TObject *Sender)
{
int w=OpenGLPanel1->Width;
int h=OpenGLPanel1->Height;
GLfloat fAspect;
if(h == 0)
h = 1;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
fAspect = (GLfloat) w / (GLfloat) h;
gluPerspective(35.0f, fAspect, 1.0f, 500.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -250.0f);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
OpenGLPanel1->Width=Form1->Width;
OpenGLPanel1->Height=Form1->Height;
xRot = 0.0f;
yRot = 0.0f;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender)
{
OpenGLPanel1->Width=Form1->Width;
OpenGLPanel1->Height=Form1->Height;
OpenGLPanel1->Invalidate();
}
//---------------------------------------------------------------------------
void TForm1::LuzPunto()
{
GLUquadricObj *pObj;
pObj = gluNewQuadric();
gluQuadricNormals(pObj, GLU_SMOOTH);
if(Forma == MODO_PLANO)
glShadeModel(GL_FLAT);
else // FORMA = MODO_SUAVE;
glShadeModel(GL_SMOOTH);
// Limpiar la venta con el color de borrado actual
______________________________________________________________________ 75
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Colocar primero la luz
// Guardar las transformadas de las coordenadas
glPushMatrix();
// Rotar el sistema de coordenadas
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
//Especificar la nueva posición y dirección en coordenada rotadas
glLightfv(GL_LIGHT0,GL_POSITION,PosicionLuz);
glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,DirPunto);
// dibujar un cono rojo para introducir la fuente de luz
glColor3ub(255,0,0);
// glColor3ub(0,255,0);
// Trasladar origen para mover el cono donde esta la luz situada
glTranslatef(PosicionLuz[0],PosicionLuz[1],PosicionLuz[2]);
// gluCylinder(pObj, 5,1,7, 15, 15);
gluCylinder(pObj, 2,3,17, 15, 15);
// Dibujar una esfera desplazada para denotar la bobilla de luz
//guardar las variables de estado de iluminación
glPushAttrib(GL_LIGHTING_BIT);
// Apagar la iluminación y especificar una esfera amarilla brillante
glDisable(GL_LIGHTING);
//glColor3ub(255,255,0);
glColor3ub(255,0,0);
// gluSphere(pObj, 4, 15, 15);
gluSphere(pObj, 2, 5, 5);
// Restablecer las variables del estado de iluminación
glPopAttrib();
// Restablecer las transformaciones de coordenadas
glPopMatrix();
// Establecer el color del material y dibujar una esfera en el centro
glColor3ub(255,0, 0 ); //rojo
gluSphere(pObj, 55, 50, 50);

}
//---------------------------------------------------------------------------
void __fastcall TForm1::ScrollBar1Change(TObject *Sender)
{
xRot=ScrollBar1->Position;
OpenGLPanel1->Invalidate();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ScrollBar2Change(TObject *Sender)
{
yRot=ScrollBar2->Position;
OpenGLPanel1->Invalidate();
}
______________________________________________________________________ 76
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

//---------------------------------------------------------------------------
void __fastcall TForm1::Plano1Click(TObject *Sender)
{
Forma = MODO_PLANO;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Suave1Click(TObject *Sender)
{
Forma = MODO_SUAVE;
}
//---------------------------------------------------------------------------
En el archivo .h de c++ builder 5 declare de forma pública la función “LuzPunto”

public: // User declarations


void LuzPunto();

______________________________________________________________________ 77
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Práctica número 19: Sombras

Objetivo: Agregar sombra a los gráficos

La sombra es un efecto que permite dar una apariencia más real a los objetos
graficados, una sombra es la ausencia de luz producida por la superposición de un
cuerpo opaco entre una fuente de luz y otro cuerpo, en OpenGL para generar el
efecto de sombra se tienen que especificar los siguientes puntos:
1. Graficar un objeto
2. Especificar un punto como fuente de luz
3. Generar una matriz de proyección en la cual se calculará el plano de
proyección donde se quiere la sombra.
En la figura 43 se observa el efecto de sombra, donde la fuente de luz se
representa por un círculo amarillo, el objeto opaco que se superpone a la luz y la
sombra.

Figura 43. Sombra

El código correspondiente a la figura 43 es:

#include <GL/glu.h>
#include <vcl.h> #include <GL/gl.h>
#pragma hdrstop //-----------------------------------------------------------
----------------
#include "Unit1.h" #pragma package(smart_init)
#include <math.h> #pragma link "OpenGLPanel"
#include <math.h> #pragma resource "*.dfm"
//#include <GL/glaux.h> TForm1 *Form1;
#include <GL/glut.h> void Base();

______________________________________________________________________ 78
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

void Pinata(); glViewport(0,0,OpenGLPanel1-


void Sol(); >ClientWidth,OpenGLPanel1->ClientHeight);
}
void gltMakeShadowMatrix(GLfloat //-----------------------------------------------------------
puntos[3][3], GLfloat lightPos[4], GLfloat ----------------
destMat[16]); void __fastcall
void gltGetNormalVector(const GLfloat vP1[], TForm1::OpenGLPanel1Paint(TObject
const GLfloat vP2[], const GLfloat vP3[], *Sender)
GLfloat vNormal[]); {
void gltSubtractVectors(const GLfloat vFirst[],
const GLfloat vSecond[], GLfloat vResult[]); glEnable(GL_DEPTH_TEST);
void gltVectorCrossProduct(const GLfloat glFrontFace(GL_CCW);
vU[], const GLfloat vV[], GLfloat vResult[]); glEnable(GL_CULL_FACE);
void gltNormalizeVector(GLfloat vNormal[]);
void gltScaleVector(GLfloat vVector[], const glEnable(GL_LIGHT0);
GLfloat fScale);
void gltGetPlaneEquation(GLfloat vPoint1[], // color de fondo
GLfloat vPoint2[], GLfloat vPoint3[], GLfloat glClearColor(0.0f, 0.0f, 1.0f, 1.0f );
vPlane[]);
GLfloat gltGetVectorLength(const GLfloat //cálculo de la matriz de proyección para
vVector[]); dibujar la sombra en el suelo
GLfloat gltGetVectorLengthSqrd(const gltMakeShadowMatrix(points, LuzPosicion,
GLfloat vVector[]); shadowMat);
//funcion que dibuja el avión
// Para realizar la rotación Sombra();
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f; }
GLfloat LuzPosicion[4] = {-75, 150.0f, 0, 0.0f //-----------------------------------------------------------
}; ----------------
void __fastcall
// Una matriz de transformación para TForm1::OpenGLPanel1Init(TObject
proyectar la sombra *Sender)
GLfloat shadowMat[16]; {
int w=OpenGLPanel1->Width;
//cualquier de estos tres puntos en el int h=OpenGLPanel1->Height;
suelo(en el sentido contrario a las agujas del GLfloat fAspect;
reloj)
GLfloat points[3][3] = {{ -30.0f, -149.0f, -20.0f if(h == 0)
},{ -30.0f, -149.0f, 20.0f }, { 40.0f, -149.0f, h = 1;
20.0f }};
glViewport(0, 0, w, h);
//-----------------------------------------------------------
---------------- glMatrixMode(GL_PROJECTION);
__fastcall TForm1::TForm1(TComponent* glLoadIdentity();
Owner)
: TForm(Owner) fAspect = (GLfloat)w/(GLfloat)h;
{ gluPerspective(60.0f, fAspect, 200.0,
} 500.0);
//-----------------------------------------------------------
---------------- glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

void __fastcall // Mover en el eje z para que se pueda ver


TForm1::OpenGLPanel1Resize(TObject glTranslatef(0.0f, 0.0f, -400.0f);
*Sender)
{

______________________________________________________________________ 79
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

//Prepararse para dibujar la sombra del


glLightfv(GL_LIGHT0,GL_POSITION,LuzPosi suelo
cion); //Desactiva la iluminación primero y
} guardad el estado de la proyección
//----------------------------------------------------------- glDisable(GL_DEPTH_TEST);
---------------- glDisable(GL_LIGHTING);
void __fastcall TForm1::FormCreate(TObject glPushMatrix();
*Sender)
{ // Multiplicar por la matriz de proyección de
sombra
OpenGLPanel1->Width=Form1->Width; glMultMatrixf((GLfloat *)shadowMat);
OpenGLPanel1->Height=Form1->Height;
// Girar ahora el avión en el espacio recién
xRot = 0.0f; aplastado
yRot = 0.0f; glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
}
//----------------------------------------------------------- // Pasar 1 para indicar dibujo de sombra
---------------- Dibujo(1);
void __fastcall TForm1::FormResize(TObject
*Sender) // Reestablecer la proyección normal
{ glPopMatrix();
OpenGLPanel1->Width=Form1->Width;
OpenGLPanel1->Height=Form1->Height; // Dibujar la fuente de luz
glPushMatrix();
OpenGLPanel1->Invalidate(); Sol();
} glPopMatrix();
//-----------------------------------------------------------
---------------- // Reestablecer las variables de estado de
void TForm1::Sombra() iluminación
{ glEnable(GL_DEPTH_TEST);

// Borrar la ventana con el borrado actual


glClear(GL_COLOR_BUFFER_BIT | }
GL_DEPTH_BUFFER_BIT); void __fastcall
Base(); TForm1::FormKeyPress(TObject *Sender,
char &Key)
// guardar el estado de la matriz y efectuar {
rotaciones if(Key ==(char)"A")
glPushMatrix(); xRot-= 5.0f;

//dibujar el avión en la nueva orientación, if(Key == (char)"B")


situar la luz en la posición correcta antes de xRot += 5.0f;
girar el avión
glEnable(GL_LIGHTING); if(Key == (char) "C")
yRot -= 5.0f;
glLightfv(GL_LIGHT0,GL_POSITION,LuzPosi
cion); if(Key == (char) "D")
glRotatef(xRot, 1.0f, 0.0f, 0.0f); yRot += 5.0f;
glRotatef(yRot, 0.0f, 1.0f, 0.0f); OpenGLPanel1->Invalidate();
Dibujo(0); }
//-----------------------------------------------------------
// Reestablecer el estado de la matriz ----------------
original void __fastcall
glPopMatrix(); TForm1::ScrollBar1Change(TObject *Sender)
{

______________________________________________________________________ 80
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

xRot=ScrollBar1->Position;
OpenGLPanel1->Invalidate(); // Realizar ahora la proyección
} // primer columna
//----------------------------------------------------------- destMat[0] = dot - vLightPos[0] *
---------------- vPlaneEquation[0];
void __fastcall destMat[4] = 0.0f - vLightPos[0] *
TForm1::ScrollBar2Change(TObject *Sender) vPlaneEquation[1];
{ destMat[8] = 0.0f - vLightPos[0] *
yRot=ScrollBar2->Position; vPlaneEquation[2];
OpenGLPanel1->Invalidate(); destMat[12] = 0.0f - vLightPos[0] *
} vPlaneEquation[3];
//-----------------------------------------------------------
---------------- // Segunda columna
destMat[1] = 0.0f - vLightPos[1] *
void TForm1::Dibujo(int Tipo) vPlaneEquation[0];
{ destMat[5] = dot - vLightPos[1] *
vPlaneEquation[1];
if(Tipo == 0) destMat[9] = 0.0f - vLightPos[1] *
glColor3ub(128, 128, 128); vPlaneEquation[2];
else destMat[13] = 0.0f - vLightPos[1] *
glColor3ub(0,0,0); vPlaneEquation[3];

if(RadioButton2->Checked==true) //Tercer columna


glutWireSphere(15,15,15); destMat[2] = 0.0f - vLightPos[2] *
vPlaneEquation[0];
if(RadioButton3->Checked==true) destMat[6] = 0.0f - vLightPos[2] *
glutWireTeapot(25); vPlaneEquation[1];
destMat[10] = dot - vLightPos[2] *
vPlaneEquation[2];
destMat[14] = 0.0f - vLightPos[2] *
vPlaneEquation[3];
}
// Cuarta columna
//crea una matriz de proyección de sombra a destMat[3] = 0.0f - vLightPos[3] *
partir de los coeficientes vPlaneEquation[0];
//de la ecuación del plano y de la posición de destMat[7] = 0.0f - vLightPos[3] *
la luz, el valor devuelto se guarda en destMat vPlaneEquation[1];
//----------------------------------------------------------- destMat[11] = 0.0f - vLightPos[3] *
-------------------- vPlaneEquation[2];
void gltMakeShadowMatrix(GLfloat destMat[15] = dot - vLightPos[3] *
vPoints[3][3], GLfloat vLightPos[4], GLfloat vPlaneEquation[3];
destMat[16])
{ }
GLfloat vPlaneEquation[4];
GLfloat dot; //-----------------------------------------------------------
--
gltGetPlaneEquation(vPoints[0], vPoints[1], //// Gets the three coefficients of a plane
vPoints[2], vPlaneEquation); equation given three points on the plane.
void gltGetPlaneEquation(GLfloat vPoint1[],
// punto producto del plano y de la posición GLfloat vPoint2[], GLfloat vPoint3[], GLfloat
de la luz vPlane[])
dot = vPlaneEquation[0]*vLightPos[0] + {
vPlaneEquation[1]*vLightPos[1] + // Get normal vector from three points. The
vPlaneEquation[2]*vLightPos[2] + normal vector is the first three coefficients
vPlaneEquation[3]*vLightPos[3]; // to the plane equation...

______________________________________________________________________ 81
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

gltGetNormalVector(vPoint1, vPoint2, //----------------------------


vPoint3, vPlane); // Scales a vector by a scalar
void gltScaleVector(GLfloat vVector[], const
// Final coefficient found by back GLfloat fScale)
substitution {
vPlane[3] = -(vPlane[0] * vPoint3[0] + vVector[0] *= fScale; vVector[1] *= fScale;
vPlane[1] * vPoint3[1] + vPlane[2] * vVector[2] *= fScale;
vPoint3[2]); }
} ///-----------------------------
//------------------------------------ // Gets the length of a vector
// Given three points on a plane in counter GLfloat gltGetVectorLength(const GLfloat
clockwise order, calculate the unit normal vVector[])
void gltGetNormalVector(const GLfloat vP1[], {
const GLfloat vP2[], const GLfloat vP3[], return
GLfloat vNormal[]) (GLfloat)sqrt(gltGetVectorLengthSqrd(vVecto
{ r));
GLfloat vV1[3], vV2[3]; }
//----------------------------------------------------------
gltSubtractVectors(vP2, vP1, vV1); // Gets the length of a vector squared
gltSubtractVectors(vP3, vP1, vV2); GLfloat gltGetVectorLengthSqrd(const
GLfloat vVector[])
gltVectorCrossProduct(vV1, vV2, {
vNormal); return (vVector[0]*vVector[0]) +
gltNormalizeVector(vNormal); (vVector[1]*vVector[1]) +
} (vVector[2]*vVector[2]);
}
//------------------------------ //--------------------------
// Subtract one vector from another void Base()
void gltSubtractVectors(const GLfloat vFirst[], { //dibujar el suelo creamos manualmente una
const GLfloat vSecond[], GLfloat vResult[]) sombra con un verde
{ //más oscuro en el suelo para dar la ilusión
vResult[0] = vFirst[0] - vSecond[0]; de profundidad
vResult[1] = vFirst[1] - vSecond[1]; glBegin(GL_QUADS);
vResult[2] = vFirst[2] - vSecond[2]; glColor3ub(0,32,0);
} glVertex3f(400.0f, -150.0f, -200.0f);
//--------------------------------------------- glVertex3f(-400.0f, -150.0f, -200.0f);
// Calculate the cross product of two vectors glColor3ub(0,255,0);
void gltVectorCrossProduct(const GLfloat glVertex3f(-400.0f, -150.0f, 200.0f);
vU[], const GLfloat vV[], GLfloat vResult[]) glVertex3f(400.0f, -150.0f, 200.0f);
{ glEnd();
vResult[0] = vU[1]*vV[2] - }
vV[1]*vU[2];
vResult[1] = -vU[0]*vV[2] + //--------------
vV[0]*vU[2]; void Pinata()
vResult[2] = vU[0]*vV[1] - {
vV[0]*vU[1]; glutSolidSphere(15, 30, 30);
} }
//----------------------
// Scales a vector by it's length - creates a //-------------------------------------
unit vector void Sol()
void gltNormalizeVector(GLfloat vNormal[]) {
{ glTranslatef(LuzPosicion[0],LuzPosicion[1],
GLfloat fLength = 1.0f / LuzPosicion[2]);
gltGetVectorLength(vNormal); glColor3ub(255,255,0);
gltScaleVector(vNormal, fLength); glutSolidSphere(15, 30, 30);
} }

______________________________________________________________________ 82
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

void __fastcall void __fastcall


TForm1::RadioButton3Click(TObject TForm1::ScrollBar3Change(TObject *Sender)
*Sender) {
{ LuzPosicion[0]=ScrollBar3->Position;
OpenGLPanel1->Invalidate(); OpenGLPanel1->Invalidate();
} }
//----------------------------------------------------------- //-----------------------------------------------------------
---------------- ----------------

void __fastcall void __fastcall


TForm1::RadioButton2Click(TObject TForm1::ScrollBar4Change(TObject *Sender)
*Sender) {
{ LuzPosicion[1]=ScrollBar4->Position;
OpenGLPanel1->Invalidate(); OpenGLPanel1->Invalidate();
} }
//----------------------------------------------------------- //-----------------------------------------------------------
---------------- ----------------

void __fastcall void __fastcall


TForm1::RadioButton1Click(TObject TForm1::ScrollBar5Change(TObject *Sender)
*Sender) {
{ LuzPosicion[2]=ScrollBar5->Position;
OpenGLPanel1->Invalidate(); OpenGLPanel1->Invalidate();
} }

La función gltMakeShadowMatrix(), calcula la matriz de proyección, ésta función


puede descargarse directamente de la página del autor Richard S. Wright:
http://www.1av10.nu/~gerry/c/common/MatrixMath.c.

______________________________________________________________________ 83
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Práctica número 20: Transparencia

Objetivo: Agregar reflejo a los gráficos usando transparencia

El reflejo es un efecto que permite dar una apariencia más real a los objetos
graficados, para conseguir el efecto se utiliza la transparencia de la superficie
reflectante, en OpenGL para generar el efecto se deben seguir los siguientes
pasos:
1. Graficar el objeto de fondo (reflejo)
2. Graficar la superficie reflectante
3. Graficar de forma normal el objeto

Ejemplo, graficar una tetera con reflejo, figura 44, se grafica una tetera (fondo) con
orientación inversa para dar el efecto de reflejo, enseguida se grafica la superficie
que hará el papel de reflejo y por último sobre la superficie se grafica nuevamente
la tetera de forma norma.

Figura 44. Usando transparencia para obtener el efecto reflejo.

El código correspondiente a la figura 44 es:

#pragma resource "*.dfm"


include <vcl.h> TForm1 *Form1;
#pragma hdrstop void DrawGround(void);

#include "Unit1.h"
#include<gl/glut.h> //-----------------------------------------------------------
//----------------------------------------------------------- ----------------
---------------- __fastcall TForm1::TForm1(TComponent*
#pragma package(smart_init) Owner)
#pragma link "OpenGLPanel" : TForm(Owner)

______________________________________________________________________ 84
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

{ glPushMatrix();
} glFrontFace(GL_CW);
//----------------------------------------------------------- glScalef(1,-1,1);
---------------- glColor3f(0,0,0);
void __fastcall Escena(); //fondo
TForm1::OpenGLPanel1Init(TObject
*Sender) glFrontFace(GL_CCW);
{ glPopMatrix();
int w=OpenGLPanel1->Width;
int h=OpenGLPanel1->Height; //Dibujar el suelo transparente sobre el
GLfloat fAspect; reflejo
glDisable(GL_LIGHTING);
if(h == 0) glEnable(GL_BLEND); //fundido de color
h = 1; glBlendFunc(GL_SRC_ALPHA,
GL_ONE_MINUS_SRC_ALPHA); //efecto de
glViewport(0, 0, w, h); dibujar un objeto transparente delante de
algún objeto opaco
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); glColor4f(0.5,0.5,0.5,0.5);
Suelo();
fAspect = (GLfloat)w/(GLfloat)h; //transparencia
gluPerspective(60.0f, fAspect, 1.0, 300.0); glColor4f(1,0,0,0.5);

glMatrixMode(GL_MODELVIEW); glDisable(GL_BLEND);
glLoadIdentity(); glEnable(GL_LIGHTING);

// Mover en el eje z para que se pueda ver // Dibujar escena


glTranslatef(0.0f, 0.0f, -100.0f); glColor3f(0,0,0);
glEnable(GL_DEPTH_TEST); Escena(); // el objeto normal
//color (RGB)del área de trabajo,
glClearColor(0.0f,0.0f,1.0f,1.0); glPopMatrix();
}
//--------------------------------------------------
void __fastcall }
TForm1::OpenGLPanel1Paint(TObject //---------------------------
*Sender) void TForm1::Escena()
{ {
glTranslatef(0,30,0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEP // glutSolidSphere(20,30,30);
TH_BUFFER_BIT); glutWireTeapot(24);
glPushMatrix(); }
//---------------------
glRotatef(5, 1.0f, 0.0f, 0.0f); void TForm1::Ejes()
glRotatef(5, 0.0f, 1.0f, 0.0f); {
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f); glBegin(GL_LINES);
glVertex3f(-200,0,0);
glColor3f(1,0,0); glVertex3f(200,0,0);
Ejes();
glVertex3f(0,-200,0);
glVertex3f(0,200,0);
//Para conseguir el efecto se requiere de
dibujar el objeto de fondo, enseguida el de glVertex3f(0,0,-200);
transparencia glVertex3f(0,0,200);
//Mover la luz debajo del suelo a la luz del glEnd();
objeto reflejado

______________________________________________________________________ 85
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

} fColor = 0.0f;
//---------------------------------------
void TForm1::Suelo() glColor4f(fColor, fColor, fColor,
{ 0.5f);
glVertex3f(iStrip, y, iRun);
glBegin(GL_QUADS); glVertex3f(iStrip + fStep, y, iRun);
glVertex3f(200,0,200);
glVertex3f(200,0,-200); iBounce++;
glVertex3f(-200,0,-200); }
glVertex3f(-200,0,200); glEnd();
}
glEnd(); glShadeModel(GL_SMOOTH);
}
} void __fastcall
//----------------------------------------------------------- TForm1::ScrollBar1Change(TObject *Sender)
---------------- {
void DrawGround(void) xRot=ScrollBar1->Position;
{ OpenGLPanel1->Invalidate();
GLfloat fExtent = 200.0f; }
GLfloat fStep = 5; //-----------------------------------------------------------
GLfloat y = 0.0f; ----------------
GLfloat fColor; void __fastcall
GLfloat iStrip, iRun; TForm1::ScrollBar2Change(TObject *Sender)
GLint iBounce = 0; {
yRot=ScrollBar2->Position;
glShadeModel(GL_FLAT); OpenGLPanel1->Invalidate();
for(iStrip = -fExtent; iStrip <= fExtent; iStrip }
+= fStep) //-----------------------------------------------------------
{ ----------------
glBegin(GL_TRIANGLE_STRIP); void __fastcall TForm1::FormCreate(TObject
for(iRun = fExtent; iRun >= -fExtent; *Sender)
iRun -= fStep) {
{ xRot=0;
if((iBounce %2) == 0) yRot=0;
fColor = 1.0f; }
else //-----------------------------------------------------------
//--------------------------------------------------------------

Para que un objeto sea transparente se debe especificar la transparencia en la


función glColor() en el cuarto argumento, para el ejemplo anterior antes de graficar
el rectángulo (superficie transparente), a glColor4f(1,0,0,0.5); se modificó el
cuarto argumento a un valor de 0.5 correspondiente a transparencia.

______________________________________________________________________ 86
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

______________________________________________________________________ 87
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

______________________________________________________________________ 88
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

______________________________________________________________________ 89
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

______________________________________________________________________ 90
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

______________________________________________________________________ 91
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

______________________________________________________________________ 92
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

______________________________________________________________________ 93
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Conclusiones

Para graficar se requieren de dos elementos básicos, conocer la herramienta para


graficar; puede ser OpenGL, ActiveX u otro, y la creatividad para embonar figuras
básicas, como puntos, líneas, triángulos, rectángulos, esferas, etc. que en
conjunto representen un excelente gráfico, tal como los ejemplos anteriores.

Los efectos 3D, color, iluminación, sombra, transparencia, sin duda alguna ayudan
a tener gráficos con mayor realismo, otros no presentados en este manual son
suavizado de bordes, texturas, manejo de líneas y superficies, música, etc.

Este manual fue presentado con el fin de fomentar el arte por el manejo de los
gráficos y para incrementar el acervo bibliográfico con material de calidad y
utilidad.

______________________________________________________________________ 94
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Agradecimientos

A la Universidad del Mar, campus Puerto Escondido, por facilitarnos tiempo,


instalaciones y recursos económicos para la realización de este manual.

Un especial agradecimiento a los alumnos que colaboraron en la realización de los


gráficos presentados en la portada y ejemplos: Aarón, David, Darwin, Elizabeth,
José y Omar, quienes dedicaron su mejor esfuerzo y muchas horas de trabajo.

Por último, pero no menos importante un agradecimiento a mi familia; mi hija Azul,


mi esposa, mis padres y hermanos, por su tiempo y compresión.

______________________________________________________________________ 95
M.C. Isidro Moctezuma Cantorán
________________________________________________________________________________________

Bibliografía

Programación OpenGL, Richard S. Wringht / Benjamín Lipchak, Anaya


Multimedia, 2005.

Programación C++ Builder 5, Programación, Francisco Charte, Anaya


Multimedia, 2006.

Gráficos por computadora con OpenGL, Donald Hearn, M. Pauline Baker,


Prentice Hall, 2006.

http://www.opengl.org, 2008.

http://www.1av10.nu/~gerry/c/common/MatrixMath, 2008

______________________________________________________________________ 96
M.C. Isidro Moctezuma Cantorán

You might also like