OpenGL4.x学习之搭建基于Qt和OpenGL4.x的框架
OpenGL是一套充满活力的跨平台的渲染API。在2004年前,其不过是刚迈入了2.0版本,那时候Direct3D成为游戏开发者们最青睐的开发框架,HLSL已经被一些游戏所使用,而OpenGL才刚刚支持顶点着色器和片断着色器,人们都为此而感到担心——究竟OpenGL还有没有希望?OpenGL的出路到底在哪里?幸运的是随后的几年,OpenGL在khronos组织和其它巨头的推动下取得了长足的发展,版本很快迈向了3.0甚至是4.0。2012年OpenGL4.3发布,NVIDIA等厂商随即发布了支持它的驱动程序,当时我认为4.3应该是OpenGL的一个巅峰,不会频繁地更新了吧。就在去年,也就是2013年,OpenGL4.4发布,让我们知道了OpenGL仍然富有活力,不断前进。相比OpenGL的蓬勃迈进,Direct3D的步伐明显慢了许多。从Direct3D11随着Windows7的发布已经有了近5年,它的继任者却迟迟难产。即使Direct3D9有着大量的拥趸,对于一个刚入门的开发者来说,是跟还是不跟?我想大家心里都有自己的一杆秤。
原创文章,反对未声明的引用。原博客地址:http://blog.csdn.net/gamesdev/article/details/18995825
我想OpenGL和同样是优秀的跨平台图形API——Qt的结合应该是一件非常有趣的事儿吧。有关Qt的介绍我已有大量的篇幅描述,有兴趣的搜搜我以前写的日志吧。OpenGL和Qt结合使用,简单快捷见效快。如果一定要说有什么缺点,我想应该是Qt的个头稍大并且可能对纯C的开发者并不友好,毕竟Qt是C++的开发框架。题外说一句,如果实在不喜欢Qt+OpenGL这一组合,那么使用wxWidgets+OpenGL也是可以的,我最近发现博客专栏里多出了介绍wxWidgets的专栏,有兴趣的话可以搜搜看。
一个简单的OpenGL4.x框架,从我写的QWindow的子类:GLWindow开始说起。下面是类的声明:
class GLWindow: public QWindow,
protected QOpenGLFunctions_4_3_Core
{
Q_OBJECT
public:
GLWindow( QWindow* pParent = Q_NULLPTR );
protected:
void exposeEvent( QExposeEvent* pEvent );
void InitGL( void ); // 额外OpenGL的初始化
void RenderGL( void ); // OpenGL渲染相关
void ResizeGL( int width, int height ); // 窗口大小改变时该如何应对
private:
QOpenGLContext* m_pContext;
};
Qt5.1以后,为了方便,添加了QOpenGLFunctions_x_y_z这样形式的类。这样好处是可以保证编译器这些函数的原型都能被找到而不至于出现编译错误。要是能够运行,还是的找能够支持该规范的显卡吧。这里重载了exposeEvent()函数以便进行初始化OpenGL渲染上下文m_pContext和进行实际的渲染。我们关注的则是InitGL()、RenderGL()和ResizeGL()这三个函数。以后部分我主要在这三个函数中做文章,以后可能还会添加ReleaseGL()这样释放内存的函数。
下面是GLWindow成员函数实现的前半部分:
/*---------------------------------------------------------------------------*/
GLWindow::GLWindow( QWindow* pParent ):
QWindow( pParent ),
m_pContext( Q_NULLPTR )
{
setSurfaceType( OpenGLSurface );
resize( 640, 360 );
}
/*---------------------------------------------------------------------------*/
void GLWindow::exposeEvent( QExposeEvent* pEvent )
{
Q_UNUSED( pEvent );
if ( m_pContext == Q_NULLPTR )
{
QSurfaceFormat format;
format.setVersion( 4, 3 ); // 需要OpenGL4.3版本
format.setSamples( 4 ); // 四倍采样
m_pContext = new QOpenGLContext( this );
m_pContext->setFormat( format );
m_pContext->create( );
m_pContext->makeCurrent( this );
initializeOpenGLFunctions( );
InitGL( );
}
ResizeGL( width( ), height( ) );
RenderGL( );
m_pContext->swapBuffers( this );
}
这里我们看到,通过QSurfaceFormat、QOpenGLContext等类,我们初始化好了OpenGL的环境。相关的函数参见Qt文档,这里为了能正确地解析OpenGL4.4的函数指针,需要调用initializeOpenGLFunctions()这个函数。
下面就是GLWindow实现的剩余部分:
/*---------------------------------------------------------------------------*/
void GLWindow::InitGL( void )
{
}
/*---------------------------------------------------------------------------*/
void GLWindow::ResizeGL( int width, int height )
{
Q_UNUSED( width );
Q_UNUSED( height );
}
/*---------------------------------------------------------------------------*/
void GLWindow::RenderGL( void )
{
static const GLfloat red[] = { 1.0f, 0.0f, 0.0f, 1.0f };
glClearBufferfv(GL_COLOR, 0, red );
}
/*---------------------------------------------------------------------------*/
第一个程序实现非常简单,我们在RenderGL()这个函数中调用glClearBufferfv()函数,清除了颜色缓存(缓冲区),填充的颜色是100%不透明的红色,其余我们什么也没做。
程序能够顺利地编译。在我的开发环境(Windows8+Qt5.2+QtCreator3.0)中没有出现问题。运行的时候可能有些不一样。如果没有安装好最新的显卡驱动程序,那么可能无法运行该程序,好在我们使用的唯一的gl类函数glClearBufferfv它是自OpenGL3.0引入的,并不是来自最高的OpenGL4.4,有些计算机虽然不能支持OpenGL4.4,但应该也能运行。这里有两个程序可以判定当前计算机最高支持多少OpenGL规范:一个是qglinfo,它是Qt3D库的实用工具;另外一个是glewinfo,它来自于glew。下面是程序的运行截图:
源代码下载地址:这里