Hola Complicado Mundo OpenGL-Win32

PREPARAR LA VENTANA Y LIGARLA A OPENGL

Ahora es necesario:


GLuint  PixelFormat;

static	PIXELFORMATDESCRIPTOR pfd=
{
	sizeof(PIXELFORMATDESCRIPTOR),
	1,
	PFD_DRAW_TO_WINDOW |PFD_SUPPORT_OPENGL |PFD_DOUBLEBUFFER,			PFD_TYPE_RGBA,
	32,
	0, 0, 0, 0, 0, 0,
	0,
	0,
	0,
	0, 0, 0, 0,
	32,
	0,
	0,
	0,
	0,
	0, 0, 0
};

hdc=GetDC(hWnd);
PixelFormat=ChoosePixelFormat(hdc,&pfd);
SetPixelFormat(hdc,PixelFormat,&pfd);
hglrc=wglCreateContext(hdc);
wglMakeCurrent(hdc,hglrc);

El PIXELFORMATDESCRIPTOR tiene los siguientes datos:

PIXELFORMATDESCRIPTOR {
WORD nSize : Tamaño de la estructura
WORD nVersion : Versión de la estructura, siempre es 1
DWORD dwFlags : Propiedades del buffer de píxeles, en este caso dibujar sobre una ventana (PFD_DRAW_TO_WINDOW), soporte a OpenGL (PFD_SUPPORT_OPENGL) y doble buffer (PFD_DOUBLEBUFFER)
BYTE iPixelType : La forma de describir los píxeles, en este caso como RGBA (PFD_TYPE_RGBA)
BYTE cColorBits : Tamaño de un píxel individual en bits, en este caso 32 que es el mas común
BYTE cRedBits : Ignorado
BYTE cRedShift : Ignorado
BYTE cGreenBits : Ignorado
BYTE cGreenShift : Ignorado
BYTE cBlueBits : Ignorado
BYTE cBlueShift : Ignorado
BYTE cAlphaBits : Ignorado
BYTE cAlphaShift : Ignorado
BYTE cAccumBits : Ignorado
BYTE cAccumRedBits : Ignorado
BYTE cAccumGreenBits : Ignorado
BYTE cAccumBlueBits : Ignorado
BYTE cAccumAlphaBits : Ignorado
BYTE cDepthBits : Bits para el buffer de profundidad, pueden ser 16 o 32 como en este caso.
BYTE cStencilBits : Ignorado
BYTE cAuxBuffers : Ignorado
BYTE iLayerType : Ignorado
BYTE bReserved : Ignorado
DWORD dwLayerMask : Ignorado
DWORD dwVisibleMask : Ignorado
DWORD dwDamageMask : Ignorado
}

GetDC() obtiene el Device Context asociado a la ventana identificada por hWnd.

ChoosePixelFormat() utiliza dos parámetros, el hdc sobre el cual se buscara un formato de píxeles compatible y el pfd que especifica el formato deseado por la aplicación. Esta función devuelve el formato de píxeles mas cercano encontrado, con respecto al pfd.

SetPixelFormat() utilizar tres parámetros, el hdc sobre el cual se va a establecer el formato de píxeles, un entero, el PixelFormat, donde esta guardado el índice a dicho formato de píxeles y el pfd de referencia que se uso para encontrar el formato, el ultimo valor no afecta el funcionamiento de esta función, ya que se utiliza solamente como registro.

wglCreateContext() crea un contexto de dibujo para OpenGL, a partir de un contexto de dibujo de GDI.

wglMakeCurrent() elige un HGLRC sobre el cual se va a dibujar los OpenGL, esto es debido a que una aplicación puede tener varios contextos de dibujo, pero solo puede operar un proceso sobre un contexto a la vez.

INICIALIZAR OPENGL
La inicialización de OpenGL es en este caso bastante simple y más bien utilitaria, es realizada por las siguientes líneas de código:

glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glMatrixMode (GL_PROJECTION);
glViewport (0, 0, VENTANA_ANCHO , VENTANA_ALTO);
gluPerspective(45.0f,VENTANA_ANCHO/VENTANA_ALTO,0.1f,100.0f);
gluLookAt( 0,0,16,  0,0,0, 0,1,0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();

glClearColor() establece el color de fondo
glMatrixMode() escoge una matriz para operar sobre ella. Primero se elige la de proyección (GL_PROJECTION)
glViewport() establece el tamaño del marco de dibujo de OpenGL
gluPerspective() establece el frustrum, en este caso apertura de 45, aspecto de 640/480, plano mas visible a 0.1 de distancia y mas lejano a 100.
gluLookAt() posiciona la “cámara” (en realidad hace transformaciones sobre la matriz proyección. Los parámetros están agrupado de a 3 (x, y, z) y representan la posición de la camara, el punto al que mira y que vector es considerado “hacia arriba”

Finalmente se vuelve al modo de matriz GL_MODELVIEW que es el utilizado para dibujar las primitivas.

HACER EL CICLO DE MENSAJES Y DIBUJADO

El ciclo de mensajes se encarga de revisar constantemente los mensajes, en busca de alguno de interés para la aplicación, de no haber mensajes, se dibuja la escena de OpenGL. El código es así:

MSG		mensaje;
BOOL	continuar=TRUE;

while(continuar)
	{
		if (PeekMessage(&mensaje,NULL,0,0,PM_REMOVE))
		{
			if (mensaje.message==WM_QUIT)
			{
				continuar=FALSE;
			}
			else
			{
				TranslateMessage(&mensaje);
				DispatchMessage(&mensaje);
			}
		}
		else
		{
				render();
				SwapBuffers(hdc);
		}
	}

La variable continuar indica cuando el ciclo debe detenerse, cuando el usuario o el sistema decidan cerrar la aplicación, bien sea con la X sobre la barra de la ventana, con el método abreviado, mediante el administrador de aplicaciones, etc. En algunos ejemplos se obvia esta variable al hacer un ciclo while(1) y utilizando un break; en caso de recibir el mensaje.

PeekMessage() busca y almacena un mensaje de la pila de mensajes de la aplicación. Si tal mensaje existe lo almacena en el primer parámetro y devuelve TRUE, de lo contrario devuelve FALSE. El ultimo parámetro (PM_REMOVE) le indica a la función al leer un mensaje debe borrarlo de la pila de mensajes.

En este caso solo estamos observando el mensaje WM_QUIT, que indica que el WndProc llamo la función PostQuitMessage(), es decir que intercepto algún mensaje de salida de la aplicación.

Si no es este mensaje, se vuelve a colocar en la pila de mensajes mediante las funciones TranslateMessage() y DispatchMessage, para que este pueda ser leído por el wndProc() creado anteriormente o por el manejador de mensajes por defecto (DefWindowProc()).

Finalmente si no hay ningún mensaje por leer en la pila de mensajes, se hace el dibujado(render()) y se cambia de buffer (SwapBuffers()). El código del render() es bastante simple y pinta un triangulo

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glBegin(GL_TRIANGLES);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(3.0f,-2.0f,0.0f);
glVertex3f(0.0f,1.0f,0.0f);
glVertex3f(-3.0f,-2.0f,0.0f);
glEnd();

glClear() limpia los buffers pasados como parámetro de acuerdo al color de limpiado (negro) y entre las funciones glBegin() y glEnd() esta la especificación de un triangulo de color azul.

1 2 3 4

Compartir esta entrada

DiggReddit
  • http://http.//dedolog.blogspot.com Debor

    Está chido pero no lo leí todo llevo prisa, pero si cae mal que pasen por tu log y no comenten 😉

  • http://dedolog.blogspot.com Debor

    Por cierto ando programando en luinux pero quiero exportar a win32 o 64 espero poder

  • Martin_395

    Muy completo y interesante, pero lleva tiempo entender todo(menos mal que soy joven y tengo tiempo).
    Gracias por el tutorial.

  • miguel365

    :O interesante, muy completo el post, desde hace tiempo he querido escribir una aplicacion sencilla de opengl pero que me permita manejar botones, menus etc. pero no encuentro un manual. Sabes si puedo preparar el contexto de opengl utlizando un picturebox de windows forms? agradezco tu respuesta por favor.