wxWidgets中OpenGL渲染環境的配置,主要解決不能顯示物體陰影問題

在使用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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章