OpenGL y wxWidgets

Gráficos OpenGL en ventanas wxWidgets

Logos de wxWidgets y OpenGL

Ya tenemos un tutorial de cómo utilizar OpenGL utilizando la librería GLUT. Dicha librería la utilizamos para crear una ventana para dibujar en OpenGL.

Esta ventana es una ventana del tipo “consola”, donde no podemos poner botones, menús, o componentes visuales.

En este pequeño artículo básicamente voy a indicar como utilizar OpenGL con Widgets, no será ningún tutorial o curso de OpenGL.

Básicamente tenemos que crear nuestra clase lienzo que es donde se dibujará la escena. Todas las instrucciones de OpenGL se utilizarán en esta clase.

Esta clase deriva de la clase wxGLCanvas.

Como vemos en la herencia deriva de la clase wxWindow, podemos capturar todos los eventos de dicha clase, EVT_PAINT, EVT_KEY_DOWN, EVT_SIZE, etc.

Vamos a implementar una aplicación con un menú principal con 2 opciones, Dibuja y No Dibuja.

La opción Dibuja, dibujara una escena formada por rectángulo con un triángulo invertido y la opción No Dibuja, no dibujará ninguna escena.

Ventana principal de la aplicación

Como habíamos comentado anteriormente, lo primero que haremos será crearnos nuestra clase lienzo (CCanvasGL) que deriva de wxGLCanvas.

En esta clase a través de la función dibujarEscena indicamos si se dibuja la escena o no.

La función dibuja, dibujará o no la escena, según se lo hayamos indicado a través de la función dibujarEscena.

En dicha clase crearemos una variable miembro (mpContext) que se utilizará para instanciar el contexto (wxGLContex).

// CCanvasGL.h
class CCanvasGL : public wxGLCanvas

private:
    wxGLContext *mpContext;

En el constructor de nuestra clase debemos de definir un identificador de nuestra ventana (ID_CANVAS_OPEN_GL). Este identificador se encuentra en el fichero ident.h del proyecto.

Este identificador es el que se utilizará en nuestra aplicación (wxFrame) para obtener nuestro lienzo.

También instanciamos el contexto.

// CCanvasGL.cpp
CCanvasGL::CCanvasGL(wxFrame* parent, int* args):
	   wxGLCanvas(parent, ID_CANVAS_OPEN_GL, args, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE)
{
 mpContext = new wxGLContext(this);

Nuestra clase capturará el evento EVT_PAINT, a través de la función OnPaint. En dicha función se dibujara la escena.

void CCanvasGL::OnPaint(wxPaintEvent& WXUNUSED(pEvento))
{
 wxGLCanvas::SetCurrent(*mpContext);
 wxPaintDC(this);
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

 glViewport(0, 0, (GLint)GetSize().x, (GLint)GetSize().y);

 dibuja();

 glFlush();
 SwapBuffers();
}

Tenemos que crear nuestra clase frame (CMyFrame), que deriva de wxFrame. En dicha clase crearemos el menú y sus opciones.

La función onDibujaClick capturará el evento de ítem de menú Dibuja y la función onNoDibujaClick capturará el evento del ítem de menú No Dibuja.

Estas funciones obtendrán CCanvasGL a través de la función wxWindow::FindWindow, pasándole el ID de la ventana ID_CANVAS_OPEN_GL (ident.h).

Indicaremos si queremos dibujar la escena a través de la función dibujarEscena pasando el valor true, o no queremos dibujar la escena pasando el valor false.

// CMyFrame.cpp
void CMyFrame::onDibujaClick(wxCommandEvent& event)
{
 CCanvasGL *lpCanvasOpenGL;

 lpCanvasOpenGL=nullptr;
 // voy a buscar el canvas
 lpCanvasOpenGL=(CCanvasGL *)wxWindow::FindWindow(ID_CANVAS_OPEN_GL);
 // Indico que se dibujo la escena
 lpCanvasOpenGL->dibujarEscena(true);
 // Refresco la ventana, por lo que lanzo el evento EVT_PAINT
 Refresh(false,NULL);
}

void CMyFrame::onNoDibujaClick(wxCommandEvent& event)
{
 CCanvasGL *lpCanvasOpenGL;

 lpCanvasOpenGL=nullptr;
 // Busco el canvas
 lpCanvasOpenGL=(CCanvasGL *)wxWindow::FindWindow(ID_CANVAS_OPEN_GL);
 //  Indico que se dibujo la escena
 lpCanvasOpenGL->dibujarEscena(false);

 Refresh(false,NULL);
}

Por último en nuestra clase appOpenGL, en la función onInit es donde lo uniremos todo.

Instanciamos nuestra clase CMyFrame:

frame=new CMyFrame((wxFrame *)NULL, -1,  TXT_TITULO_APP, wxPoint(50,50), wxSize(400,200));

Instanciamos nuestro lienzo CCanvasGL:

int args[] = {WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 16, 0};
lpMiOpenGL=new CCanvasGL((wxFrame*) frame,args);

El array args, contiene los parámetros de configuración de OpenGL.

Nuestro lienzo lo añadimos en un wxSizer.

sizer->Add(lpMiOpenGL,1, wxEXPAND);

El sizer lo añadimos a nuestro frame:

frame->SetSizer(sizer,true);
frame->SetAutoLayout(true);

Por último mostramos nuestro frame:

frame->Show(true);

Cuando pulsemos la opción dibuja, dibujará un rectángulo con un triángulo invertido.

Dibujo openGL

Configuración del proyecto

Primero indicamos donde tenemos el compilador.

En propiedades del proyecto(Project->Properties) en C/C++Build->Enviorement.

Propiedades de proyecto

La variable MINGW_HOME deberá apuntar a la ubicación de nuestro compilador.

Variable de compilador

Debemos indicar donde tenemos la instalación de wxWidgets para los includes.

Carpeta de ficheros include

En mi caso wxWidgets lo tengo instalado [INSTALACION_WIDGETS] en D:\Lenguajes\wxWidgets\wxWidgets-3.2.5.

INSTALACION_WIDGETS\lib\gcc_lib32_4_8_1\mswu
INSTALACION_WIDGETS\include

Para utilizar OpenGL necesitamos las librerías:

lwxmsw31u_gl.
opengl32.
glu32.

Por último debemos indicar donde tenemos la instalación de wxWidgets para las librerias.

Librerias wxWidgets

En mi caso:

INSTALACION_WIDGETS\lib\gcc_lib64

Referencias

https://conclase.net/winapi/wxwidgets/wxGL/wxGLCanvas.

https://wiki.wxwidgets.org/WxGLCanvas.

Ejemplo

Nombre Fichero Fecha Tamaño Contador Descarga
Ejemplo OpenGL wxWidgets proyecto.zip 2025-10-15 9904 bytes 3