您的位置:首页 > 运维架构

wxWidgets中OpenGL渲染环境的配置,主要解决不能显示物体阴影问题

2015-05-12 13:01 495 查看
在使用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

2.cpp文件main.cpp
#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相关内容。

最后,基本上自己所用到的所有绘制功能都可以在这种配置上正确运行,但请不要忘了glewInit()的初始化,这个是必不可少的。
大家若是有其他更高的需求,请参考他人的文章。

PS:上面用到的代码示例,摘取自https://wiki.wxwidgets.org/WxGLCanvas。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  opengl 图形 3d 界面
相关文章推荐