现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

windows下opengl(四):wxWidgets集成OpenGL

2014-10-30 22:40 工业·编程 ⁄ 共 5513字 ⁄ 字号 暂无评论

      通过前面3章,我们得到了一个只需要使用微软opengl32.lib和glew32.lib的用于开发OpenGL程序的基本框架。这个框架是基于win32 api的,这样的程序框架好处是它最为简单,只使用尽可能少的第三方库和尽可能少的封装,这样才容易搞明白真正的底层原理。

        但一旦开始编写实际有用的程序,我们总是会使用到各种各样的第三方库,对OpenGL来说,需要处理的最重要关系时与第三方界面库的关系。即如果我们使用MFC或者wxWidgets之类的界面库进行开发时,如何让OpenGL在这些界面库的窗口里绘图。

        其实如果前3章的代码仔细体会了,就明白这个问题很简单。对OpenGL来说,只要能得到HGLRC句柄,HGLRC句柄与哪个窗口绑定,OpenGL就在哪个窗口上绘图。

        所有windows平台上的第三方界面库,都最终用到了windows平台的窗体,有窗体就可以得到HWND,有HWND就可以得到HDC,有HDC就可以创建OpenGL环境,创建了环境就可以得到HGLRC,就可以绑定到HDC,OpenGL就可以在那个窗口上绘图。

       本章仅以wxWidgets为例验证该思路的可行性。

4.1 wxWidgets集成OpenGL

        虽然wxWidgets可以通过wxUSE_GLCANVAS=1使得编译出来的wxWidgets库支持OpenGL,但知道怎么样自己做到这点可以更灵活。

4.1.1 创建最简单的wxWidgets程序

        创建一个App模块,一个Frame模块,两个模块各一个.h文件和一个.cpp文件。wxWidgets版本用的是2.9.4,其它版本原理都是一样的。链接库除了wxWidgets库外,还需要opengl32.lib和glew32.lib。自行添加。

4.2各文件及其内容

4.2.1 aboutApp.h

#ifndef ABOUT_APP_H

#define ABOUT_APP_H

#include <wx/wx.h>

class aboutApp:public wxApp 

public: 

virtual bool OnInit(); 

}; 

#endif

4.2.2 aboutApp.cpp

        注意该文件中的OnInit函数中初始化OpenGL环境的内容。

#include "aboutApp.h"

#include "aboutFrame.h"

#include "wx/image.h"

#include <Windows.h>

#include <gl/glew.h>

#include <gl/wglew.h>

bool aboutApp::OnInit() 

    wxInitAllImageHandlers(); 

HWND         hWnd; 

    HGLRC        hRC; 

HDC          hDC; 

    wxFrame * nullFrame = new wxFrame(NULL,wxID_ANY,wxT("null")); 

    hWnd = nullFrame->GetHWND(); 

    hDC = GetDC(hWnd); 

    PIXELFORMATDESCRIPTOR pfd; 

    SetPixelFormat( hDC, 1,&pfd); 

    hRC = wglCreateContext( hDC ); 

    wglMakeCurrent( hDC, hRC ); 

//一旦wgl被初始化,可以撤消相关环境

//之后可以利用wgl函数,调用最新版的OpenGL建立真正使用的环境

    GLenum ret = glewInit(); 

if (GLEW_OK != ret) 

    { 

//MessageBox(NULL,(LPCSTR)glewGetErrorString(ret),TEXT("glew初始化"),MB_OK);

        MessageBox(NULL,TEXT("OnInit()glewInit错误"),TEXT("glew初始化"),MB_OK); 

    } 

//释放OpenGL环境,wgl函数已经在调用glewInit()时完成了初始化

//释放环境后仍然可以使用

    wglMakeCurrent(NULL, NULL); 

    wglDeleteContext(hRC); 

    ReleaseDC(hWnd, hDC); 

    hWnd = 0; 

    nullFrame->Destroy(); 

    aboutFrame * paf = new aboutFrame(_("about")); 

    hWnd = paf->GetHWND(); 

    hDC = GetDC(hWnd); 

int nPixCount = 0; 

//利用OpenGL查询函数查找最符合要求的OpenGL环境特性

//需要#include <gl/wglew.h>

int pixAttribs[] = { WGL_SUPPORT_OPENGL_ARB, GL_TRUE,  //要求支持OpenGL

        WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,                   //可以绘制到某个窗口

        WGL_ACCELERATION_ARB,   WGL_FULL_ACCELERATION_ARB, //必须完全支持硬件加速

        WGL_RED_BITS_ARB,       8,                         //红色为8位精度

        WGL_GREEN_BITS_ARB,     8,                         //绿色为8位精度

        WGL_BLUE_BITS_ARB,      8,                         //蓝色为8位精度

        WGL_DEPTH_BITS_ARB,     16,                        //深度为16位精度

        WGL_PIXEL_TYPE_ARB,      WGL_TYPE_RGBA_ARB,        //使用RGBA类型的像素

        0};                                                //必须以0结尾

int nPixelFormat  = -1; 

//查询系统中是否存在满足要求的环境像素格式

    wglChoosePixelFormatARB(hDC, &pixAttribs[0], NULL, 1, &nPixelFormat, (UINT*)&nPixCount); 

if(nPixelFormat == -1)  

    { 

//不存在满足要求的环境,则释放数据,结束程序

        ReleaseDC(hWnd, hDC); 

        DestroyWindow(hWnd); 

        MessageBox(NULL,TEXT("OpenGL不支持查询的格式"),TEXT("错误"),MB_OK); 

return 1; 

    } 

else

    { 

//找到满足要求的格式,则设置其为当前像素格式,并创建OpenGL环境

        SetPixelFormat( hDC, nPixelFormat, &pfd ); 

//指定OpenGL版本为3.10

        GLint attribs[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, 3,WGL_CONTEXT_MINOR_VERSION_ARB,  1,  0 }; 

        hRC = wglCreateContextAttribsARB(hDC, 0, attribs); 

if (hRC == NULL) 

        { 

            MessageBox(NULL,TEXT("无法创建OpenGL环境"),TEXT("错误"),MB_OK);      

return false; 

        } 

//成功则绑定OpenGL渲染环境(hRC)至窗口设备环境(hDC)

        wglMakeCurrent( hDC, hRC ); 

    } 

    paf->Show(true); 

return true; 

IMPLEMENT_APP(aboutApp); 

DECLARE_APP(aboutApp); 

4.2.3 aboutFrame.h

#ifndef ABOUT_FRAME_H

#define ABOUT_FRAME_H

#include <wx/wx.h>

class aboutFrame: public wxFrame 

public: 

    aboutFrame(const wxString & title); 

void OnAbout(wxCommandEvent & event); 

void OnExit(wxCommandEvent & event); 

void OnPaint(wxPaintEvent& event); 

private: 

    DECLARE_EVENT_TABLE() 

}; 

#endif

4.2.4 aboutFrame.cpp

        在OnPaint函数中用旧风格编写了一段显示三角形的代码。

#include "aboutFrame.h"

#include <wx/wxhtml.h>

#include <GL/glew.h>

aboutFrame::aboutFrame(const wxString & title) 

    :wxFrame(NULL,wxID_ANY,title) 

//SetIcon(wxICON(sample));

    wxMenuBar * menubar = new wxMenuBar(); 

    wxMenu * menu = new wxMenu(); 

    menu->Append(wxID_ABOUT,wxT("关于")); 

    menu->Append(wxID_EXIT,wxT("退出")); 

    menubar->Append(menu,wxT("文件")); 

    SetMenuBar(menubar); 

void aboutFrame::OnAbout(wxCommandEvent & event) 

    wxBoxSizer *topsizer; 

    wxHtmlWindow *html; 

    wxDialog dlg(this, wxID_ANY, wxString(_("About"))); 

    topsizer = new wxBoxSizer(wxVERTICAL); 

    html = new wxHtmlWindow(&dlg, wxID_ANY, wxDefaultPosition, wxSize(380, 160), wxHW_SCROLLBAR_NEVER); 

    html -> SetBorders(0); 

    html -> LoadPage(wxT("data/about.htm")); 

    html -> SetSize(html -> GetInternalRepresentation() -> GetWidth(), 

                    html -> GetInternalRepresentation() -> GetHeight()); 

    topsizer -> Add(html, 1, wxALL, 10); 

    wxButton *bu1 = new wxButton(&dlg, wxID_OK, _("OK")); 

    bu1 -> SetDefault(); 

    topsizer -> Add(bu1, 0, wxALL | wxALIGN_RIGHT, 15); 

    dlg.SetSizer(topsizer); 

    topsizer -> Fit(&dlg); 

    dlg.ShowModal(); 

void aboutFrame::OnExit(wxCommandEvent & event) 

    Close(true); 

void aboutFrame::OnPaint(wxPaintEvent& event) 

    glClearColor(1.0f,1.0f,1.0f,1.0f); 

    glClear(GL_COLOR_BUFFER_BIT); 

    glColor3f(1.0,0.0,0.0); 

    glBegin(GL_TRIANGLES); 

    glVertex2f(-1.0,0.0); 

    glVertex2f(1.0,0.0); 

    glVertex2f(0.0,1.0); 

    glVertex2f(-0.7,0.5); 

    glVertex2f(-0.9,-0.1); 

    glEnd(); 

    glBegin(GL_TRIANGLES); 

    glVertex2f(0.5,0.8); 

    glEnd(); 

    glFlush(); 

BEGIN_EVENT_TABLE(aboutFrame,wxFrame) 

EVT_MENU(wxID_ABOUT, aboutFrame::OnAbout) 

EVT_MENU(wxID_EXIT, aboutFrame::OnExit) 

EVT_PAINT(aboutFrame::OnPaint) 

END_EVENT_TABLE() 

4.3 运行结果

图4-1集成OpenGL的wxFrame

给我留言

留言无头像?