在使用wxWidgets图形库之前,一直在使用GLUT库来为OpenGL程序提供图形界面,但其毕竟只能算是一个中间过渡,想要有更完整的图形的库,那么选择之一便是wxWidgets库。
目前本人所使用的wxWidgets版本号是"wxWidgets-3.0.2",想要有使用其它版本,请参考官网。
下面主要分享一下在wxCanvas中如何设置OpenGL渲染上下文,解决物体阴影不能显示的问题,给出一个wxGLCanvas初始化的例子。
直接上代码:
1.头文件main.h
#include "wx/wx.h" #include "wx/glcanvas.h" class BasicGLPane : public wxGLCanvas { wxGLContext* m_context; public: BasicGLPane(wxFrame* parent, int* args); virtual ~BasicGLPane(); void resized(wxSizeEvent& evt); int getWidth(); int getHeight(); void render(wxPaintEvent& evt); void prepare3DViewport(int topleft_x, int topleft_y, int bottomrigth_x, int bottomrigth_y); // events void mouseMoved(wxMouseEvent& event); void mouseDown(wxMouseEvent& event); void mouseWheelMoved(wxMouseEvent& event); void mouseReleased(wxMouseEvent& event); void rightClick(wxMouseEvent& event); void mouseLeftWindow(wxMouseEvent& event); void keyPressed(wxKeyEvent& event); void keyReleased(wxKeyEvent& event); DECLARE_EVENT_TABLE() }; #endif
#include <gl\glew.h> #include "wx/wx.h" #include "wx/sizer.h" #include "wx/glcanvas.h" #include "main.h" #include "shadowGenerator.h" // include OpenGL #ifdef __WXMAC__ #include "OpenGL/glu.h" #include "OpenGL/gl.h" #else #include <GL/glu.h> #include <GL/gl.h> #endif class MyApp : public wxApp { virtual bool OnInit(); wxFrame *frame; BasicGLPane * glPane; public: }; IMPLEMENT_APP(MyApp) bool MyApp::OnInit() { //wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL); frame = new wxFrame((wxFrame *)NULL, -1, wxT("Hello GL World"), wxPoint(50, 50), wxSize(400, 400)); <span style="color:#000099;"><span style="white-space:pre"> </span>//很重要的一个参数集,下面正文会有讲到 int args[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 32, 0 }; </span> glPane = new BasicGLPane((wxFrame*)frame, args); //sizer->Add(glPane, 1, wxEXPAND); //frame->SetSizer(sizer); //frame->SetAutoLayout(true); frame->Show(); InitGLObjects(); return true; } BEGIN_EVENT_TABLE(BasicGLPane, wxGLCanvas) EVT_MOTION(BasicGLPane::mouseMoved) EVT_LEFT_DOWN(BasicGLPane::mouseDown) EVT_LEFT_UP(BasicGLPane::mouseReleased) EVT_RIGHT_DOWN(BasicGLPane::rightClick) EVT_LEAVE_WINDOW(BasicGLPane::mouseLeftWindow) EVT_SIZE(BasicGLPane::resized) EVT_KEY_DOWN(BasicGLPane::keyPressed) EVT_KEY_UP(BasicGLPane::keyReleased) EVT_MOUSEWHEEL(BasicGLPane::mouseWheelMoved) EVT_PAINT(BasicGLPane::render) END_EVENT_TABLE() // some useful events to use void BasicGLPane::mouseMoved(wxMouseEvent& event) {} void BasicGLPane::mouseDown(wxMouseEvent& event) {} void BasicGLPane::mouseWheelMoved(wxMouseEvent& event) {} void BasicGLPane::mouseReleased(wxMouseEvent& event) {} void BasicGLPane::rightClick(wxMouseEvent& event) {} void BasicGLPane::mouseLeftWindow(wxMouseEvent& event) {} void BasicGLPane::keyPressed(wxKeyEvent& event) {} void BasicGLPane::keyReleased(wxKeyEvent& event) {} BasicGLPane::BasicGLPane(wxFrame* parent, int* args) : wxGLCanvas(parent, wxID_ANY, args, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE) {
m_context = new wxGLContext(this); // To avoid flashing on MSW
<span style="color:#000099;"><span style="white-space: pre;"> </span>//原文上设置为,wxBG_STYLE_CUSTOM,但是在这个版本中,已声明为predicated,请使用wxBG_STYLE_PAIT </span> SetBackgroundStyle(wxBG_STYLE_PAINT);
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>//SetCurrent( ),默许设置,还是算了。 SetCurrent(*m_context); if (glewInit() != GLEW_OK) { int i = 0; } } BasicGLPane::~BasicGLPane() { delete m_context; } void BasicGLPane::resized(wxSizeEvent& evt) { wxGLCanvas::OnSize(evt); //if (getHeight()== 0) //h = 1; glViewport(0.0, 0.0, getWidth(), getHeight()); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, (GLdouble)getWidth() / getHeight(), 0.01f, 100.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0f, 0.0, 10.0f, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0f); //Refresh(); //取消注释,则在本人电脑上会出现闪烁的问题 } /** Inits the OpenGL viewport for drawing in 3D. */ void BasicGLPane::prepare3DViewport(int topleft_x, int topleft_y, int bottomrigth_x, int bottomrigth_y) { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Black Background glClearDepth(1.0f); // Depth Buffer Setup glEnable(GL_DEPTH_TEST); // Enables Depth Testing glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //glEnable(GL_COLOR_MATERIAL); glViewport(topleft_x, topleft_y, bottomrigth_x - topleft_x, bottomrigth_y - topleft_y); glMatrixMode(GL_PROJECTION); glLoadIdentity(); float ratio_w_h = (float)(bottomrigth_x - topleft_x) / (float)(bottomrigth_y - topleft_y); gluPerspective(45 /*view angle*/, ratio_w_h, 0.1 /*clip close*/, 100 /*clip far*/); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } int BasicGLPane::getWidth() { return GetSize().x; } int BasicGLPane::getHeight() { return GetSize().y; } void BasicGLPane::render(wxPaintEvent& evt) { if (!IsShown()) return; wxGLCanvas::SetCurrent(*m_context); wxPaintDC(this); // only to be used in paint events. use wxClientDC to paint outside the paint event glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // ------------- draw some 3D ---------------- prepare3DViewport(getWidth() / 2, 0, getWidth(), getHeight()); glLoadIdentity();
<span style="white-space:pre"> </span>//to draw something
SwapBuffers(); }程序中遇到的问题:
1、一开始想在wxWigets中也用GLUT来显示设备、显示模式等。
结论:愚拙的想法,外来人(GLUT)想来套近乎?只是“我”太高冷。
2、采用wxGLCanvas默认的上下文设置,即使用SetCurrent(),而非SetCurrent(*m_context)。
结论:SetCurrent():我不想梳妆打扮就去相亲。等我,Shadow。
Shadow: 你太不符合我的胃口了,我也是有节操的,我是不会跟你一起的出现的。
SetCurrent():真任性。我回去重新包装一下,看你还傲娇不。
3、定义一个窗体参数集 int args[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 16 /*32*/, 0 };完成自定义风格的绘制设置。
结论:SetCurrent():Hi,Shadow我又来了,这次怎么样?
Shadow: 你就想用16(深度缓冲精度)分的妆容来见我?
SetCurrent():你还想我怎样?就配你还不够?
Shadow: 就我吧,起码你得32分才可以。。(事实上,24就可以,毕竟傲娇嘛。)
SetCurrent():我也是有原则的,最多24,给你,爱要不要。
Shadow: 来吧,我们结婚吧。!!
小注:深度缓存的位数是衡量深度缓存精度的参数。深度缓存位数越高,则精确度越高,目前的显卡一般都可支持16位的Z Buffer,一些高级的显卡已经可以支持32位的Z Buffer,但一般用24位Z Buffer就已经足够了。更加详细说明,请查 阅Z-BUFFER相关内容。