Acerca de
Tutoriales
Comunidad
Actualidad
Enlaces





En macprogramadores.org
En Internet

Tutorial 2: La primera imagen


Una vez que vimos en el tutorial anterior cómo debíamos preparar el entorno para tenerlo listo para empezar a trabajar con OpenGL, ha llegado el momento de realizar nuestros primeros pinitos.

Lo que vamos a hacer es muy sencillo por dos razones. La primera es que simplemente vamos a dibujar un triángulo y un cuadrado, lo que no requiere mayores complicaciones y de esta manera, por una parte vamos aumentando muy poquito a poquito la dificultad y, por otra y a pesar de todo, comprenderemos conceptos OpenGL muy útiles listos para ser empleados en los demás tutoriales. De hecho, el presente tutorial corresponde a los números 2 y 3 de Nehe.

La segunda razón de la simplicidad de nuestro siguiente proyecto es que la mayor parte del trabajo, ¡ya la tenemos hecha!. En efecto, creado el esqueleto de toda aplicación simple OpenGL en el tutorial anterior, ahora sólo queda decirle qué queremos que dibuje; es decir, implementar el método DrawGLScene. Por lo tanto sólo tendremos que modificar su código.

Miremos cómo nos quedó dicho código en el tutorial anterior:

Todo lo que tenemos que hacer es añadir lo que creamos pertinente detrás de ese glLoadIdentity, que recordemos que lo que hacía era resetear la matriz del modelo. En particular nos interesa saber cómo nos ha dejado respecto de la escena. Como puede imaginarse, tras ese glLoadIdentity, en el centro de la imagen está el origen de coordenadas (hacia el que estamos mirando), con el eje X dirigido hacia la derecha, el eje Y hacia arriba y el eje Z hacia nosotros (es decir, estamos mirando a lo largo de la dirección -Z). Es exactamente la misma situación que con el control 3D que incorpora el propio REALbasic. Visualmente:

Vamos ahora a dibujar el triángulo. Para empezar, debemos decidir dónde. Tenemos que hacerlo algo a la izquierda de la pantalla para dejar sitio al cuadrado que también queremos dibujar, y un poco más lejos que el origen de coordenadas pues si no lo tendremos en nuestras propias narices. La situación semeja un poco al viejo lenguaje gráfico Logo. Allí se tenía una tortuga (que llevaba un lápiz) a la que debía decirse cómo moverse por la pantalla y, por tanto, había que tener encuenta en todo momento cuál era su posición. Aquí ocurre lo mismo, siempre tenemos que conocer cual es nuestra posición actual, por decirlo de algún modo. Allí tendrán lugar todas las instrucciones gráficas OpenGL que usemos. Tras el glLoadIdentity dicha posición es el origen de coordenadas o (0,0,0). Añadamos en primer lugar lo siguiente al método DrawGLScene:

glTranslatef -1.5,0.0,-6.0

Precisamente la instrucción glTranslate tiene como misión cambiar esa posición actual a la que hacíamos alusión. Si nos fijamos en sus parámetros, el valor -1.5 indica que nos hemos de desplazar 1.5 unidades hacia la izquierda (eje X), el 0.0 indica que no nos hemos de mover en la dirección vertical de la pantalla (eje Y) y el -6.0 nos dice que debemos avanzar 6 unidades en la dirección hacia el monitor (eje Z). Así mismo, podemos apreciar otra característica y es que muchas funciones (por ejemplo nuestro glTranslate) pueden tener añadido un sufijo. Éste puede ser una f o una d, entre otros. Su misión es indicar el tipo de valor numérico que viene detrás, ya que OpenGL tiene diferentes rutinas optimizadas según sean dichos valores. Así la f indica float, que es el tipo de valor numérico que REALbasic llama Single, mientras que la d indicaría double, término que también emplea REALbasic. Nosotros hemos elegido glTranslatef de acuerdo a la elección del Tutorial 2 de Nehe, pero volveremos a ello más adelante.

Una vez que nos hemos separado del centro, ya estamos en disposición de dibujar el triángulo. Las figuras sencillas se construyen en OpenGL indicando el tipo que deseas crear. Como siempre, esto es para optimizar el resultado y para que las tarjetas gráficas lo realicen rápida y eficientemente (en definitiva, muchas de estas tarjetas se dedican a dibujar simplemente triángulos a una velocidad vertiginosa). Cuando queramos dibujar una figura de tres puntos (como un triángulo), debemos usar la constante GL_TRIANGLES; si son cuatro puntos (cuadrado) GL_QUADS; y si son más GL_POLYGON. La siguiente porción de código es, de esta forma,

glBegin GL_TRIANGLES
glVertex3f 0.0,1.0,0.0
glVertex3f -1.0,-1.0,0.0
glVertex3f 1.0,-1.0,0.0
glEnd

En este bloque, la primera instrucción y la última definen el comienzo de la construcción de un triángulo y su finalización; todas estas estructuras deben empezar con un glBegin y terminar con un glEnd. Por su parte, como podemos ver, los tres vértices del triángulo se indican con glVertex3f, en primer lugar el vértice superior, luego el inferior izquierdo y finalmente el inferior derecho. Y recordemos que todas sus medidas numéricas son con respecto a la posición actual: Las coordenadas de todos esos puntos son 0, indicando que no se desplazan más en el eje Z, sin cambiar el valor actual que era el -6 (¿recuerdas?). Debemos cuidar de que halla tres líneas en el interior del bloque, o más excatamente un múltiplo de tres si es que queremos dibujar más triángulos. De la misma manera, si estamos usando GL_QUADS tendremos 4 líneas o un múltiplo suyo, mientras que no hay restricciones en el número de líneas para GL_POLYGON.

Si ahora ejecutamos el proyecto veremos, quizá para nuestra sorpresa, lo siguiente:

Es decir, nada. ¿Qué ha sucedido? Algo muy sencillo. Hemos creado la escena, pero no le hemos dicho a OpenGL que la muestre. Si nos fijamos en las propiedades del control OGL, veremos que hay una propiedad booleana que por defecto es verdadera; se trata de DoubleBuffered:

El doble buffer significa que toda la escena OpenGL se genera a parte de la escena que actualmente se muestra en pantalla. Eso tiene ventajas a la hora de hacer animaciones más suaves o para controlar con mayor detalle el aspecto que va a tener la imagen final. Cuando nos interesa mostrarla, una vez que ya la tengamos construída, sólo debemos volcar el buffer en la pantalla. Eso se consigue intercambiando los buffers con la siguiente instrucción que es la que hemos de añadir a continuación de lo anterior:

aglSwapBuffers

De esta manera, el resultado que tendremos una vez compilado el proyecto es el siguiente:

Bien, ya tenemos dibujado el triángulo. Ahora sólo tenemos que desplazarnos hacia la derecha una distancia conveniente y hacer lo propio con el cuadrado. Para ello, añadamos el siguiente código al final del método pero antes de la última línea que hemos puesto, es decir, antes de aglSwapBuffers:

glTranslatef 3.0,0.0,0.0
glBegin GL_QUADS
glVertex3f -1.0,1.0,0.0
glVertex3f 1.0,1.0,0.0
glVertex3f 1.0,-1.0,0.0
glVertex3f -1.0,-1.0,0.0
glEnd

Con la primera línea conseguimos movernos hacia la derecha (eje positivo de las X, primera coordenada) 3 unidades. Una vez allí comenzamos el bloque que define un cuadrado, haciéndolo a partir de sus vértices en las cuatro líneas siguientes. Se trata, respectivamente, del vértice superior izquierdo, el superior derecho, el inferior derecho y el inferior izquierdo. Para terminar, cerramos el bloque que define el cuadrado con glEnd.

Podemos hacer ya la prueba final; ejecutamos el proyecto y obtenemos la escena deseada:

¿Le damos color a la escena? Para hacerlo debemos usar simplemente la instrucción OpenGL glColor3f. Como podemos adivinar de su nombre, para especificar el color precisa de tres parámetros, al estilo del color RGB que ya nos resultará familiar si hemos manejado REALbasic; el primero indica la cantidad de rojo, el segundo la de verde y el tercero la de azul. En este caso, los valores que demos deben estar comprendidos entre 0.0 (ausencia) y 1.0 (color puro). Así, (1.0,0.0,0.0) es un rojo brillante puro y (0.5, 0.5, 1.0) es una mezcla de color más bien azulada. Debemos tener en cuenta que en cuanto usemos esta instrucción, todo lo que dibujemos se hará en el color indicado.

Cambiemos a este último color el cuadrado blanco. Para ello bastará que escribamos lo siguiente justo antes de la definición del cuadrado, es decir, antes del glBegin GL_QUADS:

glColor3f 0.5,0.5,1.0

Pero no sólo podemos conseguir colores solidos, también gradientes. Eso lo podemos llevar a la práctica con el triángulo; bastará con que le asignemos un color distinto a cada vértice para que OpenGL rendere la imagen con el gradiente de color resultante entre ellos (fijémonos que estamos con lo que se denomina, color suave). La nueva construcción del triángulo quedará así:

glBegin GL_TRIANGLES
glColor3f 1.0,0.0,0.0 'color rojo
glVertex3f 0.0,1.0,0.0
glColor3f 0.0,1.0,0.0 'color verde
glVertex3f -1.0,-1.0,0.0
glColor3f 0.0,0.0,1.0 'color azul
glVertex3f 1.0,-1.0,0.0
glEnd

El resultado de la coloración de la escena es la siguiente:

Puedes descargarte el código fuente del proyecto de este tutorial haciendo click aquí. Lo próximo que haremos será añadir movimiento a nuestro mundo, que por el momento es estático y algo aburrido.