OpenGL es una poderosa herramienta de programación 3D utilizada para dibujar complejas escenas tridimensionales a partir de primitivas simples. ¡Este artículo te enseñará cómo dibujar un cubo simple que puedes girar para verlo en tres dimensiones!

Para este proyecto, necesitará un editor de código y cierto conocimiento de la programación C.

Parte uno de cuatro:
Configuración inicial y main ()

1) Instalar OpenGL

  • Para comenzar, siga estos pasos para instalar OpenGL en su sistema. Si ya tiene instalado OpenGL y un compilador c, puede omitir este paso y pasar al siguiente.

2) Crea el documento

  • Cree un nuevo archivo en su editor de código favorito y guárdelo como mycube.c

3) # incluye

  • Estos son los elementos básicos que necesitaremos para nuestro programa. Es importante darse cuenta de que en realidad hay diferentes necesidades incluidas para los diferentes sistemas operativos. Asegúrese de incluir todo esto para asegurarse de que su programa sea versátil y se pueda ejecutar para cualquier usuario.
     // Incluye #incluir  #incluir  #incluir  #define GL_GLEXT_PROTOTYPES #ifdef __APPLE__ #incluir  #más #incluir  #terminara si 

4) Prototipos de funciones y variables globales

  • Nuestro siguiente paso es declarar algunos prototipos de funciones.
     // Prototipos de funciones vacío monitor(); vacío Llaves especiales(); // Variables globales doble rotate_y=0; doble rotate_x=0; 
  • Explicaré cada una de estas funciones y las variables globales en detalle a medida que las implementemos más adelante en este tutorial. Por ahora, es importante que los declares.

5) Configurar la función principal ()

  •  En t principal(En t argc, carbonizarse* argv[]) // Inicializa GLUT y procesa los parámetros del usuario glutInit(&argc,argv); // Solicitar ventana de color verdadero con doble buffer con Z-buffer glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); 
  • Esta declaración establece nuestro entorno. Una gran cosa para recordar al escribir programas OpenGL es que debe pedir todo. Esto requiere que comprenda mejor cómo funciona su programa y qué necesita incluir para obtener la funcionalidad que desea. En esta línea, configuraremos la pantalla con doble almacenamiento en búfer, color RGB y un Z-buffer.
  • Doble almacenamiento en búfer es una técnica utilizada en programas gráficos para eliminar un problema que surge debido a cómo se dibujan las imágenes en la pantalla. Cada vez que volvemos a dibujar la escena, la pantalla primero debe borrarse y luego se dibujará la nueva información. Sin doble buffer, observará un efecto parpadeante a medida que la pantalla se borra y se vuelve a dibujar repetidamente.
    Este problema se soluciona al agregar un segundo buffer para dibujar. Con este método, se dibuja una imagen en el primer buffer y se muestra ese buffer. El siguiente cuadro se dibujará en el segundo buffer y, una vez hecho esto, los dos buffers cambiarán de lugar. Veremos inmediatamente el segundo búfer, pero, oculto para nosotros, el primer búfer se borrará y se volverá a dibujar con el tercer fotograma que se intercambiará cuando finalice.
  • También queremos habilitar el Color RGB sistema en nuestra ventana. Explicaré más sobre cómo se usa el color en OpenGL cuando trabajamos en la función de visualización.
  • Z-buffering es cómo obtenemos los efectos 3D que queremos. OpenGL utiliza un sistema de coordenadas tridimensional con ejes x, y y z. Para dar el efecto de que un objeto está más cerca de usted, su posición en el eje z aumenta, sin embargo, para que aparezca más lejos, su posición en el eje z disminuye. Hablaré un poco más sobre esto cuando dibujemos nuestros vértices para el cubo.

6) Creando la ventana

  • El siguiente paso es crea la ventana dentro de la cual dibujaremos el cubo. En este tutorial, llamo a nuestra ventana "Awesome Cube".
     // Crear ventana glutCreateWindow("Cubo impresionante"); 

7) Habilitar prueba de profundidad

  • OpenGL es un lenguaje estricto ya que no supone que se hayan habilitado características especiales. Para que nuestro programa se muestre correctamente en 3 dimensiones con el Z-buffer que vimos anteriormente, necesitamos habilitar la prueba de profundidad. A medida que continúe explorando OpenGL, descubrirá muchas características que deberá habilitar, incluidas la iluminación, las texturas, la detección selectiva y mucho más.
     // Habilita la prueba de profundidad Z-buffer glEnable(GL_DEPTH_TEST); 

8) Funciones de devolución de llamada

  • Aquí están las funciones de devolución de llamada para las que escribimos los prototipos anteriormente. Cada vez que se pasa por el ciclo principal, se invocarán estas funciones. La función de visualización vuelve a dibujar la escena en función de cualquier cambio en las variables que se hicieron desde la llamada anterior. La función specialKeys nos permite interactuar con el programa.
     // Funciones de devolución de llamada glutDisplayFunc(monitor); glutSpecialFunc(Llaves especiales); 

9) Funciones de devolución de llamada

  • El último paso en nuestra configuración inicial es iniciar el MainLoop. Esto recordará la función principal hasta que cerremos el programa para permitir las animaciones y la interacción del usuario.
     // Pasa el control a GLUT para eventos glutMainLoop(); // Regrese al sistema operativo regreso 0;  

Parte dos de cuatro:
La función de visualización ()

  • Todo el trabajo de dibujar nuestro cubo se hará en esta función. La idea general detrás de nuestro cubo es dibujar los seis lados individualmente y colocarlos en la posición adecuada.
  • Conceptualmente, cada lado se dibujará definiendo las cuatro esquinas y permitiendo que OpenGL conecte las líneas y lo complete con el color que definamos. Debajo están los pasos para hacer esto.

1) glClear ()

  • El primer paso que debemos dar en esta función es borrar el color y el buffer Z. Sin estos pasos, los dibujos antiguos aún pueden ser visibles bajo los nuevos dibujos y los objetos dibujados no estarían en la ubicación correcta en la pantalla.
     vacío monitor() // Borrar pantalla y Z-buffer glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 

2) glBegin () y glEnd ()

  • OpenGL define objetos como combinaciones de diferentes polígonos. Utilizando el glBegin () comando, efectivamente dejamos un lápiz que dibujará una forma.Para levantar el lápiz y comenzar una nueva forma, debemos usar glEND () mando. En este tutorial vamos a utilizar GL_POLYGON a dibujar cada lado del cubo, pero es posible utilizar otras opciones de parámetros tales como GL_LINE, GL_QUAD o GL_TRIANGLE para crear otras formas.
  • Aquí comenzaremos con el frente de nuestro cubo. Más tarde agregaremos color a los 6 lados.
     // lado multicolor - DELANTERO glBegin(GL_POLYGON); // Los vértices se agregarán en el próximo paso glEND(); 

3) glVertex3f ()

  • Una vez que hemos declarado que queremos comenzar nuestro polígono, necesitamos definir los vértices del objeto. glVertex tiene múltiples formas dependiendo de lo que quieras hacer con tu objeto.
  • La primera es la cantidad de dimensiones en las que está trabajando. La 3 anterior en glVertex3f dice que estamos dibujando en 3 dimensiones. También es posible trabajar en 2 o 4 dimensiones. La f de arriba en glVertex3f dice que estamos trabajando con números de coma flotante. También puedes usar cortos, enteros o dobles.
  • Tenga en cuenta que estos puntos se definen en una sinistrórsum manera. Esto no es muy importante en este momento, pero cuando comencemos a trabajar con iluminación, texturas y exposición selectiva, será increíblemente importante, así que adquiere el hábito de definir tus puntos en el sentido contrario a las agujas del reloj ahora.
  • Ahora agregamos los vértices entre las líneas glBegin () y glEnd ().
     // lado multicolor - DELANTERO glBegin(GL_POLYGON); glVertex3f( -0.5, -0.5, -0.5); // P1 glVertex3f( -0.5, 0.5, -0.5); // P2 glVertex3f( 0.5, 0.5, -0.5); // P3 glVertex3f( 0.5, -0.5, -0.5); // P4 glEND(); 

4) glColor3f ()

  • glColor funciona de manera similar a glVertex. Podemos definir puntos como cortos, enteros, dobles o flotantes. Cada color tiene un valor de 0 a 1. Todos los 0 hacen que el punto sea negro y todos los 1 hacen que el punto sea blanco. El 3 en glColor3f () se refiere al sistema de color RGB sin canal alfa. El alfa de un color define su transparencia. Para cambiar el nivel alfa, use glColor4f () con el último parámetro siendo un valor de 0 a 1 para opaco a transparente.
  • Cuando llamemos a glColor3f (), cada vértice dibujado desde ese punto será de ese color. Por lo tanto, si queremos que los cuatro vértices sean rojos, simplemente configure el color una vez en cualquier momento antes de que los comandos glVertex3f () y todos los vértices sean rojos.
  • El anverso que se define a continuación muestra cómo definir un nuevo color para cada vértice. Cuando hacemos esto, podemos ver una propiedad interesante de los colores OpenGL. Como cada vértice del polígono tiene su propio color, OpenGL combinará automáticamente los colores. El siguiente paso mostrará cómo asignar cuatro vértices con el mismo color.
     // lado multicolor - DELANTERO glBegin(GL_POLYGON); glColor3f( 1.0, 0.0, 0.0 ); glVertex3f( 0.5, -0.5, -0.5 ); // P1 es rojo glColor3f( 0.0, 1.0, 0.0 ); glVertex3f( 0.5, 0.5, -0.5 ); // P2 es verde glColor3f( 0.0, 0.0, 1.0 ); glVertex3f( -0.5, 0.5, -0.5 ); // P3 es azul glColor3f( 1.0, 0.0, 1.0 ); glVertex3f( -0.5, -0.5, -0.5 ); // P4 es morado glEND(); 

5) Los otros lados

  • Los animo a que averigüen cuál será la ubicación de cada vértice para los otros cinco lados del cubo, pero, para simplificar, los calculé y los incluí en nuestro función de visualización final () abajo.
     // Lado blanco - ATRÁS glBegin(GL_POLYGON); glColor3f( 1.0, 1.0, 1.0 ); glVertex3f( 0.5, -0.5, 0.5 ); glVertex3f( 0.5, 0.5, 0.5 ); glVertex3f( -0.5, 0.5, 0.5 ); glVertex3f( -0.5, -0.5, 0.5 ); glEND(); // Lado morado - DERECHO glBegin(GL_POLYGON); glColor3f( 1.0, 0.0, 1.0 ); glVertex3f( 0.5, -0.5, -0.5 ); glVertex3f( 0.5, 0.5, -0.5 ); glVertex3f( 0.5, 0.5, 0.5 ); glVertex3f( 0.5, -0.5, 0.5 ); glEND(); // Lado verde - IZQUIERDA glBegin(GL_POLYGON); glColor3f( 0.0, 1.0, 0.0 ); glVertex3f( -0.5, -0.5, 0.5 ); glVertex3f( -0.5, 0.5, 0.5 ); glVertex3f( -0.5, 0.5, -0.5 ); glVertex3f( -0.5, -0.5, -0.5 ); glEND(); // lado azul - TOP glBegin(GL_POLYGON); glColor3f( 0.0, 0.0, 1.0 ); glVertex3f( 0.5, 0.5, 0.5 ); glVertex3f( 0.5, 0.5, -0.5 ); glVertex3f( -0.5, 0.5, -0.5 ); glVertex3f( -0.5, 0.5, 0.5 ); glEND(); // Lado rojo - ABAJO glBegin(GL_POLYGON); glColor3f( 1.0, 0.0, 0.0 ); glVertex3f( 0.5, -0.5, -0.5 ); glVertex3f( 0.5, -0.5, 0.5 ); glVertex3f( -0.5, -0.5, 0.5 ); glVertex3f( -0.5, -0.5, -0.5 ); glEND(); GlFlush(); glutSwapBuffers();  


  • También queremos agregar dos últimas líneas de código para esta función. Estos son glFlush (); y glutSwapBuffers (); que nos dan el doble efecto de amortiguación que aprendimos antes.

Parte tres de cuatro:
Interactividad del usuario

1) specialKeys ()

  • Casi hemos terminado, pero por el momento, podemos dibujar un cubo pero no tenemos forma de girarlo. Para hacer esto, lo haremos crear unaTecla especial () función para permitirnos presionar las teclas de flecha y girar el cubo!
  • Esta función es la razón por la que declaramos las variables globales rotate_x y rotate_y. Cuando presionamos las teclas de flecha derecha e izquierda, rotate_y se incrementará o disminuirá en 5 grados. Del mismo modo, cuando presionamos las teclas de flecha arriba y abajo, rotate_x cambiará en consecuencia.
     vacío Llaves especiales( En t llave, En t X, En t y )  // Flecha derecha - aumentar la rotación en 5 grados Si (llave == GLUT_KEY_RIGHT) rotate_y += 5; // Flecha izquierda: disminuya la rotación en 5 grados más Si (llave == GLUT_KEY_LEFT) rotate_y -= 5; más Si (llave == GLUT_KEY_UP) rotate_x += 5; más Si (llave == GLUT_KEY_DOWN) rotate_x -= 5; // Solicitud de actualización de pantalla glutPostRedisplay();  

2) glRotate ()

  • Nuestra última declaración es agregar la declaración que rotará nuestro objeto. Regresa a la monitor() función y antes del lado FRONTAL, agregue estas líneas:
     // Restablecer transformaciones glLoadIdentity(); // Girar cuando el usuario cambie rotate_x y rotate_y glRotatef( rotate_x, 1.0, 0.0, 0.0 ); glRotatef( rotate_y, 0.0, 1.0, 0.0 ); // lado multicolor - DELANTERO


  • Primero note que la sintaxis de glRotatef () es similar a la de glColor3f () y glVertex3f () pero siempre requiere 4 parámetros. El primer parámetro es el grado de rotación que se aplicará. Los siguientes tres parámetros definen sobre qué eje girar: el primero es el eje x, el segundo es el eje y, y el tercero es el eje z. En este momento, solo necesitamos rotar sobre los ejes xey.
  • Todas las transformaciones que escribimos en nuestro programa necesitan líneas similares a esta. Conceptualmente, pensamos en esto como rotando nuestro objeto sobre el eje x por la cantidad definida por rotate_x y luego girando alrededor del eje y por rotate_y. Sin embargo, OpenGL combina todas estas declaraciones en una transformación de matriz. Cada vez que llamamos a la función de visualización, construimos una matriz de transformación y glLoadIdentity () asegura que comenzaremos con una nueva matriz en cada pase.
  • Las otras funciones de transformación que podríamos aplicar son glTranslatef () y glScalef (). Estas funciones son similares a glRotatef () con la excepción de que solo toman 3 parámetros, las cantidades x, y, y z para traducir o escalar el objeto.
  • Para obtener el efecto correcto al aplicar las tres transformaciones a un objeto, debemos aplicarlas en el orden correcto. Siempre escríbelos en el orden glTranslate, glRotate, luego glScale. OpenGL esencialmente aplica las transformaciones de abajo hacia arriba. Para comprender esto, intente imaginarse qué aspecto tendría un cubo simple de 1x1x1 con las transformaciones si OpenGL los aplicara de arriba a abajo y si OpenGL los aplicara de abajo hacia arriba.
  • Agregue los siguientes comandos para escalar el cubo por 2 a lo largo del eje x, 2 a lo largo del eje y, gire el cubo 180 grados alrededor del eje y, y traduzca el cubo por 0.1 a lo largo del eje x. Asegúrese de organizar estos y los comandos glRotate () anteriores en el orden correcto como se describe arriba. (Si no está seguro, lo he hecho en el código final al final del tutorial).
     // Otras transformaciones glTranslatef( 0.1, 0.0, 0.0 ); glRotatef( 180, 0.0, 1.0, 0.0 ); glScalef( 2.0, 2.0, 0.0 ); 

Compilando

  • El último paso para terminar su primer proyecto OpenGL es compila y ejecuta tu código. Suponiendo que está utilizando gcc como compilador, ejecute estos comandos desde su terminal para compilar y probar su programa.
     En Linux: gcc cube.c -o cubo -lglut -lGL ./ mycube en Mac: gcc -o foo foo.c -marco de referencia EXCESO -marco de referencia OpenGL./ mycube en Windows: gcc -Pared -ofoo foo.c -lglut32cu -lglu32 -lopengl32 ./ mycube 

Parte cuatro de cuatro:
Código final

  • Ahí tienes. ¡Tu primer programa OpenGL! Te proporcioné mi código fuente a continuación como punto de referencia.
     // // Archivo: mycube.c // Autor: Matt Daisley // Creado: 4/25/2012 // Proyecto: código fuente para hacer un cubo en OpenGL // Descripción: crea una ventana OpenGL y dibuja un cubo 3D // que el usuario puede rotar usando las teclas de flecha //  // Controles: Flecha izquierda - Girar a la izquierda // Right Arrow - Girar a la derecha // Flecha arriba - Girar hacia arriba // Flecha abajo - Girar hacia abajo  // ---------------------------------------------------------- // Incluye // ---------------------------------------------------------- #incluir  #incluir  #incluir  #define GL_GLEXT_PROTOTYPES #ifdef __APPLE__ #incluir  #más #incluir  #terminara si // ---------------------------------------------------------- // Prototipos de funciones // ---------------------------------------------------------- vacío monitor(); vacío Llaves especiales(); // ---------------------------------------------------------- // Variables globales // ---------------------------------------------------------- doble rotate_y=0; doble rotate_x=0; // ---------------------------------------------------------- // display () Función de devolución de llamada // ---------------------------------------------------------- vacío monitor() // Borrar pantalla y Z-buffer glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // Restablecer transformaciones glLoadIdentity(); // Otras transformaciones // glTranslatef (0.1, 0.0, 0.0); // No incluido // glRotatef (180, 0.0, 1.0, 0.0); // No incluido // Girar cuando el usuario cambie rotate_x y rotate_y glRotatef( rotate_x, 1.0, 0.0, 0.0 ); glRotatef( rotate_y, 0.0, 1.0, 0.0 ); // Otras transformaciones // glScalef (2.0, 2.0, 0.0); // No incluido // lado multicolor - DELANTERO glBegin(GL_POLYGON); glColor3f( 1.0, 0.0, 0.0 ); glVertex3f( 0.5, -0.5, -0.5 ); // P1 es rojo glColor3f( 0.0, 1.0, 0.0 ); glVertex3f( 0.5, 0.5, -0.5 ); // P2 es verde glColor3f( 0.0, 0.0, 1.0 ); glVertex3f( -0.5, 0.5, -0.5 ); // P3 es azul glColor3f( 1.0, 0.0, 1.0 ); glVertex3f( -0.5, -0.5, -0.5 ); // P4 es morado glEND(); // Lado blanco - ATRÁS glBegin(GL_POLYGON); glColor3f( 1.0, 1.0, 1.0 ); glVertex3f( 0.5, -0.5, 0.5 ); glVertex3f( 0.5, 0.5, 0.5 ); glVertex3f( -0.5, 0.5, 0.5 ); glVertex3f( -0.5, -0.5, 0.5 ); glEND(); // Lado morado - DERECHO glBegin(GL_POLYGON); glColor3f( 1.0, 0.0, 1.0 ); glVertex3f( 0.5, -0.5, -0.5 ); glVertex3f( 0.5, 0.5, -0.5 ); glVertex3f( 0.5, 0.5, 0.5 ); glVertex3f( 0.5, -0.5, 0.5 ); glEND(); // Lado verde - IZQUIERDA glBegin(GL_POLYGON); glColor3f( 0.0, 1.0, 0.0 ); glVertex3f( -0.5, -0.5, 0.5 ); glVertex3f( -0.5, 0.5, 0.5 ); glVertex3f( -0.5, 0.5, -0.5 ); glVertex3f( -0.5, -0.5, -0.5 ); glEND(); // lado azul - TOP glBegin(GL_POLYGON); glColor3f( 0.0, 0.0, 1.0 ); glVertex3f( 0.5, 0.5, 0.5 ); glVertex3f( 0.5, 0.5, -0.5 ); glVertex3f( -0.5, 0.5, -0.5 ); glVertex3f( -0.5, 0.5, 0.5 ); glEND(); // Lado rojo - ABAJO glBegin(GL_POLYGON); glColor3f( 1.0, 0.0, 0.0 ); glVertex3f( 0.5, -0.5, -0.5 ); glVertex3f( 0.5, -0.5, 0.5 ); glVertex3f( -0.5, -0.5, 0.5 ); glVertex3f( -0.5, -0.5, -0.5 ); glEND(); GlFlush(); glutSwapBuffers();  // ---------------------------------------------------------- // specialKeys () Función de devolución de llamada // ---------------------------------------------------------- vacío Llaves especiales( En t llave, En t X, En t y )  // Flecha derecha - aumentar la rotación en 5 grados Si (llave == GLUT_KEY_RIGHT) rotate_y += 5; // Flecha izquierda: disminuya la rotación en 5 grados más Si (llave == GLUT_KEY_LEFT) rotate_y -= 5; más Si (llave == GLUT_KEY_UP) rotate_x += 5; más Si (llave == GLUT_KEY_DOWN) rotate_x -= 5; // Solicitud de actualización de pantalla glutPostRedisplay();  // ---------------------------------------------------------- // función principal // ---------------------------------------------------------- En t principal(En t argc, carbonizarse* argv[]) // Inicializa GLUT y procesa los parámetros del usuario glutInit(&argc,argv); // Solicitar ventana de color verdadero con doble buffer con Z-buffer glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); // Crear ventana glutCreateWindow("Cubo impresionante"); // Habilita la prueba de profundidad Z-buffer glEnable(GL_DEPTH_TEST); // Funciones de devolución de llamada glutDisplayFunc(monitor); glutSpecialFunc(Llaves especiales); // Pasa el control a GLUT para eventos glutMainLoop(); // Regrese al sistema operativo regreso 0;