opengl绘制立方体 怎么在qt 创建一个立方体

今天看啥 热点:
【Qt for Android】OpenGL ES 绘制彩色立方体,qtandroid
Qt 内置对OpenGL ES的支持,选用Qt进行OpenGL ES的开发是非常方便的,许多辅助类都已经具备。从Qt 5.0开始增加了一个QWindow类,该类既可以使用OpenGL绘制3D图形,也可以使用QPainter绘制2D传统的GDI+图形,5.0以前的QGLWidget不推荐再使用。在即将到来(官方时间是今年秋天)Qt 5.4会完全废弃QGLWidget,作为替代将会新增QOpenGLWidget和QOpenGLWindow类来方便OpenGL的编程。
好了废话不多说了,今天我会使用OpenGL ES绘制一个彩色立方体,先在桌面平台编译运行成功后,再针对Android平台编译一次即可,下面是在Android上的运行效果,基于同一个着色器绘制了四个相同的彩色立方体。
为了使用OpenGL,我从QWindow类和QOpenGLFunctions类派生出了一个OpenGLWindow类,该类声明如下:
class OpenGLWindow : public QWindow, protected QOpenGLFunctions
explicit OpenGLWindow(QWindow *parent = 0);
~OpenGLWindow();
virtual void initialize();
virtual void render(QPainter *painter);
virtual void render(double currentTime = 0.0);
// elapsed seconds from program started.
protected:
void exposeEvent(QExposeEvent *event);
QOpenGLPaintDevice *m_
QOpenGLContext *m_
//    QOpenGLShaderProgram *m_shaderP
由于继承自QWindow因此可以使用QWindow提供的OpenGL环境,不需要EGL来控制本地窗口显示图形。同时由于继承自QOpenGLFunctions,所以在OpenGLWindow类的成员函数中可以直接使用 gl* 风格的原生的OpenGL API。在Qt中提供了很多封装好的OpenGL便捷类,如QOpenGLShaderProgram可以很方便的对着色器程序进行操作,但这样做可能对不熟悉Qt的人不友好,所以这里我不用Qt提供的便捷类,而直接使用原生的C风格的 OpenGL API进行操作,这完全是可以的(这也是我喜欢Qt的原因之一:提供自身类库的同时,允许你使用非Qt的类,并提供二者之间的转换,如Qt中的容器类QVector、QMap、QString可以和C++标准库中的相应容器相互转换)。甚至你可以混合使用Qt的OpenGL类和原生的OpenGL
下面看看几个关键的函数。首先是initialize()负责着色器的创建、编译、链接等操作,并设置背景色。代码如下,其中被注释的部分是使用Qt自带类库实现相同的功能。
void OpenGLWindow::initialize()
const char *vertexShaderSrc =
&attribute vec4 a_ \n&
&uniform mat4 u_ \n&
&varying vec4 v_ \n&
&void main()
v_color = a_position*0.7 + 0.5;
gl_Position = u_mvp * a_ \n&
const char *fragmentShaderSrc =
&varying vec4 v_ \n&
&void main()
gl_FragColor = v_ \n&
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSrc, NULL);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSrc, NULL);
glCompileShader(fragmentShader);
m_program = glCreateProgram();
glAttachShader(m_program, vertexShader);
glAttachShader(m_program, fragmentShader);
glLinkProgram(m_program);
//    // add vertex shader(compiled internal)
//    m_shaderProgram-&addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSrc);
//    // add fragment shader(compiled internal)
//    m_shaderProgram-&addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSrc);
//    // link shaders to program
//    m_shaderProgram-&link();
// set the background clear color.
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
再来看看QWindow的QExposeEvent事件,当QWindow需要重绘时会调用该事件的处理函数exposeEvent(),这里我对该事件的处理函数进行了重写。isExposed()用来判断当前窗口是否显示在屏幕上(onScreen or offScreen),只有显示在屏幕上时才重绘(虽然窗口需要重绘,但是由于没有显示在屏幕上,重绘了也没人看得见,所以加这个判断可以减少不必要的绘图操作)。首先创建OpenGL上下文,然后进行调用相应的初始化函数,这两步只在第一次被执行,以后不会再执行。接下来是该函数的核心部分,调用render()函数在后端缓冲区进行图形渲染,然后交换前端和后端缓冲区,让后端缓冲区图形显示到界面上。
void OpenGLWindow::exposeEvent(QExposeEvent *event)
Q_UNUSED(event)
static bool needInit =
// Returns true if this window is exposed in the windowing system.
if (isExposed())
if (m_context == nullptr)
m_context = new QOpenGLContext(this);
m_context-&setFormat(requestedFormat());
m_context-&create();
m_context-&makeCurrent(this);
if (needInit)
initializeOpenGLFunctions();
this-&initialize();
needInit =
// calculate elapsed seconds from program started.
double duration = startTime.msecsTo(QTime::currentTime()) / 1000.0;
render(duration);
m_context-&swapBuffers(this);
最后看看render()渲染函数,这个也是学习OpenGL的主要部分。
在render()函数的开始部分创建了一个QOpenGLPaintDevice实例,该示例用于绘制QPainter的绘图操作,这里可以忽略,删掉也可以。接下来就是定义立方体的顶点位置,以及顶点索引。创建2个顶点缓冲区对象(vertex buffer object),通过glBufferData()函数将立方体的顶点位置和顶点所以放到顶点缓冲区对象中,将顶点位置通过glVertexAttribPointer()传递给顶点着色器。计算model/view/projection,然后将结果通过glUniformMatrix4fv()传递给顶点着色器中的mvp,最后使用glDrawElement()绘制立方体。立方体每个点的颜色由其所在的位置决定,所以不同位置的顶点具有不同颜色。
void OpenGLWindow::render(double currentTime)
if (m_device == nullptr)
m_device = new QOpenGLPaintD
m_device-&setSize(this-&size());
static GLfloat vCubeVertices[] = {
-0.5f, -0.5f,
0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, -0.5f,
0.5f, -0.5f,
-0.5f, -0.5f, -0.5f, // v7
static GLushort vCubeIndices[] = {
0, 1, 2, 0, 2, 3,
// front face
5, 6, 7, 4, 5, 7,
// back face
0, 1, 7, 0, 6, 7,
// left face
2, 3, 4, 3, 4, 5,
// right face
0, 3, 5, 0, 5, 6,
// top face
1, 2, 4, 1, 4, 7
// bottom face
glViewport(0, 0, width(), height());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(m_program);
GLuint vbos[2];
glGenBuffers(2, vbos);
glBindBuffer(GL_ARRAY_BUFFER, vbos[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vCubeVertices), vCubeVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vCubeIndices), vCubeIndices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vbos[0]);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindAttribLocation(m_program, 0, &a_position&);
static GLfloat angle = 0.0;
GLuint mvpLoc = glGetUniformLocation(m_program, &u_mvp&);
QMatrix4x4 model, view, projection,
model.rotate(angle + 5, QVector3D(1,0,0));
model.rotate(angle - 5, QVector3D(0,1,0));
model.scale(0.5, 0.5, 0.5);
view.translate(0.5, 0.5, 0);
angle += 10;
mvp = projection * view *
glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, mvp.constData());
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos[1]);
glDrawElements(GL_TRIANGLES, sizeof(vCubeIndices)/sizeof(GLushort), GL_UNSIGNED_SHORT, 0);
/* draw another cube in different place with the same shader */
view.translate(-1.0, 0, 0);
mvp = projection * view *
glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, mvp.constData());
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos[1]);
glDrawElements(GL_TRIANGLES, sizeof(vCubeIndices)/sizeof(GLushort), GL_UNSIGNED_SHORT, 0);
view.translate(0.0, -1.0, 0);
mvp = projection * view *
glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, mvp.constData());
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos[1]);
glDrawElements(GL_TRIANGLES, sizeof(vCubeIndices)/sizeof(GLushort), GL_UNSIGNED_SHORT, 0);
view.translate(1.0, 0, 0);
mvp = projection * view *
glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, mvp.constData());
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos[1]);
glDrawElements(GL_TRIANGLES, sizeof(vCubeIndices)/sizeof(GLushort), GL_UNSIGNED_SHORT, 0);
QPainter painter(m_device);
render(&painter);
glDeleteBuffers(2, vbos);
好了大致就这样了~
设置一个速度变量fSpeed。它等于拖动距离/拖动时间,这样不就是拖得越快,转得越快了么。慢慢静止下来无非就是没有拖动操作时候,让这个fSpeed自减一个偏移量就行了。
把这三行去掉,正视投影(glOrtho)不需要这样设置:glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
gluLookAt( 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
相关搜索:
相关阅读:
相关频道:
Android教程最近更新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/
&&&&&& 我想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
GLWindow( QWindow* pParent = Q_NULLPTR );
protected:
void exposeEvent( QExposeEvent* pEvent );
void InitGL( void );
// 额外OpenGL的初始化
void RenderGL( void );
// OpenGL渲染相关
void ResizeGL( int width, int height ); // 窗口大小改变时该如何应对
QOpenGLContext* m_pC
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 )
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规范:,它是Qt3D库的实用工具;,它来自于glew。下面是程序的运行截图:
& & & &源代码下载地址:
本文已收录于以下专栏:
相关文章推荐
原文                 
http://blog.csdn.net/bcs_01/article/details...
         暑假在家里花了些时间了研究了Ogre,基本是每天一篇wiki教程。最后做完了初级教程后觉得自己进行不下去了,因为里面还有挺多东西都每有理解,所以想来接触一下更“低端...
原文: http://qiliang.net/old/nehe_qt/
Qt OpenGL教程
最近一段时间除了学习Qt,翻译Qt文档之外,由于工作和兴趣的原因,开始着手看Qt OpenG...
在这个教程里,我们将在Qt Creator环境中创建OpenGL对象,它将显示一个空的OpenGL窗口,可以在窗口和全屏模式下切换,按ESC退出,它将是我们后面应用程序的基础框架。
环境:Qt4.7.3 + VS2008
//*************** 
#ifndef GLUTTTT_H
#define GLUTTTT_...
学习QT已经有一段时间了,为了可以进一步的学习QT,并学习在QT在使用OpenGL。将定期按照Nehe的OpenGL教程,将功能在QT中全部实现。本博客发布的代码,在Window XP + Visua...
这次教程中,我们将介绍类似于DirectDraw的blit(其实blit函数在许多绘图库都有),我们将用代码自己来实现它。它的作用非常简单,就是把一块纹理的贴到另一块纹理上。想想,有了这个函数,我们就...
这次教程中,我们将在纹理映射的基础上加上混合,使它看起来具有透明的效果,当然解释它不是那么容易但代码并不难,希望你喜欢它。
这次教程中,我们将创建一个简单的粒子系统,并用它来创建一种喷射效果。利用粒子系统,我们可以实现爆炸、喷泉、流星之类的效果,听起来是不是很棒呢!
他的最新文章
讲师:刘文志
讲师:陈伟
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)Qt 和 OpenGL 组合实现三维建模可行吗? - 知乎16被浏览2034分享邀请回答0添加评论分享收藏感谢收起0添加评论分享收藏感谢收起查看更多回答

我要回帖

更多关于 opengl画立方体 的文章

 

随机推荐