Está en la página 1de 52

Tutorial 1 - Create a window Get the source!

Background The OpenGL spec does not specify any API in order to create and manipulate windo ws. Modern windowing systems that support OpenGL include a sub-system that provi des the binding between an OpenGL context and the windowing system. In the X Win dow system that interface is called GLX. Microsoft provides WGL (pronounced: Wig gle) for Windows and MacOS has CGL. Working directly with these interfaces in or der to create a window in which to display graphics is usually grunt work which is why we use a high level library that abstracts away the fine details. The lib rary we use here is called the 'OpenGL utility library', or GLUT. It provides a simplified API for window management as well as event handling, IO control and a few other services. In addition, GLUT is cross platform which makes portability easier. Alternatives to GLUT include SDL and GLFW. Source walkthru glutInit(&argc, argv); This call initializes GLUT. The parameters can be provided directly from the com mand line and include useful options such as '-sync' and '-gldebug' which disabl e the asynchronous nature of X and automatically checks for GL errors and displa ys them (respectively). glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); Here we configure some GLUT options. GLUT_DOUBLE enables double buffering (drawi ng to a background buffer while another buffer is displayed) and the color buffe r where most rendering ends up (i.e. the screen). We will usually want these two as well as other options which we will see later. glutInitWindowSize(1024, 768); glutInitWindowPosition(100, 100); glutCreateWindow("Tutorial 01"); These calls specify the window parameters and create it. You also have the optio n to specify the window title. glutDisplayFunc(RenderSceneCB); Since we are working in a windowing system most of the interaction with the runn ing program occurs via event callback functions. GLUT takes care of interacting with the underlying windowing system and provides us with a few callback options . Here we use just one - a "main" callback to do all the rendering of one frame. This function is continuously called by GLUT internal loop. glClearColor(0.0f, 0.0f, 0.0f, 0.0f); This is our first encounter with the concept of state in OpenGL. The idea behind state is that rendering is such a complex task that it cannot be treated as a f unction call that receives a few parameters (and correctly designed functions ne ver receive a lot of parameters). You need to specify shaders, buffers and vario us flags that effect how rendering will take place. In addition, you would often want to keep the same piece of configuration across several rendering operation s (e.g. if you never disable the depth test then there is no point in specifying it for every render call). That is why most of the configuration of rendering o perations is done by setting flags and values in the OpenGL state machine and th e rendering calls themselves are usually limited to the few parameters that revo lve around the number of vertices to draw and their starting offset. After calli ng a state changing function that particular configuration remains intact until the next call to the same function with a different value. The call above sets t he color that will be used when clearing the framebuffer (described later). The color has four channels (RGBA) and it is specified as a normalized value between

0.0 and 1.0. glutMainLoop(); This call passes control to GLUT which now begins its own internal loop. In this loop it listens to events from the windowing system and passes them via the cal lbacks that we configured. In our case GLUT will only call the function we regis tered as a display callback (RenderSceneCB) to give us a chace to render the fra me. glClear(GL_COLOR_BUFFER_BIT); glutSwapBuffers(); The only thing we do in our render function is to clear the framebuffer (using t he color specified above - try changing it). The second call tells GLUT to swap the roles of the backbuffer and the frontbuffer. In the next round through the r ender callback we will render into the current frames front buffer and the curre nt backbuffer will be displayed.

acceder "Ningn juego dura tanto hasta que te lo terminas como el que te programas t mismo, ninguno te absorbe tanto y ninguno te produce tanta satisfaccin cuando lo has aca bado" Programacion de videojuegos Inicio Curso de programacin de juegos 3. Empezamos con OpenGL Jueves 08 de Agos to del 2013 Menu principal Inicio Que es UnSitioWeb? Noticias, opiniones y ms Curso de programacin de juegos La librera de UnSitioWeb - libUSW Pintar texto con GLetraUSW en OpenGL Temas interesantes en la programacin de juegos Libreras tiles para programar juegos Programas del creador de juegos Manuales varios sobre informtica Foro Descargas Enlaces Contctanos Colaborar (con PayPal) Para continuar con el trabajo de esta Web y poder pagar el hosting, viene bien l a ayuda que sea. Gracias a todos. Importe: PayPal secure payments. Ultimas descargas GLetraUSW.zip 19.Jan Clase que permite dibujar texto en OpenGL con mucha facilidad.Usa FreeType2.Para ver que hace y c... FTGL compilado para VC y DEV-C 10.May Librera Corona compilada para DEV-C++

15.Apr

Nueva librera GLetraUSW Como usar GLetraUSW Clase para pintar texto en OpenGL La muerte del PC? 23. Linux. Programa bsico XWindows y OpenGL 22. Bounding volumes y reestructuracin Frustum Culling. Otro manual. Grata sorpresa con LINUX 21. GLSL. Carga de shaders GLM (OpenGL Mathematics) 20. Billboarding. Shader Maker

3. Empezamos con OpenGL Imprimir Correo electrnico Videojuegos - Curso de Programacin de juegos Escrito por Vicengetorix oglLa libreria grafica que vamos a usar es OpenGL. Ahora comenzamos a acostumbra rnos a su uso y entender como funciona. Ya explique porque usaremos OpenGL. Ahora una breve explicacion para aclarar alg un tema que suele ser confuso cuando se empieza con esta libreria grafica. Lo normal es pensar que hace falta bajarse unas librerias para programar con Ope nGL y un "run time" para ejecutar los programas hechos con ella. Con DirectX si hace falta y ocupa lo suyo; pero con OpenGL no hay "run time" y solo hacen falta dos pequeas librerias que vienen con los compiladores (en realidad solo haria fa lta una). En realidad el nucleo de OpenGL instalado en tu ordenador, esta en el driver gra fico de tu tarjera de video y es el fabricante de la misma quien la implementa p ara su hardware. La libreria que viene con el compilador es solo un interface pa ra usar las rutinas del fabricante, y este interface incluye un metodo para ampl iar el OpenGL para futuras mejoras de la libreria grafica (para usar OpenGL 1.0 se usa la misma libreria que para usar OpenGL 2.0) es lo que se llaman extension es. Bastante mas adelante las veremos. En resumen: no hace falta bajarse OpenGL de ningun sitio, y para hacer nuestro p rograma solo necesitaremos incluir "gl/gh.h" y "gl/glu.h" y aadir a nuestro proye cto las librerias opengl32.lib y glu32.lib. Para que nuestro programa funcione c onvendra tener bien instalado el driver de la tarjeta grafica, aunque al usar ca racteristicas basicas de OpenGL va a funcionar siempre ya que windows lo puede e jecutar por software (si usamos caracteristicas avanzadas propias de nuestro har dware de video y no tenemos los driver, fallara). Aunque este curso es eminentemente practico, no esta de mas la explicacion de al gunos conceptos basicos en programacion grafica. El buffer. No solo en graficos, sino en programacion general, es un espacio de m emoria reservado para almacenar algo. OpenGL usa varios bufferes. Los primeros y mas importantes son los que se usan p ara dibujar y el que se usa para presentar en pantalla. Se usa la tecnica de doble buffer (pueden ser mas). Entender esto es la base par a empezar a saber como trabaja un juego. Esto hay que entenderlo !. En la tecnica de boble buffer, dibujamos en un buffer que no es visible para que no se aprecie como se va haciendo nuestro dibujo y mientras presentamos el dibu

jo anterior. Cuando hemos acabado de dibujar suicheamos (intercambiamos) un buff er por otro, y asi se presenta el dibujo instantaneamente. Despues seguimos dibu jando en siguiente fotograma (frame), pero esta vez lo estaremos haciendo en el otro buffer, el que ahora esta oculto (back buffer), mientras el jugador esta vi endo en pantalla el fotograma que hemos dibujado antes. Estos bufferes son de memoria de video (la de la tarjeta de video, no memoria RA M del PC). El sistema no mueve la informacion de un buffer a otro, si no que, ha ce que la tarjeta de video cambie el rango de memoria de video que se traspasa a l monitor, y el rango de memoria en la que esta el back buffer (el que se presen ta en pantalla se llama front buffer). Ejemplo: Tenemos dos bufferes, el 1 y el 2 (por ejemplo). Que siempre van a ser el mismo trozo de memoria cada uno: Ahora el 1 es el back y el 2 es el front. En el 1 pintamos mientras se ve el 2 e n el monitor. Intercambamos bufferes (SwapBuffers(DevContex)) Ahora el 2 es el back y el 1 es el front. En el 2 pintamos mientras se ve el 1 e n el monitor con el dibujo anterior. Intercambamos bufferes (SwapBuffers(DevContex)) Ahora el 1 es el back y el 2 es el front. En el 1 pintamos mientras se ve el 2 e n el monitor. ... Por si hace falta la aclaracion, la animacion en un juego -y en una pelicula- se hace presentando un dibujo tras otro con pequeas variaciones en el mismo. Siempr e deben ser mas de 24 dibujos segundo para que el ojo no perciba el cambio y el movimiento sea suave. Otro buffer importante es el de profundidad o z-buffer, muuuuuy importante si pr etendemos hacer algo en 3D. En el se guarda la profundidad de cada pixel al pint arlo (distancia de lo que se pinta a la camara). Cuando se pinta de nuevo el mis mo pixel de pantalla (con otro objeto) se compara la profundidad de el ultimo co n la que estaba guardada de antes, si es mayor la nueva (esta mas lejos), no se pinta el pixel, y si es menor (esta mas cerca), se pinta el pixel del color nuev o en el buffer de dibujo (back buffer) y se pone la nueva profundidad -menor- en el buffer de profundidad. Hay mas bufferes como el de estarcido (stencil) o el de acumulacion pero de mome nto no nos hacen falta. Tras la explicacion, el codigo que creo que tiene suficientes comentarios para s eguirlo facilmente. En esta segunda version he puesto en funciones aparte la creacion de la ventana y la inicializacion de OpenGL. #pragma comment( lib, "openGL32.lib" ) // Estas directivas del preprocesador #pragma comment( lib, "glu32.lib" ) // le dicen a el enlazador (linker o // linkador o ...) que incluya estas // librerias. Esto se puede hacer en // la configuracion del proyecto en el // Visual C++ pero esto me parece mas // claro. #include <windows.h> #include <GL/gl.h> #include <GL/glu.h> // Fichero de inclusion para programas Windows // // // // Los ficheros de inclusion de OpenGL. Estrictamente solo es necesario el primero. El segundo es de funciones utiles que se podrian hacer de otra manera. No nos vamos a complicar la

// vida y la usaremos. HINSTANCE IdAplicacion; // Para guardar el identificador del programa HWND IdVentana; // Para guardar el identificador de la ventana HDC DevContex; // Device Context para conectar la ventana con OpenGL. HGLRC OGLrc; // Render Context para la ventana OpenGL. int AnchoVentana = 600; int AltoVentana = 400; // Lo que dice el nombre de la variable // Lo que dice el nombre de la variable

//-------------------------------------------------------------// Funcion para inicializar OpenGL. void IniciaGL() { // Definimos una estructura de tipo PIXELFORMATDESCRIPTOR para definir // las caracteristicas graficas que queremos usar (dentro de las que nos // permite el OpenGL de nuestra tarjeta de video) static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // Tamao de este descriptor 1, // Nmero de versin PFD_DRAW_TO_WINDOW | // El formato debe soportar ventana PFD_SUPPORT_OPENGL | // El formato debe soportar OpenGL PFD_DOUBLEBUFFER | // Debe soportar Doble Buffer PFD_TYPE_RGBA, // Tambin debe soportar RGBA 32, // Bits por pixels seleccionados 0,0,0,0,0,0, // Bits de color ignorados 0, // Sin buffer alpha 0, // Shift bit ignorado 0, // Buffer de acumulacin ignorado 0,0,0,0, // Bits de acumulacin ignorados 32, // Z-Buffer de 32 bits 0, // Sin buffer de pincel (Stencil) 0, // Sin buffer auxiliar PFD_MAIN_PLANE, // Layer de dibujo principal 0, // Reservado 0,0,0, // Layers de mscara ignorados }; // Estas funciones son las que hacen que la ventana acepte el modo grafico // que queremos dado el descriptor de pixel anterior. (en el que uno de // los parametros es que funcione con OpenGL). DevContex=GetDC(IdVentana); // Obtengo el "device context" de la ventana. int PixF=ChoosePixelFormat(DevContex,&pfd); // Busco un indice de una conbinacion // que coincida con mis especificaciones SetPixelFormat(DevContex,PixF,&pfd); // Pongo la ventana en el formato que quiero. // Dos funciones de OpenGL por fin (aunque sean especificas de windows). OGLrc=wglCreateContext(DevContex); // Indico a OpenGL que la ventana esta disponible para el. wglMakeCurrent(DevContex,OGLrc); // Le digo a OpenGL que nuestra ventana es donde tiene // que dibujar a partir de ahora. // A partir de ahora podemos considerar OpenGL inicializado. // Aun nos queda decirle los parametros del modo en que dibujar, aunque

// eso se puede, y de hecho se hace continuamente, cambiar durante la // ejecucion del programa. // Ahora pondremos algunos parametros puramente de OpenGL de inicio. glClearDepth(1.0f); // Profundidad del buffer de profundidad. Hace que lo que esta // mas cerca se vea (dibuje) encima de lo que esta mas lejos. glDepthFunc(GL_LEQUAL); // Comparacion del buffer de profundidad. glEnable(GL_DEPTH_TEST); // Habilita test de profundidad. A partir de ahora, lo que // esta mas cerca se pinta encima. glClearColor(0,0,0,1.0f); // Color del fondo. Color con el que se borra la pantalla, o la // ventana donde pintamos. Cuando usemos la funcion glClear. glShadeModel(GL_SMOOTH); // Renderizado suave. Cuanta mejor calidad mas lento. Nosotros // tenemos un ordenador reciente(+ o -) y queremos que se vea bien. glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST); // Calidad buena de perspectiva. glViewport(0,0,AnchoVentana,AltoVentana); // Le dice a OpenGL el tamao del lienzo en el que va a pintar en // pixels. Coincidira, en principio, con el tamao de nuestra ventana // y empezando por 0,0 (la esquina de nuestra ventana). glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // Borramos la ventana con el color antes establecido // (en realidad solo el backbuffer (la pantalla oculta // donde en realidad estamos pintando) // y borramos tambien el buffer de profundidad SwapBuffers(DevContex); // Le digo a nuestro espacio de dibujo que cambie "muy rapido" // el buffer de dibujo por el de visualizacion y viceversa // (suichear en Espanglish) } // Fin IniciaGL //-----------------------------------------------------------------// Funcion para controlar lo que ocurre en la ventana segun los eventos // que vienen de Windows. Mas tarde se asocia a la ventana que crearemos. // De momento solo interceptamos la tecla ESC para poder salir del // programa cuando queramos y el evento de destruccion de ventana con el // que terminamos la aplicacion LRESULT FAR PASCAL ProcesaMensajes(HWND Ventana, UINT Mensaje, WPARAM wParam, LPARAM lParam) { switch(Mensaje) // Segn el mensaje recibido { case WM_KEYDOWN: // Caso de mensaje de pulsacin de una tecla switch(wParam) // y segun el contenido de la variable wParam { case VK_ESCAPE: // ESC causa la salida del programa // Funcion para enviar mensaje de cerrado a la ventana // y despues de la aplicacion PostMessage(Ventana, WM_CLOSE, 0, 0); break; } break; case WM_DESTROY:// Mensaje de destruccin de la ventana (provocado por

// nosotros al pulsar ESC o cerrar la ventana. PostQuitMessage(0); // Funcion para salir del programa break; } // Efectuar el proceso por defecto del mensaje (si viene cualquier mensaje // que no hemos usado, querremos que haga lo que suele hacer) return DefWindowProc(Ventana, Mensaje, wParam, lParam); } // fin ProcesaMansajes //-----------------------------------------------------------------// Funcion para crear la ventana de nuestro programa, que asociaremos // al OpenGL para pintar en ella void CreaVentana() { WNDCLASS ClaseVentana; // Declaramos un tipo de ventana, el nuestro. //Definimos nuestro tipo de ventana... ClaseVentana.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Se redibujara si // cambia el tamao de la ventana horizontal y verticalmente, y // un solo DC (device context) para cada ventana (para cuando // empezemos con OpenGL) ClaseVentana.lpfnWndProc = ProcesaMensajes; // La definimos antes para contolar // los mansajes como los del teclado ClaseVentana.cbClsExtra = 0; //Sin memoria extra para la clase ClaseVentana.cbWndExtra = 0; //Sin memoria extra para la ventana ClaseVentana.hInstance = IdAplicacion; // Identificador del programa para asociar // esta ventana con este programa. ClaseVentana.hIcon = NULL; // De momento pasamos de icono ClaseVentana.hCursor = LoadCursor(NULL, IDC_ARROW); // Flecha normal de raton ClaseVentana.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // Por ahora lo ponemos blanco ClaseVentana.lpszMenuName = NULL; // Pasamos de menu ClaseVentana.lpszClassName = L"UnSitioWeb"; // Nombre de la clase (la "L" antes de la cadena es // por que solo admite cadenas de caracteres // unicode -LPCWSTR o TCHAR- y con la "L" se convierte). RegisterClass(&ClaseVentana); // Registramos nuestro tipo de ventana IdVentana = CreateWindowEx( // Funcion que crea la ventana. Guardamos el identificativo. WS_EX_APPWINDOW, // estilo extendido de ventana L"UnSitioWeb", // Nombre de la clase puesto antes (la "L" para UNICODE) L"Un Sitio Web", // Titulo que aparecera en la ventana. WS_POPUPWINDOW|WS_CAPTION|WS_MINIMIZEBOX, // Parametros de como sera la ventana // se pueden combinar varios. 100, // Posicion Horizontal. 100, // Posicion Vertical. AnchoVentana, // Ancho de la ventana. AltoVentana, // Alto de la ventana. (HWND) NULL, // No depende de otra ventana. (HMENU) NULL,

// No le damos un menu diferente al de la clase(que es ninguno) IdAplicacion, // Identificador del programa al que pertenece la ventana. Al // empezar lo guardamos en una variable para usarlo despues. (LPVOID) NULL ); // Puntero a "no se que" datos (pasamos del tema, es para // aplicaciones MIDI). ShowWindow(IdVentana, SW_SHOW); // Mostramos nuestra ventana. UpdateWindow(IdVentana); // La actualizo para que muestre lo que tenga que mostrar // (ahora nada) } // Fin CreaVentana //-----------------------------------------------------------------// Funcion principal de un programa Windows (como main en C normal, // aqui WinMain) el prorama empieza a ejecutarse a partir de esta funcion. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(lpszCmdLine); // Para que no moleste al compilar, no lo usamos. IdAplicacion = hInstance; // Guardo el identificador del programa, luego lo usamos. CreaVentana(); // Funcion que crea la ventana. Definida mas arriba. IniciaGL(); // Funcion para inicializar OpenGL. Definida mas arriba. // // // // // Este es el bucle habitual de windows que se esta ejecutando continuamente hasta que recibe el mensaje de acabar (ya lo hemos preparado en la funcion "ProcesaMensajes" asociada a la ventana, tambien asociada a este programa atraves de su identificativo) MSG Mensaje; // Varible para contener los mensajes que van llegando. while(TRUE) // Se ejecuta continuamente. { if(PeekMessage(&Mensaje, NULL, 0, 0, PM_NOREMOVE)) // Exploramos la cola de mensajes. {// procesndolos adecuadamente if(!GetMessage(&Mensaje, NULL, 0, 0)) return (int)Mensaje.wParam; // Terminamos. TranslateMessage(&Mensaje); DispatchMessage(&Mensaje); } else WaitMessage(); // en caso contrario esperamos un mensaje }

} // fin WinMain //-----------------------------------------------------------------Una ultima explicacion para los que investiguen por internet a cerca de programa cion OpenGL. Existe una libreria muy usada, y la mas habitual en los ejemplos de codigo, llamada glut que simplifica el tema del teclado, inicializacion y demas aspectos del programa base.

Yo no la uso, tel vez por mania o por cabezoneria, pero prefiero gestionar yo mi smo estos temas ya que no me parece tan complicado, como habeis visto, y te da m ayor control sobre tu programa. En todo caso es una decision personal y el funci onamiento de OpenGL es el mismo en los dos casos. Suerte compilando.

+/ESCRIBIR COMENTARIO +/- COMENTARIOS A ?ADIR NUEVO BUSCAR

Banner Spanish Chinese (Simplified) English French German Japanese Portuguese Russian

Creative Commons License Esta Web est bajo licencia de Creative Commons Loading... acceder "Ningn juego dura tanto hasta que te lo terminas como el que te programas t mismo, ninguno te absorbe tanto y ninguno te produce tanta satisfaccin cuando lo has aca bado" Programacion de videojuegos Inicio Curso de programacin de juegos 3. Empezamos con OpenGL Jueves 08 de Agos to del 2013 Menu principal Inicio Que es UnSitioWeb? Noticias, opiniones y ms Curso de programacin de juegos La librera de UnSitioWeb - libUSW Pintar texto con GLetraUSW en OpenGL Temas interesantes en la programacin de juegos Libreras tiles para programar juegos Programas del creador de juegos Manuales varios sobre informtica Foro Descargas Enlaces Contctanos Colaborar (con PayPal) Para continuar con el trabajo de esta Web y poder pagar el hosting, viene bien l a ayuda que sea. Gracias a todos. Importe: PayPal secure payments. Ultimas descargas

GLetraUSW.zip 19.Jan Clase que permite dibujar texto en OpenGL con mucha facilidad.Usa FreeType2.Para ver que hace y c... FTGL compilado para VC y DEV-C 10.May Librera Corona compilada para DEV-C++ 15.Apr

Nueva librera GLetraUSW Como usar GLetraUSW Clase para pintar texto en OpenGL La muerte del PC? 23. Linux. Programa bsico XWindows y OpenGL 22. Bounding volumes y reestructuracin Frustum Culling. Otro manual. Grata sorpresa con LINUX 21. GLSL. Carga de shaders GLM (OpenGL Mathematics) 20. Billboarding. Shader Maker

3. Empezamos con OpenGL Imprimir Correo electrnico Videojuegos - Curso de Programacin de juegos Escrito por Vicengetorix oglLa libreria grafica que vamos a usar es OpenGL. Ahora comenzamos a acostumbra rnos a su uso y entender como funciona. Ya explique porque usaremos OpenGL. Ahora una breve explicacion para aclarar alg un tema que suele ser confuso cuando se empieza con esta libreria grafica. Lo normal es pensar que hace falta bajarse unas librerias para programar con Ope nGL y un "run time" para ejecutar los programas hechos con ella. Con DirectX si hace falta y ocupa lo suyo; pero con OpenGL no hay "run time" y solo hacen falta dos pequeas librerias que vienen con los compiladores (en realidad solo haria fa lta una). En realidad el nucleo de OpenGL instalado en tu ordenador, esta en el driver gra fico de tu tarjera de video y es el fabricante de la misma quien la implementa p ara su hardware. La libreria que viene con el compilador es solo un interface pa ra usar las rutinas del fabricante, y este interface incluye un metodo para ampl iar el OpenGL para futuras mejoras de la libreria grafica (para usar OpenGL 1.0 se usa la misma libreria que para usar OpenGL 2.0) es lo que se llaman extension es. Bastante mas adelante las veremos. En resumen: no hace falta bajarse OpenGL de ningun sitio, y para hacer nuestro p rograma solo necesitaremos incluir "gl/gh.h" y "gl/glu.h" y aadir a nuestro proye cto las librerias opengl32.lib y glu32.lib. Para que nuestro programa funcione c onvendra tener bien instalado el driver de la tarjeta grafica, aunque al usar ca racteristicas basicas de OpenGL va a funcionar siempre ya que windows lo puede e jecutar por software (si usamos caracteristicas avanzadas propias de nuestro har dware de video y no tenemos los driver, fallara). Aunque este curso es eminentemente practico, no esta de mas la explicacion de al gunos conceptos basicos en programacion grafica. El buffer. No solo en graficos, sino en programacion general, es un espacio de m emoria reservado para almacenar algo.

OpenGL usa varios bufferes. Los primeros y mas importantes son los que se usan p ara dibujar y el que se usa para presentar en pantalla. Se usa la tecnica de doble buffer (pueden ser mas). Entender esto es la base par a empezar a saber como trabaja un juego. Esto hay que entenderlo !. En la tecnica de boble buffer, dibujamos en un buffer que no es visible para que no se aprecie como se va haciendo nuestro dibujo y mientras presentamos el dibu jo anterior. Cuando hemos acabado de dibujar suicheamos (intercambiamos) un buff er por otro, y asi se presenta el dibujo instantaneamente. Despues seguimos dibu jando en siguiente fotograma (frame), pero esta vez lo estaremos haciendo en el otro buffer, el que ahora esta oculto (back buffer), mientras el jugador esta vi endo en pantalla el fotograma que hemos dibujado antes. Estos bufferes son de memoria de video (la de la tarjeta de video, no memoria RA M del PC). El sistema no mueve la informacion de un buffer a otro, si no que, ha ce que la tarjeta de video cambie el rango de memoria de video que se traspasa a l monitor, y el rango de memoria en la que esta el back buffer (el que se presen ta en pantalla se llama front buffer). Ejemplo: Tenemos dos bufferes, el 1 y el 2 (por ejemplo). Que siempre van a ser el mismo trozo de memoria cada uno: Ahora el 1 es el back y el 2 es el front. En el 1 pintamos mientras se ve el 2 e n el monitor. Intercambamos bufferes (SwapBuffers(DevContex)) Ahora el 2 es el back y el 1 es el front. En el 2 pintamos mientras se ve el 1 e n el monitor con el dibujo anterior. Intercambamos bufferes (SwapBuffers(DevContex)) Ahora el 1 es el back y el 2 es el front. En el 1 pintamos mientras se ve el 2 e n el monitor. ... Por si hace falta la aclaracion, la animacion en un juego -y en una pelicula- se hace presentando un dibujo tras otro con pequeas variaciones en el mismo. Siempr e deben ser mas de 24 dibujos segundo para que el ojo no perciba el cambio y el movimiento sea suave. Otro buffer importante es el de profundidad o z-buffer, muuuuuy importante si pr etendemos hacer algo en 3D. En el se guarda la profundidad de cada pixel al pint arlo (distancia de lo que se pinta a la camara). Cuando se pinta de nuevo el mis mo pixel de pantalla (con otro objeto) se compara la profundidad de el ultimo co n la que estaba guardada de antes, si es mayor la nueva (esta mas lejos), no se pinta el pixel, y si es menor (esta mas cerca), se pinta el pixel del color nuev o en el buffer de dibujo (back buffer) y se pone la nueva profundidad -menor- en el buffer de profundidad. Hay mas bufferes como el de estarcido (stencil) o el de acumulacion pero de mome nto no nos hacen falta. Tras la explicacion, el codigo que creo que tiene suficientes comentarios para s eguirlo facilmente. En esta segunda version he puesto en funciones aparte la creacion de la ventana y la inicializacion de OpenGL. #pragma comment( lib, "openGL32.lib" ) // Estas directivas del preprocesador #pragma comment( lib, "glu32.lib" ) // le dicen a el enlazador (linker o // linkador o ...) que incluya estas // librerias. Esto se puede hacer en // la configuracion del proyecto en el // Visual C++ pero esto me parece mas

// claro. #include <windows.h> #include <GL/gl.h> #include <GL/glu.h> // Fichero de inclusion para programas Windows // // // // // Los ficheros de inclusion de OpenGL. Estrictamente solo es necesario el primero. El segundo es de funciones utiles que se podrian hacer de otra manera. No nos vamos a complicar la vida y la usaremos.

HINSTANCE IdAplicacion; // Para guardar el identificador del programa HWND IdVentana; // Para guardar el identificador de la ventana HDC DevContex; // Device Context para conectar la ventana con OpenGL. HGLRC OGLrc; // Render Context para la ventana OpenGL. int AnchoVentana = 600; int AltoVentana = 400; // Lo que dice el nombre de la variable // Lo que dice el nombre de la variable

//-------------------------------------------------------------// Funcion para inicializar OpenGL. void IniciaGL() { // Definimos una estructura de tipo PIXELFORMATDESCRIPTOR para definir // las caracteristicas graficas que queremos usar (dentro de las que nos // permite el OpenGL de nuestra tarjeta de video) static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // Tamao de este descriptor 1, // Nmero de versin PFD_DRAW_TO_WINDOW | // El formato debe soportar ventana PFD_SUPPORT_OPENGL | // El formato debe soportar OpenGL PFD_DOUBLEBUFFER | // Debe soportar Doble Buffer PFD_TYPE_RGBA, // Tambin debe soportar RGBA 32, // Bits por pixels seleccionados 0,0,0,0,0,0, // Bits de color ignorados 0, // Sin buffer alpha 0, // Shift bit ignorado 0, // Buffer de acumulacin ignorado 0,0,0,0, // Bits de acumulacin ignorados 32, // Z-Buffer de 32 bits 0, // Sin buffer de pincel (Stencil) 0, // Sin buffer auxiliar PFD_MAIN_PLANE, // Layer de dibujo principal 0, // Reservado 0,0,0, // Layers de mscara ignorados }; // Estas funciones son las que hacen que la ventana acepte el modo grafico // que queremos dado el descriptor de pixel anterior. (en el que uno de // los parametros es que funcione con OpenGL). DevContex=GetDC(IdVentana); // Obtengo el "device context" de la ventana. int PixF=ChoosePixelFormat(DevContex,&pfd); // Busco un indice de una conbinacion // que coincida con mis especificaciones SetPixelFormat(DevContex,PixF,&pfd); // Pongo la ventana en el formato que quiero.

// Dos funciones de OpenGL por fin (aunque sean especificas de windows). OGLrc=wglCreateContext(DevContex); // Indico a OpenGL que la ventana esta disponible para el. wglMakeCurrent(DevContex,OGLrc); // Le digo a OpenGL que nuestra ventana es donde tiene // que dibujar a partir de ahora. // A partir de ahora podemos considerar OpenGL inicializado. // Aun nos queda decirle los parametros del modo en que dibujar, aunque // eso se puede, y de hecho se hace continuamente, cambiar durante la // ejecucion del programa. // Ahora pondremos algunos parametros puramente de OpenGL de inicio. glClearDepth(1.0f); // Profundidad del buffer de profundidad. Hace que lo que esta // mas cerca se vea (dibuje) encima de lo que esta mas lejos. glDepthFunc(GL_LEQUAL); // Comparacion del buffer de profundidad. glEnable(GL_DEPTH_TEST); // Habilita test de profundidad. A partir de ahora, lo que // esta mas cerca se pinta encima. glClearColor(0,0,0,1.0f); // Color del fondo. Color con el que se borra la pantalla, o la // ventana donde pintamos. Cuando usemos la funcion glClear. glShadeModel(GL_SMOOTH); // Renderizado suave. Cuanta mejor calidad mas lento. Nosotros // tenemos un ordenador reciente(+ o -) y queremos que se vea bien. glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST); // Calidad buena de perspectiva. glViewport(0,0,AnchoVentana,AltoVentana); // Le dice a OpenGL el tamao del lienzo en el que va a pintar en // pixels. Coincidira, en principio, con el tamao de nuestra ventana // y empezando por 0,0 (la esquina de nuestra ventana). glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // Borramos la ventana con el color antes establecido // (en realidad solo el backbuffer (la pantalla oculta // donde en realidad estamos pintando) // y borramos tambien el buffer de profundidad SwapBuffers(DevContex); // Le digo a nuestro espacio de dibujo que cambie "muy rapido" // el buffer de dibujo por el de visualizacion y viceversa // (suichear en Espanglish) } // Fin IniciaGL //-----------------------------------------------------------------// Funcion para controlar lo que ocurre en la ventana segun los eventos // que vienen de Windows. Mas tarde se asocia a la ventana que crearemos. // De momento solo interceptamos la tecla ESC para poder salir del // programa cuando queramos y el evento de destruccion de ventana con el // que terminamos la aplicacion LRESULT FAR PASCAL ProcesaMensajes(HWND Ventana, UINT Mensaje, WPARAM wParam, LPARAM lParam) { switch(Mensaje) // Segn el mensaje recibido { case WM_KEYDOWN: // Caso de mensaje de pulsacin de una tecla switch(wParam) // y segun el contenido de la variable wParam {

case VK_ESCAPE: // ESC causa la salida del programa // Funcion para enviar mensaje de cerrado a la ventana // y despues de la aplicacion PostMessage(Ventana, WM_CLOSE, 0, 0); break; } break; case WM_DESTROY:// Mensaje de destruccin de la ventana (provocado por // nosotros al pulsar ESC o cerrar la ventana. PostQuitMessage(0); // Funcion para salir del programa break; } // Efectuar el proceso por defecto del mensaje (si viene cualquier mensaje // que no hemos usado, querremos que haga lo que suele hacer) return DefWindowProc(Ventana, Mensaje, wParam, lParam); } // fin ProcesaMansajes //-----------------------------------------------------------------// Funcion para crear la ventana de nuestro programa, que asociaremos // al OpenGL para pintar en ella void CreaVentana() { WNDCLASS ClaseVentana; // Declaramos un tipo de ventana, el nuestro. //Definimos nuestro tipo de ventana... ClaseVentana.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Se redibujara si // cambia el tamao de la ventana horizontal y verticalmente, y // un solo DC (device context) para cada ventana (para cuando // empezemos con OpenGL) ClaseVentana.lpfnWndProc = ProcesaMensajes; // La definimos antes para contolar // los mansajes como los del teclado ClaseVentana.cbClsExtra = 0; //Sin memoria extra para la clase ClaseVentana.cbWndExtra = 0; //Sin memoria extra para la ventana ClaseVentana.hInstance = IdAplicacion; // Identificador del programa para asociar // esta ventana con este programa. ClaseVentana.hIcon = NULL; // De momento pasamos de icono ClaseVentana.hCursor = LoadCursor(NULL, IDC_ARROW); // Flecha normal de raton ClaseVentana.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // Por ahora lo ponemos blanco ClaseVentana.lpszMenuName = NULL; // Pasamos de menu ClaseVentana.lpszClassName = L"UnSitioWeb"; // Nombre de la clase (la "L" antes de la cadena es // por que solo admite cadenas de caracteres // unicode -LPCWSTR o TCHAR- y con la "L" se convierte). RegisterClass(&ClaseVentana); // Registramos nuestro tipo de ventana IdVentana = CreateWindowEx( // Funcion que crea la ventana. Guardamos el identificativo. WS_EX_APPWINDOW, // estilo extendido de ventana L"UnSitioWeb", // Nombre de la clase puesto antes (la "L" para UNICODE) L"Un Sitio Web", // Titulo que aparecera en la ventana. WS_POPUPWINDOW|WS_CAPTION|WS_MINIMIZEBOX,

// Parametros de como sera la ventana // se pueden combinar varios. 100, // Posicion Horizontal. 100, // Posicion Vertical. AnchoVentana, // Ancho de la ventana. AltoVentana, // Alto de la ventana. (HWND) NULL, // No depende de otra ventana. (HMENU) NULL, // No le damos un menu diferente al de la clase(que es ninguno) IdAplicacion, // Identificador del programa al que pertenece la ventana. Al // empezar lo guardamos en una variable para usarlo despues. (LPVOID) NULL ); // Puntero a "no se que" datos (pasamos del tema, es para // aplicaciones MIDI). ShowWindow(IdVentana, SW_SHOW); // Mostramos nuestra ventana. UpdateWindow(IdVentana); // La actualizo para que muestre lo que tenga que mostrar // (ahora nada) } // Fin CreaVentana //-----------------------------------------------------------------// Funcion principal de un programa Windows (como main en C normal, // aqui WinMain) el prorama empieza a ejecutarse a partir de esta funcion. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(lpszCmdLine); // Para que no moleste al compilar, no lo usamos. IdAplicacion = hInstance; // Guardo el identificador del programa, luego lo usamos. CreaVentana(); // Funcion que crea la ventana. Definida mas arriba. IniciaGL(); // Funcion para inicializar OpenGL. Definida mas arriba. // // // // // Este es el bucle habitual de windows que se esta ejecutando continuamente hasta que recibe el mensaje de acabar (ya lo hemos preparado en la funcion "ProcesaMensajes" asociada a la ventana, tambien asociada a este programa atraves de su identificativo) MSG Mensaje; // Varible para contener los mensajes que van llegando. while(TRUE) // Se ejecuta continuamente. { if(PeekMessage(&Mensaje, NULL, 0, 0, PM_NOREMOVE)) // Exploramos la cola de mensajes. {// procesndolos adecuadamente if(!GetMessage(&Mensaje, NULL, 0, 0)) return (int)Mensaje.wParam; // Terminamos. TranslateMessage(&Mensaje); DispatchMessage(&Mensaje); } else WaitMessage(); // en caso contrario esperamos un mensaje }

} // fin WinMain //-----------------------------------------------------------------Una ultima explicacion para los que investiguen por internet a cerca de programa cion OpenGL. Existe una libreria muy usada, y la mas habitual en los ejemplos de codigo, llamada glut que simplifica el tema del teclado, inicializacion y demas aspectos del programa base. Yo no la uso, tel vez por mania o por cabezoneria, pero prefiero gestionar yo mi smo estos temas ya que no me parece tan complicado, como habeis visto, y te da m ayor control sobre tu programa. En todo caso es una decision personal y el funci onamiento de OpenGL es el mismo en los dos casos. Suerte compilando.

+/ESCRIBIR COMENTARIO +/- COMENTARIOS A ?ADIR NUEVO BUSCAR

Banner Spanish Chinese (Simplified) English French German Japanese Portuguese Russian

Creative Commons License Esta Web est bajo licencia de Creative Commons Loading... acceder "Ningn juego dura tanto hasta que te lo terminas como el que te programas t mismo, ninguno te absorbe tanto y ninguno te produce tanta satisfaccin cuando lo has aca bado" Programacion de videojuegos Inicio Curso de programacin de juegos 3. Empezamos con OpenGL Jueves 08 de Agos to del 2013 Menu principal Inicio Que es UnSitioWeb? Noticias, opiniones y ms Curso de programacin de juegos La librera de UnSitioWeb - libUSW Pintar texto con GLetraUSW en OpenGL Temas interesantes en la programacin de juegos Libreras tiles para programar juegos Programas del creador de juegos Manuales varios sobre informtica Foro Descargas Enlaces Contctanos

Colaborar (con PayPal) Para continuar con el trabajo de esta Web y poder pagar el hosting, viene bien l a ayuda que sea. Gracias a todos. Importe: PayPal secure payments. Ultimas descargas GLetraUSW.zip 19.Jan Clase que permite dibujar texto en OpenGL con mucha facilidad.Usa FreeType2.Para ver que hace y c... FTGL compilado para VC y DEV-C 10.May Librera Corona compilada para DEV-C++ 15.Apr

Nueva librera GLetraUSW Como usar GLetraUSW Clase para pintar texto en OpenGL La muerte del PC? 23. Linux. Programa bsico XWindows y OpenGL 22. Bounding volumes y reestructuracin Frustum Culling. Otro manual. Grata sorpresa con LINUX 21. GLSL. Carga de shaders GLM (OpenGL Mathematics) 20. Billboarding. Shader Maker

3. Empezamos con OpenGL Imprimir Correo electrnico Videojuegos - Curso de Programacin de juegos Escrito por Vicengetorix oglLa libreria grafica que vamos a usar es OpenGL. Ahora comenzamos a acostumbra rnos a su uso y entender como funciona. Ya explique porque usaremos OpenGL. Ahora una breve explicacion para aclarar alg un tema que suele ser confuso cuando se empieza con esta libreria grafica. Lo normal es pensar que hace falta bajarse unas librerias para programar con Ope nGL y un "run time" para ejecutar los programas hechos con ella. Con DirectX si hace falta y ocupa lo suyo; pero con OpenGL no hay "run time" y solo hacen falta dos pequeas librerias que vienen con los compiladores (en realidad solo haria fa lta una). En realidad el nucleo de OpenGL instalado en tu ordenador, esta en el driver gra fico de tu tarjera de video y es el fabricante de la misma quien la implementa p ara su hardware. La libreria que viene con el compilador es solo un interface pa ra usar las rutinas del fabricante, y este interface incluye un metodo para ampl iar el OpenGL para futuras mejoras de la libreria grafica (para usar OpenGL 1.0 se usa la misma libreria que para usar OpenGL 2.0) es lo que se llaman extension es. Bastante mas adelante las veremos. En resumen: no hace falta bajarse OpenGL de ningun sitio, y para hacer nuestro p rograma solo necesitaremos incluir "gl/gh.h" y "gl/glu.h" y aadir a nuestro proye cto las librerias opengl32.lib y glu32.lib. Para que nuestro programa funcione c onvendra tener bien instalado el driver de la tarjeta grafica, aunque al usar ca racteristicas basicas de OpenGL va a funcionar siempre ya que windows lo puede e

jecutar por software (si usamos caracteristicas avanzadas propias de nuestro har dware de video y no tenemos los driver, fallara). Aunque este curso es eminentemente practico, no esta de mas la explicacion de al gunos conceptos basicos en programacion grafica. El buffer. No solo en graficos, sino en programacion general, es un espacio de m emoria reservado para almacenar algo. OpenGL usa varios bufferes. Los primeros y mas importantes son los que se usan p ara dibujar y el que se usa para presentar en pantalla. Se usa la tecnica de doble buffer (pueden ser mas). Entender esto es la base par a empezar a saber como trabaja un juego. Esto hay que entenderlo !. En la tecnica de boble buffer, dibujamos en un buffer que no es visible para que no se aprecie como se va haciendo nuestro dibujo y mientras presentamos el dibu jo anterior. Cuando hemos acabado de dibujar suicheamos (intercambiamos) un buff er por otro, y asi se presenta el dibujo instantaneamente. Despues seguimos dibu jando en siguiente fotograma (frame), pero esta vez lo estaremos haciendo en el otro buffer, el que ahora esta oculto (back buffer), mientras el jugador esta vi endo en pantalla el fotograma que hemos dibujado antes. Estos bufferes son de memoria de video (la de la tarjeta de video, no memoria RA M del PC). El sistema no mueve la informacion de un buffer a otro, si no que, ha ce que la tarjeta de video cambie el rango de memoria de video que se traspasa a l monitor, y el rango de memoria en la que esta el back buffer (el que se presen ta en pantalla se llama front buffer). Ejemplo: Tenemos dos bufferes, el 1 y el 2 (por ejemplo). Que siempre van a ser el mismo trozo de memoria cada uno: Ahora el 1 es el back y el 2 es el front. En el 1 pintamos mientras se ve el 2 e n el monitor. Intercambamos bufferes (SwapBuffers(DevContex)) Ahora el 2 es el back y el 1 es el front. En el 2 pintamos mientras se ve el 1 e n el monitor con el dibujo anterior. Intercambamos bufferes (SwapBuffers(DevContex)) Ahora el 1 es el back y el 2 es el front. En el 1 pintamos mientras se ve el 2 e n el monitor. ... Por si hace falta la aclaracion, la animacion en un juego -y en una pelicula- se hace presentando un dibujo tras otro con pequeas variaciones en el mismo. Siempr e deben ser mas de 24 dibujos segundo para que el ojo no perciba el cambio y el movimiento sea suave. Otro buffer importante es el de profundidad o z-buffer, muuuuuy importante si pr etendemos hacer algo en 3D. En el se guarda la profundidad de cada pixel al pint arlo (distancia de lo que se pinta a la camara). Cuando se pinta de nuevo el mis mo pixel de pantalla (con otro objeto) se compara la profundidad de el ultimo co n la que estaba guardada de antes, si es mayor la nueva (esta mas lejos), no se pinta el pixel, y si es menor (esta mas cerca), se pinta el pixel del color nuev o en el buffer de dibujo (back buffer) y se pone la nueva profundidad -menor- en el buffer de profundidad. Hay mas bufferes como el de estarcido (stencil) o el de acumulacion pero de mome nto no nos hacen falta. Tras la explicacion, el codigo que creo que tiene suficientes comentarios para s eguirlo facilmente. En esta segunda version he puesto en funciones aparte la creacion de la ventana

y la inicializacion de OpenGL. #pragma comment( lib, "openGL32.lib" ) // Estas directivas del preprocesador #pragma comment( lib, "glu32.lib" ) // le dicen a el enlazador (linker o // linkador o ...) que incluya estas // librerias. Esto se puede hacer en // la configuracion del proyecto en el // Visual C++ pero esto me parece mas // claro. #include <windows.h> #include <GL/gl.h> #include <GL/glu.h> // Fichero de inclusion para programas Windows // // // // // Los ficheros de inclusion de OpenGL. Estrictamente solo es necesario el primero. El segundo es de funciones utiles que se podrian hacer de otra manera. No nos vamos a complicar la vida y la usaremos.

HINSTANCE IdAplicacion; // Para guardar el identificador del programa HWND IdVentana; // Para guardar el identificador de la ventana HDC DevContex; // Device Context para conectar la ventana con OpenGL. HGLRC OGLrc; // Render Context para la ventana OpenGL. int AnchoVentana = 600; int AltoVentana = 400; // Lo que dice el nombre de la variable // Lo que dice el nombre de la variable

//-------------------------------------------------------------// Funcion para inicializar OpenGL. void IniciaGL() { // Definimos una estructura de tipo PIXELFORMATDESCRIPTOR para definir // las caracteristicas graficas que queremos usar (dentro de las que nos // permite el OpenGL de nuestra tarjeta de video) static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // Tamao de este descriptor 1, // Nmero de versin PFD_DRAW_TO_WINDOW | // El formato debe soportar ventana PFD_SUPPORT_OPENGL | // El formato debe soportar OpenGL PFD_DOUBLEBUFFER | // Debe soportar Doble Buffer PFD_TYPE_RGBA, // Tambin debe soportar RGBA 32, // Bits por pixels seleccionados 0,0,0,0,0,0, // Bits de color ignorados 0, // Sin buffer alpha 0, // Shift bit ignorado 0, // Buffer de acumulacin ignorado 0,0,0,0, // Bits de acumulacin ignorados 32, // Z-Buffer de 32 bits 0, // Sin buffer de pincel (Stencil) 0, // Sin buffer auxiliar PFD_MAIN_PLANE, // Layer de dibujo principal 0, // Reservado 0,0,0, // Layers de mscara ignorados }; // Estas funciones son las que hacen que la ventana acepte el modo grafico // que queremos dado el descriptor de pixel anterior. (en el que uno de // los parametros es que funcione con OpenGL).

//

// // // // //

DevContex=GetDC(IdVentana); // Obtengo el "device context" de la ventana. int PixF=ChoosePixelFormat(DevContex,&pfd); // Busco un indice de una conbinacion // que coincida con mis especificaciones SetPixelFormat(DevContex,PixF,&pfd); // Pongo la ventana en el formato que quiero. Dos funciones de OpenGL por fin (aunque sean especificas de windows). OGLrc=wglCreateContext(DevContex); // Indico a OpenGL que la ventana esta disponible para el. wglMakeCurrent(DevContex,OGLrc); // Le digo a OpenGL que nuestra ventana es donde tiene // que dibujar a partir de ahora. A partir de ahora podemos considerar OpenGL inicializado. Aun nos queda decirle los parametros del modo en que dibujar, aunque eso se puede, y de hecho se hace continuamente, cambiar durante la ejecucion del programa. Ahora pondremos algunos parametros puramente de OpenGL de inicio. glClearDepth(1.0f); // Profundidad del buffer de profundidad. Hace que lo que esta // mas cerca se vea (dibuje) encima de lo que esta mas lejos. glDepthFunc(GL_LEQUAL); // Comparacion del buffer de profundidad. glEnable(GL_DEPTH_TEST); // Habilita test de profundidad. A partir de ahora, lo que // esta mas cerca se pinta encima. glClearColor(0,0,0,1.0f); // Color del fondo. Color con el que se borra la pantalla, o la // ventana donde pintamos. Cuando usemos la funcion glClear. glShadeModel(GL_SMOOTH); // Renderizado suave. Cuanta mejor calidad mas lento. Nosotros // tenemos un ordenador reciente(+ o -) y queremos que se vea bien. glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST); // Calidad buena de perspectiva. glViewport(0,0,AnchoVentana,AltoVentana); // Le dice a OpenGL el tamao del lienzo en el que va a pintar en // pixels. Coincidira, en principio, con el tamao de nuestra ventana // y empezando por 0,0 (la esquina de nuestra ventana). glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // Borramos la ventana con el color antes establecido // (en realidad solo el backbuffer (la pantalla oculta // donde en realidad estamos pintando) // y borramos tambien el buffer de profundidad SwapBuffers(DevContex); // Le digo a nuestro espacio de dibujo que cambie "muy rapido" // el buffer de dibujo por el de visualizacion y viceversa // (suichear en Espanglish)

} // Fin IniciaGL //-----------------------------------------------------------------// Funcion para controlar lo que ocurre en la ventana segun los eventos // que vienen de Windows. Mas tarde se asocia a la ventana que crearemos. // De momento solo interceptamos la tecla ESC para poder salir del // programa cuando queramos y el evento de destruccion de ventana con el // que terminamos la aplicacion

LRESULT FAR PASCAL ProcesaMensajes(HWND Ventana, UINT Mensaje, WPARAM wParam, LPARAM lParam) { switch(Mensaje) // Segn el mensaje recibido { case WM_KEYDOWN: // Caso de mensaje de pulsacin de una tecla switch(wParam) // y segun el contenido de la variable wParam { case VK_ESCAPE: // ESC causa la salida del programa // Funcion para enviar mensaje de cerrado a la ventana // y despues de la aplicacion PostMessage(Ventana, WM_CLOSE, 0, 0); break; } break; case WM_DESTROY:// Mensaje de destruccin de la ventana (provocado por // nosotros al pulsar ESC o cerrar la ventana. PostQuitMessage(0); // Funcion para salir del programa break; } // Efectuar el proceso por defecto del mensaje (si viene cualquier mensaje // que no hemos usado, querremos que haga lo que suele hacer) return DefWindowProc(Ventana, Mensaje, wParam, lParam); } // fin ProcesaMansajes //-----------------------------------------------------------------// Funcion para crear la ventana de nuestro programa, que asociaremos // al OpenGL para pintar en ella void CreaVentana() { WNDCLASS ClaseVentana; // Declaramos un tipo de ventana, el nuestro. //Definimos nuestro tipo de ventana... ClaseVentana.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Se redibujara si // cambia el tamao de la ventana horizontal y verticalmente, y // un solo DC (device context) para cada ventana (para cuando // empezemos con OpenGL) ClaseVentana.lpfnWndProc = ProcesaMensajes; // La definimos antes para contolar // los mansajes como los del teclado ClaseVentana.cbClsExtra = 0; //Sin memoria extra para la clase ClaseVentana.cbWndExtra = 0; //Sin memoria extra para la ventana ClaseVentana.hInstance = IdAplicacion; // Identificador del programa para asociar // esta ventana con este programa. ClaseVentana.hIcon = NULL; // De momento pasamos de icono ClaseVentana.hCursor = LoadCursor(NULL, IDC_ARROW); // Flecha normal de raton ClaseVentana.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // Por ahora lo ponemos blanco ClaseVentana.lpszMenuName = NULL; // Pasamos de menu ClaseVentana.lpszClassName = L"UnSitioWeb"; // Nombre de la clase (la "L" antes de la cadena es // por que solo admite cadenas de caracteres // unicode -LPCWSTR o TCHAR- y con la "L" se convierte). RegisterClass(&ClaseVentana); // Registramos nuestro tipo de ventana

IdVentana = CreateWindowEx( // Funcion que crea la ventana. Guardamos el identificativo. WS_EX_APPWINDOW, // estilo extendido de ventana L"UnSitioWeb", // Nombre de la clase puesto antes (la "L" para UNICODE) L"Un Sitio Web", // Titulo que aparecera en la ventana. WS_POPUPWINDOW|WS_CAPTION|WS_MINIMIZEBOX, // Parametros de como sera la ventana // se pueden combinar varios. 100, // Posicion Horizontal. 100, // Posicion Vertical. AnchoVentana, // Ancho de la ventana. AltoVentana, // Alto de la ventana. (HWND) NULL, // No depende de otra ventana. (HMENU) NULL, // No le damos un menu diferente al de la clase(que es ninguno) IdAplicacion, // Identificador del programa al que pertenece la ventana. Al // empezar lo guardamos en una variable para usarlo despues. (LPVOID) NULL ); // Puntero a "no se que" datos (pasamos del tema, es para // aplicaciones MIDI). ShowWindow(IdVentana, SW_SHOW); // Mostramos nuestra ventana. UpdateWindow(IdVentana); // La actualizo para que muestre lo que tenga que mostrar // (ahora nada) } // Fin CreaVentana //-----------------------------------------------------------------// Funcion principal de un programa Windows (como main en C normal, // aqui WinMain) el prorama empieza a ejecutarse a partir de esta funcion. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(lpszCmdLine); // Para que no moleste al compilar, no lo usamos. IdAplicacion = hInstance; // Guardo el identificador del programa, luego lo usamos. CreaVentana(); // Funcion que crea la ventana. Definida mas arriba. IniciaGL(); // Funcion para inicializar OpenGL. Definida mas arriba. // // // // // Este es el bucle habitual de windows que se esta ejecutando continuamente hasta que recibe el mensaje de acabar (ya lo hemos preparado en la funcion "ProcesaMensajes" asociada a la ventana, tambien asociada a este programa atraves de su identificativo) MSG Mensaje; // Varible para contener los mensajes que van llegando. while(TRUE) // Se ejecuta continuamente. { if(PeekMessage(&Mensaje, NULL, 0, 0, PM_NOREMOVE)) // Exploramos la cola de mensajes. {// procesndolos adecuadamente if(!GetMessage(&Mensaje, NULL, 0, 0))

return (int)Mensaje.wParam; // Terminamos. TranslateMessage(&Mensaje); DispatchMessage(&Mensaje); } else WaitMessage(); // en caso contrario esperamos un mensaje } } // fin WinMain //-----------------------------------------------------------------Una ultima explicacion para los que investiguen por internet a cerca de programa cion OpenGL. Existe una libreria muy usada, y la mas habitual en los ejemplos de codigo, llamada glut que simplifica el tema del teclado, inicializacion y demas aspectos del programa base. Yo no la uso, tel vez por mania o por cabezoneria, pero prefiero gestionar yo mi smo estos temas ya que no me parece tan complicado, como habeis visto, y te da m ayor control sobre tu programa. En todo caso es una decision personal y el funci onamiento de OpenGL es el mismo en los dos casos. Suerte compilando.

+/ESCRIBIR COMENTARIO +/- COMENTARIOS A ?ADIR NUEVO BUSCAR

Banner Spanish Chinese (Simplified) English French German Japanese Portuguese Russian

Creative Commons License Esta Web est bajo licencia de Creative Commons Loading... acceder "Ningn juego dura tanto hasta que te lo terminas como el que te programas t mismo, ninguno te absorbe tanto y ninguno te produce tanta satisfaccin cuando lo has aca bado" Programacion de videojuegos Inicio Curso de programacin de juegos 3. Empezamos con OpenGL Jueves 08 de Agos to del 2013 Menu principal Inicio Que es UnSitioWeb? Noticias, opiniones y ms Curso de programacin de juegos La librera de UnSitioWeb - libUSW

Pintar texto con GLetraUSW en OpenGL Temas interesantes en la programacin de juegos Libreras tiles para programar juegos Programas del creador de juegos Manuales varios sobre informtica Foro Descargas Enlaces Contctanos Colaborar (con PayPal) Para continuar con el trabajo de esta Web y poder pagar el hosting, viene bien l a ayuda que sea. Gracias a todos. Importe: PayPal secure payments. Ultimas descargas GLetraUSW.zip 19.Jan Clase que permite dibujar texto en OpenGL con mucha facilidad.Usa FreeType2.Para ver que hace y c... FTGL compilado para VC y DEV-C 10.May Librera Corona compilada para DEV-C++ 15.Apr

Nueva librera GLetraUSW Como usar GLetraUSW Clase para pintar texto en OpenGL La muerte del PC? 23. Linux. Programa bsico XWindows y OpenGL 22. Bounding volumes y reestructuracin Frustum Culling. Otro manual. Grata sorpresa con LINUX 21. GLSL. Carga de shaders GLM (OpenGL Mathematics) 20. Billboarding. Shader Maker

3. Empezamos con OpenGL Imprimir Correo electrnico Videojuegos - Curso de Programacin de juegos Escrito por Vicengetorix oglLa libreria grafica que vamos a usar es OpenGL. Ahora comenzamos a acostumbra rnos a su uso y entender como funciona. Ya explique porque usaremos OpenGL. Ahora una breve explicacion para aclarar alg un tema que suele ser confuso cuando se empieza con esta libreria grafica. Lo normal es pensar que hace falta bajarse unas librerias para programar con Ope nGL y un "run time" para ejecutar los programas hechos con ella. Con DirectX si hace falta y ocupa lo suyo; pero con OpenGL no hay "run time" y solo hacen falta dos pequeas librerias que vienen con los compiladores (en realidad solo haria fa lta una). En realidad el nucleo de OpenGL instalado en tu ordenador, esta en el driver gra fico de tu tarjera de video y es el fabricante de la misma quien la implementa p ara su hardware. La libreria que viene con el compilador es solo un interface pa ra usar las rutinas del fabricante, y este interface incluye un metodo para ampl

iar el OpenGL para futuras mejoras de la libreria grafica (para usar OpenGL 1.0 se usa la misma libreria que para usar OpenGL 2.0) es lo que se llaman extension es. Bastante mas adelante las veremos. En resumen: no hace falta bajarse OpenGL de ningun sitio, y para hacer nuestro p rograma solo necesitaremos incluir "gl/gh.h" y "gl/glu.h" y aadir a nuestro proye cto las librerias opengl32.lib y glu32.lib. Para que nuestro programa funcione c onvendra tener bien instalado el driver de la tarjeta grafica, aunque al usar ca racteristicas basicas de OpenGL va a funcionar siempre ya que windows lo puede e jecutar por software (si usamos caracteristicas avanzadas propias de nuestro har dware de video y no tenemos los driver, fallara). Aunque este curso es eminentemente practico, no esta de mas la explicacion de al gunos conceptos basicos en programacion grafica. El buffer. No solo en graficos, sino en programacion general, es un espacio de m emoria reservado para almacenar algo. OpenGL usa varios bufferes. Los primeros y mas importantes son los que se usan p ara dibujar y el que se usa para presentar en pantalla. Se usa la tecnica de doble buffer (pueden ser mas). Entender esto es la base par a empezar a saber como trabaja un juego. Esto hay que entenderlo !. En la tecnica de boble buffer, dibujamos en un buffer que no es visible para que no se aprecie como se va haciendo nuestro dibujo y mientras presentamos el dibu jo anterior. Cuando hemos acabado de dibujar suicheamos (intercambiamos) un buff er por otro, y asi se presenta el dibujo instantaneamente. Despues seguimos dibu jando en siguiente fotograma (frame), pero esta vez lo estaremos haciendo en el otro buffer, el que ahora esta oculto (back buffer), mientras el jugador esta vi endo en pantalla el fotograma que hemos dibujado antes. Estos bufferes son de memoria de video (la de la tarjeta de video, no memoria RA M del PC). El sistema no mueve la informacion de un buffer a otro, si no que, ha ce que la tarjeta de video cambie el rango de memoria de video que se traspasa a l monitor, y el rango de memoria en la que esta el back buffer (el que se presen ta en pantalla se llama front buffer). Ejemplo: Tenemos dos bufferes, el 1 y el 2 (por ejemplo). Que siempre van a ser el mismo trozo de memoria cada uno: Ahora el 1 es el back y el 2 es el front. En el 1 pintamos mientras se ve el 2 e n el monitor. Intercambamos bufferes (SwapBuffers(DevContex)) Ahora el 2 es el back y el 1 es el front. En el 2 pintamos mientras se ve el 1 e n el monitor con el dibujo anterior. Intercambamos bufferes (SwapBuffers(DevContex)) Ahora el 1 es el back y el 2 es el front. En el 1 pintamos mientras se ve el 2 e n el monitor. ... Por si hace falta la aclaracion, la animacion en un juego -y en una pelicula- se hace presentando un dibujo tras otro con pequeas variaciones en el mismo. Siempr e deben ser mas de 24 dibujos segundo para que el ojo no perciba el cambio y el movimiento sea suave. Otro buffer importante es el de profundidad o z-buffer, muuuuuy importante si pr etendemos hacer algo en 3D. En el se guarda la profundidad de cada pixel al pint arlo (distancia de lo que se pinta a la camara). Cuando se pinta de nuevo el mis mo pixel de pantalla (con otro objeto) se compara la profundidad de el ultimo co n la que estaba guardada de antes, si es mayor la nueva (esta mas lejos), no se pinta el pixel, y si es menor (esta mas cerca), se pinta el pixel del color nuev

o en el buffer de dibujo (back buffer) y se pone la nueva profundidad -menor- en el buffer de profundidad. Hay mas bufferes como el de estarcido (stencil) o el de acumulacion pero de mome nto no nos hacen falta. Tras la explicacion, el codigo que creo que tiene suficientes comentarios para s eguirlo facilmente. En esta segunda version he puesto en funciones aparte la creacion de la ventana y la inicializacion de OpenGL. #pragma comment( lib, "openGL32.lib" ) // Estas directivas del preprocesador #pragma comment( lib, "glu32.lib" ) // le dicen a el enlazador (linker o // linkador o ...) que incluya estas // librerias. Esto se puede hacer en // la configuracion del proyecto en el // Visual C++ pero esto me parece mas // claro. #include <windows.h> #include <GL/gl.h> #include <GL/glu.h> // Fichero de inclusion para programas Windows // // // // // Los ficheros de inclusion de OpenGL. Estrictamente solo es necesario el primero. El segundo es de funciones utiles que se podrian hacer de otra manera. No nos vamos a complicar la vida y la usaremos.

HINSTANCE IdAplicacion; // Para guardar el identificador del programa HWND IdVentana; // Para guardar el identificador de la ventana HDC DevContex; // Device Context para conectar la ventana con OpenGL. HGLRC OGLrc; // Render Context para la ventana OpenGL. int AnchoVentana = 600; int AltoVentana = 400; // Lo que dice el nombre de la variable // Lo que dice el nombre de la variable

//-------------------------------------------------------------// Funcion para inicializar OpenGL. void IniciaGL() { // Definimos una estructura de tipo PIXELFORMATDESCRIPTOR para definir // las caracteristicas graficas que queremos usar (dentro de las que nos // permite el OpenGL de nuestra tarjeta de video) static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // Tamao de este descriptor 1, // Nmero de versin PFD_DRAW_TO_WINDOW | // El formato debe soportar ventana PFD_SUPPORT_OPENGL | // El formato debe soportar OpenGL PFD_DOUBLEBUFFER | // Debe soportar Doble Buffer PFD_TYPE_RGBA, // Tambin debe soportar RGBA 32, // Bits por pixels seleccionados 0,0,0,0,0,0, // Bits de color ignorados 0, // Sin buffer alpha 0, // Shift bit ignorado 0, // Buffer de acumulacin ignorado 0,0,0,0, // Bits de acumulacin ignorados 32, // Z-Buffer de 32 bits 0, // Sin buffer de pincel (Stencil)

0, PFD_MAIN_PLANE, 0, 0,0,0, };

// // // //

Sin buffer auxiliar Layer de dibujo principal Reservado Layers de mscara ignorados

// Estas funciones son las que hacen que la ventana acepte el modo grafico // que queremos dado el descriptor de pixel anterior. (en el que uno de // los parametros es que funcione con OpenGL). DevContex=GetDC(IdVentana); // Obtengo el "device context" de la ventana. int PixF=ChoosePixelFormat(DevContex,&pfd); // Busco un indice de una conbinacion // que coincida con mis especificaciones SetPixelFormat(DevContex,PixF,&pfd); // Pongo la ventana en el formato que quiero. Dos funciones de OpenGL por fin (aunque sean especificas de windows). OGLrc=wglCreateContext(DevContex); // Indico a OpenGL que la ventana esta disponible para el. wglMakeCurrent(DevContex,OGLrc); // Le digo a OpenGL que nuestra ventana es donde tiene // que dibujar a partir de ahora. A partir de ahora podemos considerar OpenGL inicializado. Aun nos queda decirle los parametros del modo en que dibujar, aunque eso se puede, y de hecho se hace continuamente, cambiar durante la ejecucion del programa. Ahora pondremos algunos parametros puramente de OpenGL de inicio. glClearDepth(1.0f); // Profundidad del buffer de profundidad. Hace que lo que esta // mas cerca se vea (dibuje) encima de lo que esta mas lejos. glDepthFunc(GL_LEQUAL); // Comparacion del buffer de profundidad. glEnable(GL_DEPTH_TEST); // Habilita test de profundidad. A partir de ahora, lo que // esta mas cerca se pinta encima. glClearColor(0,0,0,1.0f); // Color del fondo. Color con el que se borra la pantalla, o la // ventana donde pintamos. Cuando usemos la funcion glClear. glShadeModel(GL_SMOOTH); // Renderizado suave. Cuanta mejor calidad mas lento. Nosotros // tenemos un ordenador reciente(+ o -) y queremos que se vea bien. glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST); // Calidad buena de perspectiva. glViewport(0,0,AnchoVentana,AltoVentana); // Le dice a OpenGL el tamao del lienzo en el que va a pintar en // pixels. Coincidira, en principio, con el tamao de nuestra ventana // y empezando por 0,0 (la esquina de nuestra ventana). glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // Borramos la ventana con el color antes establecido // (en realidad solo el backbuffer (la pantalla oculta // donde en realidad estamos pintando) // y borramos tambien el buffer de profundidad SwapBuffers(DevContex); // Le digo a nuestro espacio de dibujo que cambie "muy rapido" // el buffer de dibujo por el de visualizacion y viceversa // (suichear en Espanglish)

//

// // // // //

} // Fin IniciaGL //-----------------------------------------------------------------// Funcion para controlar lo que ocurre en la ventana segun los eventos // que vienen de Windows. Mas tarde se asocia a la ventana que crearemos. // De momento solo interceptamos la tecla ESC para poder salir del // programa cuando queramos y el evento de destruccion de ventana con el // que terminamos la aplicacion LRESULT FAR PASCAL ProcesaMensajes(HWND Ventana, UINT Mensaje, WPARAM wParam, LPARAM lParam) { switch(Mensaje) // Segn el mensaje recibido { case WM_KEYDOWN: // Caso de mensaje de pulsacin de una tecla switch(wParam) // y segun el contenido de la variable wParam { case VK_ESCAPE: // ESC causa la salida del programa // Funcion para enviar mensaje de cerrado a la ventana // y despues de la aplicacion PostMessage(Ventana, WM_CLOSE, 0, 0); break; } break; case WM_DESTROY:// Mensaje de destruccin de la ventana (provocado por // nosotros al pulsar ESC o cerrar la ventana. PostQuitMessage(0); // Funcion para salir del programa break; } // Efectuar el proceso por defecto del mensaje (si viene cualquier mensaje // que no hemos usado, querremos que haga lo que suele hacer) return DefWindowProc(Ventana, Mensaje, wParam, lParam); } // fin ProcesaMansajes //-----------------------------------------------------------------// Funcion para crear la ventana de nuestro programa, que asociaremos // al OpenGL para pintar en ella void CreaVentana() { WNDCLASS ClaseVentana; // Declaramos un tipo de ventana, el nuestro. //Definimos nuestro tipo de ventana... ClaseVentana.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Se redibujara si // cambia el tamao de la ventana horizontal y verticalmente, y // un solo DC (device context) para cada ventana (para cuando // empezemos con OpenGL) ClaseVentana.lpfnWndProc = ProcesaMensajes; // La definimos antes para contolar // los mansajes como los del teclado ClaseVentana.cbClsExtra = 0; //Sin memoria extra para la clase ClaseVentana.cbWndExtra = 0; //Sin memoria extra para la ventana ClaseVentana.hInstance = IdAplicacion; // Identificador del programa para asociar // esta ventana con este programa. ClaseVentana.hIcon = NULL; // De momento pasamos de icono ClaseVentana.hCursor = LoadCursor(NULL, IDC_ARROW); // Flecha normal de raton ClaseVentana.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

// Por ahora lo ponemos blanco ClaseVentana.lpszMenuName = NULL; // Pasamos de menu ClaseVentana.lpszClassName = L"UnSitioWeb"; // Nombre de la clase (la "L" antes de la cadena es // por que solo admite cadenas de caracteres // unicode -LPCWSTR o TCHAR- y con la "L" se convierte). RegisterClass(&ClaseVentana); // Registramos nuestro tipo de ventana IdVentana = CreateWindowEx( // Funcion que crea la ventana. Guardamos el identificativo. WS_EX_APPWINDOW, // estilo extendido de ventana L"UnSitioWeb", // Nombre de la clase puesto antes (la "L" para UNICODE) L"Un Sitio Web", // Titulo que aparecera en la ventana. WS_POPUPWINDOW|WS_CAPTION|WS_MINIMIZEBOX, // Parametros de como sera la ventana // se pueden combinar varios. 100, // Posicion Horizontal. 100, // Posicion Vertical. AnchoVentana, // Ancho de la ventana. AltoVentana, // Alto de la ventana. (HWND) NULL, // No depende de otra ventana. (HMENU) NULL, // No le damos un menu diferente al de la clase(que es ninguno) IdAplicacion, // Identificador del programa al que pertenece la ventana. Al // empezar lo guardamos en una variable para usarlo despues. (LPVOID) NULL ); // Puntero a "no se que" datos (pasamos del tema, es para // aplicaciones MIDI). ShowWindow(IdVentana, SW_SHOW); // Mostramos nuestra ventana. UpdateWindow(IdVentana); // La actualizo para que muestre lo que tenga que mostrar // (ahora nada) } // Fin CreaVentana //-----------------------------------------------------------------// Funcion principal de un programa Windows (como main en C normal, // aqui WinMain) el prorama empieza a ejecutarse a partir de esta funcion. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(lpszCmdLine); // Para que no moleste al compilar, no lo usamos. IdAplicacion = hInstance; // Guardo el identificador del programa, luego lo usamos. CreaVentana(); // Funcion que crea la ventana. Definida mas arriba. IniciaGL(); // Funcion para inicializar OpenGL. Definida mas arriba. // Este es el bucle habitual de windows que se esta ejecutando // continuamente hasta que recibe el mensaje de acabar (ya lo hemos // preparado en la funcion "ProcesaMensajes" asociada a

// la ventana, tambien asociada a este programa atraves de su // identificativo) MSG Mensaje; // Varible para contener los mensajes que van llegando. while(TRUE) // Se ejecuta continuamente. { if(PeekMessage(&Mensaje, NULL, 0, 0, PM_NOREMOVE)) // Exploramos la cola de mensajes. {// procesndolos adecuadamente if(!GetMessage(&Mensaje, NULL, 0, 0)) return (int)Mensaje.wParam; // Terminamos. TranslateMessage(&Mensaje); DispatchMessage(&Mensaje); } else WaitMessage(); // en caso contrario esperamos un mensaje } } // fin WinMain //-----------------------------------------------------------------Una ultima explicacion para los que investiguen por internet a cerca de programa cion OpenGL. Existe una libreria muy usada, y la mas habitual en los ejemplos de codigo, llamada glut que simplifica el tema del teclado, inicializacion y demas aspectos del programa base. Yo no la uso, tel vez por mania o por cabezoneria, pero prefiero gestionar yo mi smo estos temas ya que no me parece tan complicado, como habeis visto, y te da m ayor control sobre tu programa. En todo caso es una decision personal y el funci onamiento de OpenGL es el mismo en los dos casos. Suerte compilando.

+/ESCRIBIR COMENTARIO +/- COMENTARIOS A ?ADIR NUEVO BUSCAR

Banner Spanish Chinese (Simplified) English French German Japanese Portuguese Russian

Creative Commons License Esta Web est bajo licencia de Creative Commons Loading... acceder "Ningn juego dura tanto hasta que te lo terminas como el que te programas t mismo, ninguno te absorbe tanto y ninguno te produce tanta satisfaccin cuando lo has aca bado" Programacion de videojuegos

Inicio Curso de programacin de juegos 3. Empezamos con OpenGL Jueves 08 de Agos to del 2013 Menu principal Inicio Que es UnSitioWeb? Noticias, opiniones y ms Curso de programacin de juegos La librera de UnSitioWeb - libUSW Pintar texto con GLetraUSW en OpenGL Temas interesantes en la programacin de juegos Libreras tiles para programar juegos Programas del creador de juegos Manuales varios sobre informtica Foro Descargas Enlaces Contctanos Colaborar (con PayPal) Para continuar con el trabajo de esta Web y poder pagar el hosting, viene bien l a ayuda que sea. Gracias a todos. Importe: PayPal secure payments. Ultimas descargas GLetraUSW.zip 19.Jan Clase que permite dibujar texto en OpenGL con mucha facilidad.Usa FreeType2.Para ver que hace y c... FTGL compilado para VC y DEV-C 10.May Librera Corona compilada para DEV-C++ 15.Apr

Nueva librera GLetraUSW Como usar GLetraUSW Clase para pintar texto en OpenGL La muerte del PC? 23. Linux. Programa bsico XWindows y OpenGL 22. Bounding volumes y reestructuracin Frustum Culling. Otro manual. Grata sorpresa con LINUX 21. GLSL. Carga de shaders GLM (OpenGL Mathematics) 20. Billboarding. Shader Maker

3. Empezamos con OpenGL Imprimir Correo electrnico Videojuegos - Curso de Programacin de juegos Escrito por Vicengetorix oglLa libreria grafica que vamos a usar es OpenGL. Ahora comenzamos a acostumbra rnos a su uso y entender como funciona. Ya explique porque usaremos OpenGL. Ahora una breve explicacion para aclarar alg un tema que suele ser confuso cuando se empieza con esta libreria grafica.

Lo normal es pensar que hace falta bajarse unas librerias para programar con Ope nGL y un "run time" para ejecutar los programas hechos con ella. Con DirectX si hace falta y ocupa lo suyo; pero con OpenGL no hay "run time" y solo hacen falta dos pequeas librerias que vienen con los compiladores (en realidad solo haria fa lta una). En realidad el nucleo de OpenGL instalado en tu ordenador, esta en el driver gra fico de tu tarjera de video y es el fabricante de la misma quien la implementa p ara su hardware. La libreria que viene con el compilador es solo un interface pa ra usar las rutinas del fabricante, y este interface incluye un metodo para ampl iar el OpenGL para futuras mejoras de la libreria grafica (para usar OpenGL 1.0 se usa la misma libreria que para usar OpenGL 2.0) es lo que se llaman extension es. Bastante mas adelante las veremos. En resumen: no hace falta bajarse OpenGL de ningun sitio, y para hacer nuestro p rograma solo necesitaremos incluir "gl/gh.h" y "gl/glu.h" y aadir a nuestro proye cto las librerias opengl32.lib y glu32.lib. Para que nuestro programa funcione c onvendra tener bien instalado el driver de la tarjeta grafica, aunque al usar ca racteristicas basicas de OpenGL va a funcionar siempre ya que windows lo puede e jecutar por software (si usamos caracteristicas avanzadas propias de nuestro har dware de video y no tenemos los driver, fallara). Aunque este curso es eminentemente practico, no esta de mas la explicacion de al gunos conceptos basicos en programacion grafica. El buffer. No solo en graficos, sino en programacion general, es un espacio de m emoria reservado para almacenar algo. OpenGL usa varios bufferes. Los primeros y mas importantes son los que se usan p ara dibujar y el que se usa para presentar en pantalla. Se usa la tecnica de doble buffer (pueden ser mas). Entender esto es la base par a empezar a saber como trabaja un juego. Esto hay que entenderlo !. En la tecnica de boble buffer, dibujamos en un buffer que no es visible para que no se aprecie como se va haciendo nuestro dibujo y mientras presentamos el dibu jo anterior. Cuando hemos acabado de dibujar suicheamos (intercambiamos) un buff er por otro, y asi se presenta el dibujo instantaneamente. Despues seguimos dibu jando en siguiente fotograma (frame), pero esta vez lo estaremos haciendo en el otro buffer, el que ahora esta oculto (back buffer), mientras el jugador esta vi endo en pantalla el fotograma que hemos dibujado antes. Estos bufferes son de memoria de video (la de la tarjeta de video, no memoria RA M del PC). El sistema no mueve la informacion de un buffer a otro, si no que, ha ce que la tarjeta de video cambie el rango de memoria de video que se traspasa a l monitor, y el rango de memoria en la que esta el back buffer (el que se presen ta en pantalla se llama front buffer). Ejemplo: Tenemos dos bufferes, el 1 y el 2 (por ejemplo). Que siempre van a ser el mismo trozo de memoria cada uno: Ahora el 1 es el back y el 2 es el front. En el 1 pintamos mientras se ve el 2 e n el monitor. Intercambamos bufferes (SwapBuffers(DevContex)) Ahora el 2 es el back y el 1 es el front. En el 2 pintamos mientras se ve el 1 e n el monitor con el dibujo anterior. Intercambamos bufferes (SwapBuffers(DevContex)) Ahora el 1 es el back y el 2 es el front. En el 1 pintamos mientras se ve el 2 e n el monitor. ... Por si hace falta la aclaracion, la animacion en un juego -y en una pelicula- se hace presentando un dibujo tras otro con pequeas variaciones en el mismo. Siempr

e deben ser mas de 24 dibujos segundo para que el ojo no perciba el cambio y el movimiento sea suave. Otro buffer importante es el de profundidad o z-buffer, muuuuuy importante si pr etendemos hacer algo en 3D. En el se guarda la profundidad de cada pixel al pint arlo (distancia de lo que se pinta a la camara). Cuando se pinta de nuevo el mis mo pixel de pantalla (con otro objeto) se compara la profundidad de el ultimo co n la que estaba guardada de antes, si es mayor la nueva (esta mas lejos), no se pinta el pixel, y si es menor (esta mas cerca), se pinta el pixel del color nuev o en el buffer de dibujo (back buffer) y se pone la nueva profundidad -menor- en el buffer de profundidad. Hay mas bufferes como el de estarcido (stencil) o el de acumulacion pero de mome nto no nos hacen falta. Tras la explicacion, el codigo que creo que tiene suficientes comentarios para s eguirlo facilmente. En esta segunda version he puesto en funciones aparte la creacion de la ventana y la inicializacion de OpenGL. #pragma comment( lib, "openGL32.lib" ) // Estas directivas del preprocesador #pragma comment( lib, "glu32.lib" ) // le dicen a el enlazador (linker o // linkador o ...) que incluya estas // librerias. Esto se puede hacer en // la configuracion del proyecto en el // Visual C++ pero esto me parece mas // claro. #include <windows.h> #include <GL/gl.h> #include <GL/glu.h> // Fichero de inclusion para programas Windows // // // // // Los ficheros de inclusion de OpenGL. Estrictamente solo es necesario el primero. El segundo es de funciones utiles que se podrian hacer de otra manera. No nos vamos a complicar la vida y la usaremos.

HINSTANCE IdAplicacion; // Para guardar el identificador del programa HWND IdVentana; // Para guardar el identificador de la ventana HDC DevContex; // Device Context para conectar la ventana con OpenGL. HGLRC OGLrc; // Render Context para la ventana OpenGL. int AnchoVentana = 600; int AltoVentana = 400; // Lo que dice el nombre de la variable // Lo que dice el nombre de la variable

//-------------------------------------------------------------// Funcion para inicializar OpenGL. void IniciaGL() { // Definimos una estructura de tipo PIXELFORMATDESCRIPTOR para definir // las caracteristicas graficas que queremos usar (dentro de las que nos // permite el OpenGL de nuestra tarjeta de video) static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // Tamao de este descriptor 1, // Nmero de versin PFD_DRAW_TO_WINDOW | // El formato debe soportar ventana PFD_SUPPORT_OPENGL | // El formato debe soportar OpenGL PFD_DOUBLEBUFFER | // Debe soportar Doble Buffer

PFD_TYPE_RGBA, 32, 0,0,0,0,0,0, 0, 0, 0, 0,0,0,0, 32, 0, 0, PFD_MAIN_PLANE, 0, 0,0,0, };

// // // // // // // // // // // // //

Tambin debe soportar RGBA Bits por pixels seleccionados Bits de color ignorados Sin buffer alpha Shift bit ignorado Buffer de acumulacin ignorado Bits de acumulacin ignorados Z-Buffer de 32 bits Sin buffer de pincel (Stencil) Sin buffer auxiliar Layer de dibujo principal Reservado Layers de mscara ignorados

// Estas funciones son las que hacen que la ventana acepte el modo grafico // que queremos dado el descriptor de pixel anterior. (en el que uno de // los parametros es que funcione con OpenGL). DevContex=GetDC(IdVentana); // Obtengo el "device context" de la ventana. int PixF=ChoosePixelFormat(DevContex,&pfd); // Busco un indice de una conbinacion // que coincida con mis especificaciones SetPixelFormat(DevContex,PixF,&pfd); // Pongo la ventana en el formato que quiero. Dos funciones de OpenGL por fin (aunque sean especificas de windows). OGLrc=wglCreateContext(DevContex); // Indico a OpenGL que la ventana esta disponible para el. wglMakeCurrent(DevContex,OGLrc); // Le digo a OpenGL que nuestra ventana es donde tiene // que dibujar a partir de ahora. A partir de ahora podemos considerar OpenGL inicializado. Aun nos queda decirle los parametros del modo en que dibujar, aunque eso se puede, y de hecho se hace continuamente, cambiar durante la ejecucion del programa. Ahora pondremos algunos parametros puramente de OpenGL de inicio. glClearDepth(1.0f); // Profundidad del buffer de profundidad. Hace que lo que esta // mas cerca se vea (dibuje) encima de lo que esta mas lejos. glDepthFunc(GL_LEQUAL); // Comparacion del buffer de profundidad. glEnable(GL_DEPTH_TEST); // Habilita test de profundidad. A partir de ahora, lo que // esta mas cerca se pinta encima. glClearColor(0,0,0,1.0f); // Color del fondo. Color con el que se borra la pantalla, o la // ventana donde pintamos. Cuando usemos la funcion glClear. glShadeModel(GL_SMOOTH); // Renderizado suave. Cuanta mejor calidad mas lento. Nosotros // tenemos un ordenador reciente(+ o -) y queremos que se vea bien. glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST); // Calidad buena de perspectiva. glViewport(0,0,AnchoVentana,AltoVentana); // Le dice a OpenGL el tamao del lienzo en el que va a pintar en // pixels. Coincidira, en principio, con el tamao de nuestra ventana // y empezando por 0,0 (la esquina de nuestra ventana). glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

//

// // // // //

// Borramos la ventana con el color antes establecido // (en realidad solo el backbuffer (la pantalla oculta // donde en realidad estamos pintando) // y borramos tambien el buffer de profundidad SwapBuffers(DevContex); // Le digo a nuestro espacio de dibujo que cambie "muy rapido" // el buffer de dibujo por el de visualizacion y viceversa // (suichear en Espanglish) } // Fin IniciaGL //-----------------------------------------------------------------// Funcion para controlar lo que ocurre en la ventana segun los eventos // que vienen de Windows. Mas tarde se asocia a la ventana que crearemos. // De momento solo interceptamos la tecla ESC para poder salir del // programa cuando queramos y el evento de destruccion de ventana con el // que terminamos la aplicacion LRESULT FAR PASCAL ProcesaMensajes(HWND Ventana, UINT Mensaje, WPARAM wParam, LPARAM lParam) { switch(Mensaje) // Segn el mensaje recibido { case WM_KEYDOWN: // Caso de mensaje de pulsacin de una tecla switch(wParam) // y segun el contenido de la variable wParam { case VK_ESCAPE: // ESC causa la salida del programa // Funcion para enviar mensaje de cerrado a la ventana // y despues de la aplicacion PostMessage(Ventana, WM_CLOSE, 0, 0); break; } break; case WM_DESTROY:// Mensaje de destruccin de la ventana (provocado por // nosotros al pulsar ESC o cerrar la ventana. PostQuitMessage(0); // Funcion para salir del programa break; } // Efectuar el proceso por defecto del mensaje (si viene cualquier mensaje // que no hemos usado, querremos que haga lo que suele hacer) return DefWindowProc(Ventana, Mensaje, wParam, lParam); } // fin ProcesaMansajes //-----------------------------------------------------------------// Funcion para crear la ventana de nuestro programa, que asociaremos // al OpenGL para pintar en ella void CreaVentana() { WNDCLASS ClaseVentana; // Declaramos un tipo de ventana, el nuestro. //Definimos nuestro tipo de ventana... ClaseVentana.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Se redibujara si // cambia el tamao de la ventana horizontal y verticalmente, y // un solo DC (device context) para cada ventana (para cuando // empezemos con OpenGL) ClaseVentana.lpfnWndProc = ProcesaMensajes; // La definimos antes para contolar // los mansajes como los del teclado

ClaseVentana.cbClsExtra = 0; //Sin memoria extra para la clase ClaseVentana.cbWndExtra = 0; //Sin memoria extra para la ventana ClaseVentana.hInstance = IdAplicacion; // Identificador del programa para asociar // esta ventana con este programa. ClaseVentana.hIcon = NULL; // De momento pasamos de icono ClaseVentana.hCursor = LoadCursor(NULL, IDC_ARROW); // Flecha normal de raton ClaseVentana.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // Por ahora lo ponemos blanco ClaseVentana.lpszMenuName = NULL; // Pasamos de menu ClaseVentana.lpszClassName = L"UnSitioWeb"; // Nombre de la clase (la "L" antes de la cadena es // por que solo admite cadenas de caracteres // unicode -LPCWSTR o TCHAR- y con la "L" se convierte). RegisterClass(&ClaseVentana); // Registramos nuestro tipo de ventana IdVentana = CreateWindowEx( // Funcion que crea la ventana. Guardamos el identificativo. WS_EX_APPWINDOW, // estilo extendido de ventana L"UnSitioWeb", // Nombre de la clase puesto antes (la "L" para UNICODE) L"Un Sitio Web", // Titulo que aparecera en la ventana. WS_POPUPWINDOW|WS_CAPTION|WS_MINIMIZEBOX, // Parametros de como sera la ventana // se pueden combinar varios. 100, // Posicion Horizontal. 100, // Posicion Vertical. AnchoVentana, // Ancho de la ventana. AltoVentana, // Alto de la ventana. (HWND) NULL, // No depende de otra ventana. (HMENU) NULL, // No le damos un menu diferente al de la clase(que es ninguno) IdAplicacion, // Identificador del programa al que pertenece la ventana. Al // empezar lo guardamos en una variable para usarlo despues. (LPVOID) NULL ); // Puntero a "no se que" datos (pasamos del tema, es para // aplicaciones MIDI). ShowWindow(IdVentana, SW_SHOW); // Mostramos nuestra ventana. UpdateWindow(IdVentana); // La actualizo para que muestre lo que tenga que mostrar // (ahora nada) } // Fin CreaVentana //-----------------------------------------------------------------// Funcion principal de un programa Windows (como main en C normal, // aqui WinMain) el prorama empieza a ejecutarse a partir de esta funcion. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(lpszCmdLine); // Para que no moleste al compilar, no lo usamos. IdAplicacion = hInstance;

// Guardo el identificador del programa, luego lo usamos. CreaVentana(); // Funcion que crea la ventana. Definida mas arriba. IniciaGL(); // Funcion para inicializar OpenGL. Definida mas arriba. // // // // // Este es el bucle habitual de windows que se esta ejecutando continuamente hasta que recibe el mensaje de acabar (ya lo hemos preparado en la funcion "ProcesaMensajes" asociada a la ventana, tambien asociada a este programa atraves de su identificativo) MSG Mensaje; // Varible para contener los mensajes que van llegando. while(TRUE) // Se ejecuta continuamente. { if(PeekMessage(&Mensaje, NULL, 0, 0, PM_NOREMOVE)) // Exploramos la cola de mensajes. {// procesndolos adecuadamente if(!GetMessage(&Mensaje, NULL, 0, 0)) return (int)Mensaje.wParam; // Terminamos. TranslateMessage(&Mensaje); DispatchMessage(&Mensaje); } else WaitMessage(); // en caso contrario esperamos un mensaje }

} // fin WinMain //-----------------------------------------------------------------Una ultima explicacion para los que investiguen por internet a cerca de programa cion OpenGL. Existe una libreria muy usada, y la mas habitual en los ejemplos de codigo, llamada glut que simplifica el tema del teclado, inicializacion y demas aspectos del programa base. Yo no la uso, tel vez por mania o por cabezoneria, pero prefiero gestionar yo mi smo estos temas ya que no me parece tan complicado, como habeis visto, y te da m ayor control sobre tu programa. En todo caso es una decision personal y el funci onamiento de OpenGL es el mismo en los dos casos. Suerte compilando.

+/ESCRIBIR COMENTARIO +/- COMENTARIOS A ?ADIR NUEVO BUSCAR

Banner Spanish Chinese (Simplified) English French German Japanese Portuguese Russian

Creative Commons License Esta Web est bajo licencia de Creative Commons

Loading... acceder "Ningn juego dura tanto hasta que te lo terminas como el que te programas t mismo, ninguno te absorbe tanto y ninguno te produce tanta satisfaccin cuando lo has aca bado" Programacion de videojuegos Inicio Curso de programacin de juegos 3. Empezamos con OpenGL Jueves 08 de Agos to del 2013 Menu principal Inicio Que es UnSitioWeb? Noticias, opiniones y ms Curso de programacin de juegos La librera de UnSitioWeb - libUSW Pintar texto con GLetraUSW en OpenGL Temas interesantes en la programacin de juegos Libreras tiles para programar juegos Programas del creador de juegos Manuales varios sobre informtica Foro Descargas Enlaces Contctanos Colaborar (con PayPal) Para continuar con el trabajo de esta Web y poder pagar el hosting, viene bien l a ayuda que sea. Gracias a todos. Importe: PayPal secure payments. Ultimas descargas GLetraUSW.zip 19.Jan Clase que permite dibujar texto en OpenGL con mucha facilidad.Usa FreeType2.Para ver que hace y c... FTGL compilado para VC y DEV-C 10.May Librera Corona compilada para DEV-C++ 15.Apr

Nueva librera GLetraUSW Como usar GLetraUSW Clase para pintar texto en OpenGL La muerte del PC? 23. Linux. Programa bsico XWindows y OpenGL 22. Bounding volumes y reestructuracin Frustum Culling. Otro manual. Grata sorpresa con LINUX 21. GLSL. Carga de shaders GLM (OpenGL Mathematics) 20. Billboarding. Shader Maker

3. Empezamos con OpenGL Imprimir Correo electrnico Videojuegos - Curso de Programacin de juegos Escrito por Vicengetorix oglLa libreria grafica que vamos a usar es OpenGL. Ahora comenzamos a acostumbra rnos a su uso y entender como funciona. Ya explique porque usaremos OpenGL. Ahora una breve explicacion para aclarar alg un tema que suele ser confuso cuando se empieza con esta libreria grafica. Lo normal es pensar que hace falta bajarse unas librerias para programar con Ope nGL y un "run time" para ejecutar los programas hechos con ella. Con DirectX si hace falta y ocupa lo suyo; pero con OpenGL no hay "run time" y solo hacen falta dos pequeas librerias que vienen con los compiladores (en realidad solo haria fa lta una). En realidad el nucleo de OpenGL instalado en tu ordenador, esta en el driver gra fico de tu tarjera de video y es el fabricante de la misma quien la implementa p ara su hardware. La libreria que viene con el compilador es solo un interface pa ra usar las rutinas del fabricante, y este interface incluye un metodo para ampl iar el OpenGL para futuras mejoras de la libreria grafica (para usar OpenGL 1.0 se usa la misma libreria que para usar OpenGL 2.0) es lo que se llaman extension es. Bastante mas adelante las veremos. En resumen: no hace falta bajarse OpenGL de ningun sitio, y para hacer nuestro p rograma solo necesitaremos incluir "gl/gh.h" y "gl/glu.h" y aadir a nuestro proye cto las librerias opengl32.lib y glu32.lib. Para que nuestro programa funcione c onvendra tener bien instalado el driver de la tarjeta grafica, aunque al usar ca racteristicas basicas de OpenGL va a funcionar siempre ya que windows lo puede e jecutar por software (si usamos caracteristicas avanzadas propias de nuestro har dware de video y no tenemos los driver, fallara). Aunque este curso es eminentemente practico, no esta de mas la explicacion de al gunos conceptos basicos en programacion grafica. El buffer. No solo en graficos, sino en programacion general, es un espacio de m emoria reservado para almacenar algo. OpenGL usa varios bufferes. Los primeros y mas importantes son los que se usan p ara dibujar y el que se usa para presentar en pantalla. Se usa la tecnica de doble buffer (pueden ser mas). Entender esto es la base par a empezar a saber como trabaja un juego. Esto hay que entenderlo !. En la tecnica de boble buffer, dibujamos en un buffer que no es visible para que no se aprecie como se va haciendo nuestro dibujo y mientras presentamos el dibu jo anterior. Cuando hemos acabado de dibujar suicheamos (intercambiamos) un buff er por otro, y asi se presenta el dibujo instantaneamente. Despues seguimos dibu jando en siguiente fotograma (frame), pero esta vez lo estaremos haciendo en el otro buffer, el que ahora esta oculto (back buffer), mientras el jugador esta vi endo en pantalla el fotograma que hemos dibujado antes. Estos bufferes son de memoria de video (la de la tarjeta de video, no memoria RA M del PC). El sistema no mueve la informacion de un buffer a otro, si no que, ha ce que la tarjeta de video cambie el rango de memoria de video que se traspasa a l monitor, y el rango de memoria en la que esta el back buffer (el que se presen ta en pantalla se llama front buffer). Ejemplo: Tenemos dos bufferes, el 1 y el 2 (por ejemplo). Que siempre van a ser el mismo trozo de memoria cada uno: Ahora el 1 es el back y el 2 es el front. En el 1 pintamos mientras se ve el 2 e n el monitor. Intercambamos bufferes (SwapBuffers(DevContex))

Ahora el 2 es el back y el 1 es el front. En el 2 pintamos mientras se ve el 1 e n el monitor con el dibujo anterior. Intercambamos bufferes (SwapBuffers(DevContex)) Ahora el 1 es el back y el 2 es el front. En el 1 pintamos mientras se ve el 2 e n el monitor. ... Por si hace falta la aclaracion, la animacion en un juego -y en una pelicula- se hace presentando un dibujo tras otro con pequeas variaciones en el mismo. Siempr e deben ser mas de 24 dibujos segundo para que el ojo no perciba el cambio y el movimiento sea suave. Otro buffer importante es el de profundidad o z-buffer, muuuuuy importante si pr etendemos hacer algo en 3D. En el se guarda la profundidad de cada pixel al pint arlo (distancia de lo que se pinta a la camara). Cuando se pinta de nuevo el mis mo pixel de pantalla (con otro objeto) se compara la profundidad de el ultimo co n la que estaba guardada de antes, si es mayor la nueva (esta mas lejos), no se pinta el pixel, y si es menor (esta mas cerca), se pinta el pixel del color nuev o en el buffer de dibujo (back buffer) y se pone la nueva profundidad -menor- en el buffer de profundidad. Hay mas bufferes como el de estarcido (stencil) o el de acumulacion pero de mome nto no nos hacen falta. Tras la explicacion, el codigo que creo que tiene suficientes comentarios para s eguirlo facilmente. En esta segunda version he puesto en funciones aparte la creacion de la ventana y la inicializacion de OpenGL. #pragma comment( lib, "openGL32.lib" ) // Estas directivas del preprocesador #pragma comment( lib, "glu32.lib" ) // le dicen a el enlazador (linker o // linkador o ...) que incluya estas // librerias. Esto se puede hacer en // la configuracion del proyecto en el // Visual C++ pero esto me parece mas // claro. #include <windows.h> #include <GL/gl.h> #include <GL/glu.h> // Fichero de inclusion para programas Windows // // // // // Los ficheros de inclusion de OpenGL. Estrictamente solo es necesario el primero. El segundo es de funciones utiles que se podrian hacer de otra manera. No nos vamos a complicar la vida y la usaremos.

HINSTANCE IdAplicacion; // Para guardar el identificador del programa HWND IdVentana; // Para guardar el identificador de la ventana HDC DevContex; // Device Context para conectar la ventana con OpenGL. HGLRC OGLrc; // Render Context para la ventana OpenGL. int AnchoVentana = 600; int AltoVentana = 400; // Lo que dice el nombre de la variable // Lo que dice el nombre de la variable

//-------------------------------------------------------------// Funcion para inicializar OpenGL. void IniciaGL() { // Definimos una estructura de tipo PIXELFORMATDESCRIPTOR para definir

// las caracteristicas graficas que queremos usar (dentro de las que nos // permite el OpenGL de nuestra tarjeta de video) static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // Tamao de este descriptor 1, // Nmero de versin PFD_DRAW_TO_WINDOW | // El formato debe soportar ventana PFD_SUPPORT_OPENGL | // El formato debe soportar OpenGL PFD_DOUBLEBUFFER | // Debe soportar Doble Buffer PFD_TYPE_RGBA, // Tambin debe soportar RGBA 32, // Bits por pixels seleccionados 0,0,0,0,0,0, // Bits de color ignorados 0, // Sin buffer alpha 0, // Shift bit ignorado 0, // Buffer de acumulacin ignorado 0,0,0,0, // Bits de acumulacin ignorados 32, // Z-Buffer de 32 bits 0, // Sin buffer de pincel (Stencil) 0, // Sin buffer auxiliar PFD_MAIN_PLANE, // Layer de dibujo principal 0, // Reservado 0,0,0, // Layers de mscara ignorados }; // Estas funciones son las que hacen que la ventana acepte el modo grafico // que queremos dado el descriptor de pixel anterior. (en el que uno de // los parametros es que funcione con OpenGL). DevContex=GetDC(IdVentana); // Obtengo el "device context" de la ventana. int PixF=ChoosePixelFormat(DevContex,&pfd); // Busco un indice de una conbinacion // que coincida con mis especificaciones SetPixelFormat(DevContex,PixF,&pfd); // Pongo la ventana en el formato que quiero. Dos funciones de OpenGL por fin (aunque sean especificas de windows). OGLrc=wglCreateContext(DevContex); // Indico a OpenGL que la ventana esta disponible para el. wglMakeCurrent(DevContex,OGLrc); // Le digo a OpenGL que nuestra ventana es donde tiene // que dibujar a partir de ahora. A partir de ahora podemos considerar OpenGL inicializado. Aun nos queda decirle los parametros del modo en que dibujar, aunque eso se puede, y de hecho se hace continuamente, cambiar durante la ejecucion del programa. Ahora pondremos algunos parametros puramente de OpenGL de inicio. glClearDepth(1.0f); // Profundidad del buffer de profundidad. Hace que lo que esta // mas cerca se vea (dibuje) encima de lo que esta mas lejos. glDepthFunc(GL_LEQUAL); // Comparacion del buffer de profundidad. glEnable(GL_DEPTH_TEST); // Habilita test de profundidad. A partir de ahora, lo que // esta mas cerca se pinta encima. glClearColor(0,0,0,1.0f); // Color del fondo. Color con el que se borra la pantalla, o la // ventana donde pintamos. Cuando usemos la funcion glClear. glShadeModel(GL_SMOOTH); // Renderizado suave. Cuanta mejor calidad mas lento. Nosotros // tenemos un ordenador reciente(+ o -) y queremos que se vea bien.

//

// // // // //

glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST); // Calidad buena de perspectiva. glViewport(0,0,AnchoVentana,AltoVentana); // Le dice a OpenGL el tamao del lienzo en el que va a pintar en // pixels. Coincidira, en principio, con el tamao de nuestra ventana // y empezando por 0,0 (la esquina de nuestra ventana). glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // Borramos la ventana con el color antes establecido // (en realidad solo el backbuffer (la pantalla oculta // donde en realidad estamos pintando) // y borramos tambien el buffer de profundidad SwapBuffers(DevContex); // Le digo a nuestro espacio de dibujo que cambie "muy rapido" // el buffer de dibujo por el de visualizacion y viceversa // (suichear en Espanglish) } // Fin IniciaGL //-----------------------------------------------------------------// Funcion para controlar lo que ocurre en la ventana segun los eventos // que vienen de Windows. Mas tarde se asocia a la ventana que crearemos. // De momento solo interceptamos la tecla ESC para poder salir del // programa cuando queramos y el evento de destruccion de ventana con el // que terminamos la aplicacion LRESULT FAR PASCAL ProcesaMensajes(HWND Ventana, UINT Mensaje, WPARAM wParam, LPARAM lParam) { switch(Mensaje) // Segn el mensaje recibido { case WM_KEYDOWN: // Caso de mensaje de pulsacin de una tecla switch(wParam) // y segun el contenido de la variable wParam { case VK_ESCAPE: // ESC causa la salida del programa // Funcion para enviar mensaje de cerrado a la ventana // y despues de la aplicacion PostMessage(Ventana, WM_CLOSE, 0, 0); break; } break; case WM_DESTROY:// Mensaje de destruccin de la ventana (provocado por // nosotros al pulsar ESC o cerrar la ventana. PostQuitMessage(0); // Funcion para salir del programa break; } // Efectuar el proceso por defecto del mensaje (si viene cualquier mensaje // que no hemos usado, querremos que haga lo que suele hacer) return DefWindowProc(Ventana, Mensaje, wParam, lParam); } // fin ProcesaMansajes //-----------------------------------------------------------------// Funcion para crear la ventana de nuestro programa, que asociaremos // al OpenGL para pintar en ella void CreaVentana() { WNDCLASS ClaseVentana; // Declaramos un tipo de ventana, el nuestro.

//Definimos nuestro tipo de ventana... ClaseVentana.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Se redibujara si // cambia el tamao de la ventana horizontal y verticalmente, y // un solo DC (device context) para cada ventana (para cuando // empezemos con OpenGL) ClaseVentana.lpfnWndProc = ProcesaMensajes; // La definimos antes para contolar // los mansajes como los del teclado ClaseVentana.cbClsExtra = 0; //Sin memoria extra para la clase ClaseVentana.cbWndExtra = 0; //Sin memoria extra para la ventana ClaseVentana.hInstance = IdAplicacion; // Identificador del programa para asociar // esta ventana con este programa. ClaseVentana.hIcon = NULL; // De momento pasamos de icono ClaseVentana.hCursor = LoadCursor(NULL, IDC_ARROW); // Flecha normal de raton ClaseVentana.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // Por ahora lo ponemos blanco ClaseVentana.lpszMenuName = NULL; // Pasamos de menu ClaseVentana.lpszClassName = L"UnSitioWeb"; // Nombre de la clase (la "L" antes de la cadena es // por que solo admite cadenas de caracteres // unicode -LPCWSTR o TCHAR- y con la "L" se convierte). RegisterClass(&ClaseVentana); // Registramos nuestro tipo de ventana IdVentana = CreateWindowEx( // Funcion que crea la ventana. Guardamos el identificativo. WS_EX_APPWINDOW, // estilo extendido de ventana L"UnSitioWeb", // Nombre de la clase puesto antes (la "L" para UNICODE) L"Un Sitio Web", // Titulo que aparecera en la ventana. WS_POPUPWINDOW|WS_CAPTION|WS_MINIMIZEBOX, // Parametros de como sera la ventana // se pueden combinar varios. 100, // Posicion Horizontal. 100, // Posicion Vertical. AnchoVentana, // Ancho de la ventana. AltoVentana, // Alto de la ventana. (HWND) NULL, // No depende de otra ventana. (HMENU) NULL, // No le damos un menu diferente al de la clase(que es ninguno) IdAplicacion, // Identificador del programa al que pertenece la ventana. Al // empezar lo guardamos en una variable para usarlo despues. (LPVOID) NULL ); // Puntero a "no se que" datos (pasamos del tema, es para // aplicaciones MIDI). ShowWindow(IdVentana, SW_SHOW); // Mostramos nuestra ventana. UpdateWindow(IdVentana); // La actualizo para que muestre lo que tenga que mostrar // (ahora nada) } // Fin CreaVentana

//-----------------------------------------------------------------// Funcion principal de un programa Windows (como main en C normal, // aqui WinMain) el prorama empieza a ejecutarse a partir de esta funcion. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(lpszCmdLine); // Para que no moleste al compilar, no lo usamos. IdAplicacion = hInstance; // Guardo el identificador del programa, luego lo usamos. CreaVentana(); // Funcion que crea la ventana. Definida mas arriba. IniciaGL(); // Funcion para inicializar OpenGL. Definida mas arriba. // // // // // Este es el bucle habitual de windows que se esta ejecutando continuamente hasta que recibe el mensaje de acabar (ya lo hemos preparado en la funcion "ProcesaMensajes" asociada a la ventana, tambien asociada a este programa atraves de su identificativo) MSG Mensaje; // Varible para contener los mensajes que van llegando. while(TRUE) // Se ejecuta continuamente. { if(PeekMessage(&Mensaje, NULL, 0, 0, PM_NOREMOVE)) // Exploramos la cola de mensajes. {// procesndolos adecuadamente if(!GetMessage(&Mensaje, NULL, 0, 0)) return (int)Mensaje.wParam; // Terminamos. TranslateMessage(&Mensaje); DispatchMessage(&Mensaje); } else WaitMessage(); // en caso contrario esperamos un mensaje }

} // fin WinMain //-----------------------------------------------------------------Una ultima explicacion para los que investiguen por internet a cerca de programa cion OpenGL. Existe una libreria muy usada, y la mas habitual en los ejemplos de codigo, llamada glut que simplifica el tema del teclado, inicializacion y demas aspectos del programa base. Yo no la uso, tel vez por mania o por cabezoneria, pero prefiero gestionar yo mi smo estos temas ya que no me parece tan complicado, como habeis visto, y te da m ayor control sobre tu programa. En todo caso es una decision personal y el funci onamiento de OpenGL es el mismo en los dos casos. Suerte compilando.

+/ESCRIBIR COMENTARIO +/- COMENTARIOS A ?ADIR NUEVO BUSCAR

Banner Spanish Chinese (Simplified) English French German Japanese Portuguese Russian

Creative Commons License Esta Web est bajo licencia de Creative Commons Loading... acceder "Ningn juego dura tanto hasta que te lo terminas como el que te programas t mismo, ninguno te absorbe tanto y ninguno te produce tanta satisfaccin cuando lo has aca bado" Programacion de videojuegos Inicio Curso de programacin de juegos 3. Empezamos con OpenGL Jueves 08 de Agos to del 2013 Menu principal Inicio Que es UnSitioWeb? Noticias, opiniones y ms Curso de programacin de juegos La librera de UnSitioWeb - libUSW Pintar texto con GLetraUSW en OpenGL Temas interesantes en la programacin de juegos Libreras tiles para programar juegos Programas del creador de juegos Manuales varios sobre informtica Foro Descargas Enlaces Contctanos Colaborar (con PayPal) Para continuar con el trabajo de esta Web y poder pagar el hosting, viene bien l a ayuda que sea. Gracias a todos. Importe: PayPal secure payments. Ultimas descargas GLetraUSW.zip 19.Jan Clase que permite dibujar texto en OpenGL con mucha facilidad.Usa FreeType2.Para ver que hace y c... FTGL compilado para VC y DEV-C 10.May Librera Corona compilada para DEV-C++ 15.Apr

Nueva librera GLetraUSW Como usar GLetraUSW Clase para pintar texto en OpenGL La muerte del PC?

23. Linux. Programa bsico XWindows y OpenGL 22. Bounding volumes y reestructuracin Frustum Culling. Otro manual. Grata sorpresa con LINUX 21. GLSL. Carga de shaders GLM (OpenGL Mathematics) 20. Billboarding. Shader Maker

3. Empezamos con OpenGL Imprimir Correo electrnico Videojuegos - Curso de Programacin de juegos Escrito por Vicengetorix oglLa libreria grafica que vamos a usar es OpenGL. Ahora comenzamos a acostumbra rnos a su uso y entender como funciona. Ya explique porque usaremos OpenGL. Ahora una breve explicacion para aclarar alg un tema que suele ser confuso cuando se empieza con esta libreria grafica. Lo normal es pensar que hace falta bajarse unas librerias para programar con Ope nGL y un "run time" para ejecutar los programas hechos con ella. Con DirectX si hace falta y ocupa lo suyo; pero con OpenGL no hay "run time" y solo hacen falta dos pequeas librerias que vienen con los compiladores (en realidad solo haria fa lta una). En realidad el nucleo de OpenGL instalado en tu ordenador, esta en el driver gra fico de tu tarjera de video y es el fabricante de la misma quien la implementa p ara su hardware. La libreria que viene con el compilador es solo un interface pa ra usar las rutinas del fabricante, y este interface incluye un metodo para ampl iar el OpenGL para futuras mejoras de la libreria grafica (para usar OpenGL 1.0 se usa la misma libreria que para usar OpenGL 2.0) es lo que se llaman extension es. Bastante mas adelante las veremos. En resumen: no hace falta bajarse OpenGL de ningun sitio, y para hacer nuestro p rograma solo necesitaremos incluir "gl/gh.h" y "gl/glu.h" y aadir a nuestro proye cto las librerias opengl32.lib y glu32.lib. Para que nuestro programa funcione c onvendra tener bien instalado el driver de la tarjeta grafica, aunque al usar ca racteristicas basicas de OpenGL va a funcionar siempre ya que windows lo puede e jecutar por software (si usamos caracteristicas avanzadas propias de nuestro har dware de video y no tenemos los driver, fallara). Aunque este curso es eminentemente practico, no esta de mas la explicacion de al gunos conceptos basicos en programacion grafica. El buffer. No solo en graficos, sino en programacion general, es un espacio de m emoria reservado para almacenar algo. OpenGL usa varios bufferes. Los primeros y mas importantes son los que se usan p ara dibujar y el que se usa para presentar en pantalla. Se usa la tecnica de doble buffer (pueden ser mas). Entender esto es la base par a empezar a saber como trabaja un juego. Esto hay que entenderlo !. En la tecnica de boble buffer, dibujamos en un buffer que no es visible para que no se aprecie como se va haciendo nuestro dibujo y mientras presentamos el dibu jo anterior. Cuando hemos acabado de dibujar suicheamos (intercambiamos) un buff er por otro, y asi se presenta el dibujo instantaneamente. Despues seguimos dibu jando en siguiente fotograma (frame), pero esta vez lo estaremos haciendo en el otro buffer, el que ahora esta oculto (back buffer), mientras el jugador esta vi endo en pantalla el fotograma que hemos dibujado antes. Estos bufferes son de memoria de video (la de la tarjeta de video, no memoria RA M del PC). El sistema no mueve la informacion de un buffer a otro, si no que, ha ce que la tarjeta de video cambie el rango de memoria de video que se traspasa a

l monitor, y el rango de memoria en la que esta el back buffer (el que se presen ta en pantalla se llama front buffer). Ejemplo: Tenemos dos bufferes, el 1 y el 2 (por ejemplo). Que siempre van a ser el mismo trozo de memoria cada uno: Ahora el 1 es el back y el 2 es el front. En el 1 pintamos mientras se ve el 2 e n el monitor. Intercambamos bufferes (SwapBuffers(DevContex)) Ahora el 2 es el back y el 1 es el front. En el 2 pintamos mientras se ve el 1 e n el monitor con el dibujo anterior. Intercambamos bufferes (SwapBuffers(DevContex)) Ahora el 1 es el back y el 2 es el front. En el 1 pintamos mientras se ve el 2 e n el monitor. ... Por si hace falta la aclaracion, la animacion en un juego -y en una pelicula- se hace presentando un dibujo tras otro con pequeas variaciones en el mismo. Siempr e deben ser mas de 24 dibujos segundo para que el ojo no perciba el cambio y el movimiento sea suave. Otro buffer importante es el de profundidad o z-buffer, muuuuuy importante si pr etendemos hacer algo en 3D. En el se guarda la profundidad de cada pixel al pint arlo (distancia de lo que se pinta a la camara). Cuando se pinta de nuevo el mis mo pixel de pantalla (con otro objeto) se compara la profundidad de el ultimo co n la que estaba guardada de antes, si es mayor la nueva (esta mas lejos), no se pinta el pixel, y si es menor (esta mas cerca), se pinta el pixel del color nuev o en el buffer de dibujo (back buffer) y se pone la nueva profundidad -menor- en el buffer de profundidad. Hay mas bufferes como el de estarcido (stencil) o el de acumulacion pero de mome nto no nos hacen falta. Tras la explicacion, el codigo que creo que tiene suficientes comentarios para s eguirlo facilmente. En esta segunda version he puesto en funciones aparte la creacion de la ventana y la inicializacion de OpenGL. #pragma comment( lib, "openGL32.lib" ) // Estas directivas del preprocesador #pragma comment( lib, "glu32.lib" ) // le dicen a el enlazador (linker o // linkador o ...) que incluya estas // librerias. Esto se puede hacer en // la configuracion del proyecto en el // Visual C++ pero esto me parece mas // claro. #include <windows.h> #include <GL/gl.h> #include <GL/glu.h> // Fichero de inclusion para programas Windows // // // // // Los ficheros de inclusion de OpenGL. Estrictamente solo es necesario el primero. El segundo es de funciones utiles que se podrian hacer de otra manera. No nos vamos a complicar la vida y la usaremos.

HINSTANCE IdAplicacion; // Para guardar el identificador del programa HWND IdVentana; // Para guardar el identificador de la ventana HDC DevContex; // Device Context para conectar la ventana con OpenGL. HGLRC OGLrc; // Render Context para la ventana OpenGL.

int AnchoVentana = 600; int AltoVentana = 400;

// Lo que dice el nombre de la variable // Lo que dice el nombre de la variable

//-------------------------------------------------------------// Funcion para inicializar OpenGL. void IniciaGL() { // Definimos una estructura de tipo PIXELFORMATDESCRIPTOR para definir // las caracteristicas graficas que queremos usar (dentro de las que nos // permite el OpenGL de nuestra tarjeta de video) static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // Tamao de este descriptor 1, // Nmero de versin PFD_DRAW_TO_WINDOW | // El formato debe soportar ventana PFD_SUPPORT_OPENGL | // El formato debe soportar OpenGL PFD_DOUBLEBUFFER | // Debe soportar Doble Buffer PFD_TYPE_RGBA, // Tambin debe soportar RGBA 32, // Bits por pixels seleccionados 0,0,0,0,0,0, // Bits de color ignorados 0, // Sin buffer alpha 0, // Shift bit ignorado 0, // Buffer de acumulacin ignorado 0,0,0,0, // Bits de acumulacin ignorados 32, // Z-Buffer de 32 bits 0, // Sin buffer de pincel (Stencil) 0, // Sin buffer auxiliar PFD_MAIN_PLANE, // Layer de dibujo principal 0, // Reservado 0,0,0, // Layers de mscara ignorados }; // Estas funciones son las que hacen que la ventana acepte el modo grafico // que queremos dado el descriptor de pixel anterior. (en el que uno de // los parametros es que funcione con OpenGL). DevContex=GetDC(IdVentana); // Obtengo el "device context" de la ventana. int PixF=ChoosePixelFormat(DevContex,&pfd); // Busco un indice de una conbinacion // que coincida con mis especificaciones SetPixelFormat(DevContex,PixF,&pfd); // Pongo la ventana en el formato que quiero. Dos funciones de OpenGL por fin (aunque sean especificas de windows). OGLrc=wglCreateContext(DevContex); // Indico a OpenGL que la ventana esta disponible para el. wglMakeCurrent(DevContex,OGLrc); // Le digo a OpenGL que nuestra ventana es donde tiene // que dibujar a partir de ahora. A partir de ahora podemos considerar OpenGL inicializado. Aun nos queda decirle los parametros del modo en que dibujar, aunque eso se puede, y de hecho se hace continuamente, cambiar durante la ejecucion del programa. Ahora pondremos algunos parametros puramente de OpenGL de inicio. glClearDepth(1.0f); // Profundidad del buffer de profundidad. Hace que lo que esta // mas cerca se vea (dibuje) encima de lo que esta mas lejos. glDepthFunc(GL_LEQUAL); // Comparacion del buffer de profundidad.

//

// // // // //

glEnable(GL_DEPTH_TEST); // Habilita test de profundidad. A partir de ahora, lo que // esta mas cerca se pinta encima. glClearColor(0,0,0,1.0f); // Color del fondo. Color con el que se borra la pantalla, o la // ventana donde pintamos. Cuando usemos la funcion glClear. glShadeModel(GL_SMOOTH); // Renderizado suave. Cuanta mejor calidad mas lento. Nosotros // tenemos un ordenador reciente(+ o -) y queremos que se vea bien. glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST); // Calidad buena de perspectiva. glViewport(0,0,AnchoVentana,AltoVentana); // Le dice a OpenGL el tamao del lienzo en el que va a pintar en // pixels. Coincidira, en principio, con el tamao de nuestra ventana // y empezando por 0,0 (la esquina de nuestra ventana). glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // Borramos la ventana con el color antes establecido // (en realidad solo el backbuffer (la pantalla oculta // donde en realidad estamos pintando) // y borramos tambien el buffer de profundidad SwapBuffers(DevContex); // Le digo a nuestro espacio de dibujo que cambie "muy rapido" // el buffer de dibujo por el de visualizacion y viceversa // (suichear en Espanglish) } // Fin IniciaGL //-----------------------------------------------------------------// Funcion para controlar lo que ocurre en la ventana segun los eventos // que vienen de Windows. Mas tarde se asocia a la ventana que crearemos. // De momento solo interceptamos la tecla ESC para poder salir del // programa cuando queramos y el evento de destruccion de ventana con el // que terminamos la aplicacion LRESULT FAR PASCAL ProcesaMensajes(HWND Ventana, UINT Mensaje, WPARAM wParam, LPARAM lParam) { switch(Mensaje) // Segn el mensaje recibido { case WM_KEYDOWN: // Caso de mensaje de pulsacin de una tecla switch(wParam) // y segun el contenido de la variable wParam { case VK_ESCAPE: // ESC causa la salida del programa // Funcion para enviar mensaje de cerrado a la ventana // y despues de la aplicacion PostMessage(Ventana, WM_CLOSE, 0, 0); break; } break; case WM_DESTROY:// Mensaje de destruccin de la ventana (provocado por // nosotros al pulsar ESC o cerrar la ventana. PostQuitMessage(0); // Funcion para salir del programa break; } // Efectuar el proceso por defecto del mensaje (si viene cualquier mensaje // que no hemos usado, querremos que haga lo que suele hacer) return DefWindowProc(Ventana, Mensaje, wParam, lParam); } // fin ProcesaMansajes

//-----------------------------------------------------------------// Funcion para crear la ventana de nuestro programa, que asociaremos // al OpenGL para pintar en ella void CreaVentana() { WNDCLASS ClaseVentana; // Declaramos un tipo de ventana, el nuestro. //Definimos nuestro tipo de ventana... ClaseVentana.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Se redibujara si // cambia el tamao de la ventana horizontal y verticalmente, y // un solo DC (device context) para cada ventana (para cuando // empezemos con OpenGL) ClaseVentana.lpfnWndProc = ProcesaMensajes; // La definimos antes para contolar // los mansajes como los del teclado ClaseVentana.cbClsExtra = 0; //Sin memoria extra para la clase ClaseVentana.cbWndExtra = 0; //Sin memoria extra para la ventana ClaseVentana.hInstance = IdAplicacion; // Identificador del programa para asociar // esta ventana con este programa. ClaseVentana.hIcon = NULL; // De momento pasamos de icono ClaseVentana.hCursor = LoadCursor(NULL, IDC_ARROW); // Flecha normal de raton ClaseVentana.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // Por ahora lo ponemos blanco ClaseVentana.lpszMenuName = NULL; // Pasamos de menu ClaseVentana.lpszClassName = L"UnSitioWeb"; // Nombre de la clase (la "L" antes de la cadena es // por que solo admite cadenas de caracteres // unicode -LPCWSTR o TCHAR- y con la "L" se convierte). RegisterClass(&ClaseVentana); // Registramos nuestro tipo de ventana IdVentana = CreateWindowEx( // Funcion que crea la ventana. Guardamos el identificativo. WS_EX_APPWINDOW, // estilo extendido de ventana L"UnSitioWeb", // Nombre de la clase puesto antes (la "L" para UNICODE) L"Un Sitio Web", // Titulo que aparecera en la ventana. WS_POPUPWINDOW|WS_CAPTION|WS_MINIMIZEBOX, // Parametros de como sera la ventana // se pueden combinar varios. 100, // Posicion Horizontal. 100, // Posicion Vertical. AnchoVentana, // Ancho de la ventana. AltoVentana, // Alto de la ventana. (HWND) NULL, // No depende de otra ventana. (HMENU) NULL, // No le damos un menu diferente al de la clase(que es ninguno) IdAplicacion, // Identificador del programa al que pertenece la ventana. Al // empezar lo guardamos en una variable para usarlo despues. (LPVOID) NULL ); // Puntero a "no se que" datos (pasamos del tema, es para // aplicaciones MIDI).

ShowWindow(IdVentana, SW_SHOW); // Mostramos nuestra ventana. UpdateWindow(IdVentana); // La actualizo para que muestre lo que tenga que mostrar // (ahora nada) } // Fin CreaVentana //-----------------------------------------------------------------// Funcion principal de un programa Windows (como main en C normal, // aqui WinMain) el prorama empieza a ejecutarse a partir de esta funcion. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(lpszCmdLine); // Para que no moleste al compilar, no lo usamos. IdAplicacion = hInstance; // Guardo el identificador del programa, luego lo usamos. CreaVentana(); // Funcion que crea la ventana. Definida mas arriba. IniciaGL(); // Funcion para inicializar OpenGL. Definida mas arriba. // // // // // Este es el bucle habitual de windows que se esta ejecutando continuamente hasta que recibe el mensaje de acabar (ya lo hemos preparado en la funcion "ProcesaMensajes" asociada a la ventana, tambien asociada a este programa atraves de su identificativo) MSG Mensaje; // Varible para contener los mensajes que van llegando. while(TRUE) // Se ejecuta continuamente. { if(PeekMessage(&Mensaje, NULL, 0, 0, PM_NOREMOVE)) // Exploramos la cola de mensajes. {// procesndolos adecuadamente if(!GetMessage(&Mensaje, NULL, 0, 0)) return (int)Mensaje.wParam; // Terminamos. TranslateMessage(&Mensaje); DispatchMessage(&Mensaje); } else WaitMessage(); // en caso contrario esperamos un mensaje }

} // fin WinMain //-----------------------------------------------------------------Una ultima explicacion para los que investiguen por internet a cerca de programa cion OpenGL. Existe una libreria muy usada, y la mas habitual en los ejemplos de codigo, llamada glut que simplifica el tema del teclado, inicializacion y demas aspectos del programa base. Yo no la uso, tel vez por mania o por cabezoneria, pero prefiero gestionar yo mi smo estos temas ya que no me parece tan complicado, como habeis visto, y te da m ayor control sobre tu programa. En todo caso es una decision personal y el funci onamiento de OpenGL es el mismo en los dos casos. Suerte compilando.

+/ESCRIBIR COMENTARIO +/- COMENTARIOS A ?ADIR NUEVO BUSCAR

Banner Spanish Chinese (Simplified) English French German Japanese Portuguese Russian

Creative Commons License Esta Web est bajo licencia de Creative Commons Loading...

También podría gustarte