一、 提要
   之前的一篇教程已经搭建好了Qt下的OpenGL的编程环境,几天要来学习的就是OpenGL的2D绘图。
2D作为绘图的基础,还是很值得去好好学习,比如迪卡尔坐标,透视设置等等,而所谓的3D,也只是在2D的基础上加上了Z轴。
   这篇教程主要包括基本2D图元的绘制,着色,旋转。
 
二、必须要了解的几个函数
gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar);
   这个函数指定了观察的视景体在世界坐标系中的具体大小,一般而言,其中的参数aspect应该与窗口的宽高比大小相同。
fovy,视野角度,用过照相机的话就很好理解了,数值越小,相当于将镜头拉得越近,数值越大,镜头越广,镜头里的东西就越小。
aspect,这个好理解,就是实际窗口的纵横比,即x/y。
zNear,这个呢,表示你近处,的裁面。
zFar表示远处的裁面。
 
glLoadIdentity();
这个函数类似于一个复位操作:
1.X坐标轴从左至右,Y坐标轴从下至上,Z坐标轴从里至外。
2.OpenGL屏幕中心的坐标值是X和Y轴上的0.0f点。
3.中心左面的坐标值是负值,右面是正值。
移向屏幕顶端是正值,移向屏幕底端是负值。
移入屏幕深处是负值,移出屏幕则是正值。  
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
这个函数设置清除屏幕时所用的颜色,色彩值的范围从0.0f到1.0f。0.0f代表最黑的情况,1.0f就是最亮的情况。glClearColor 后的第一个参数是Red Intensity(红色分量),第二个是绿色,第三个是蓝色。最大值也是1.0f,代表特定颜色分量的最亮情况。最后一个参数是Alpha值。
glTranslatef(x, y, z)沿着 X, Y 和 Z 轴移动。根据前面的次序,下面的代码沿着X轴左移1.5个单位,Y轴不动(0.0f),最后移入屏幕6.0f个单位。注意在glTranslatef(x, y, z)中当您移动的时候,您并不是相对屏幕中心移动,而是相对与当前所在的屏幕位置。
 
glVertex *
glVertex3f 就是确定顶点的函数,三个参数是点 的空间坐标。
 
三.图形的绘制
在上一篇教程中已经绘制了一个正方形,相信大家都不会感到陌生。
先来分析上一篇的绘图代码:
 
//绘制一个正方形 glBegin( GL_QUADS ); glVertex3f( -1.0,  1.0,  0.0 ); glVertex3f(  1.0,  1.0,  0.0 ); glVertex3f(  1.0, -1.0,  0.0 ); glVertex3f( -1.0, -1.0,  0.0 ); glEnd();
glBegin 与 glEnd 很明显是一对, 标志着一组 OpenGL 操作的开始和结束。 并且在参数中告诉了 OpenGL 下面的操作是针对什么图形进行的,此例中 GL_QUADS 是表示四边形。
通过传递给glBegin不同的参数,我们可以完成各种不同的图形绘制,点,线,三角形,矩形,不规则多边形...
 
简而言之,上面的 4 句 glVertex3f 确定了矩形的 4 个顶点。(注意顺序)然后, OpenGL 就会自动根据 glBegin 指定的参数去完成相关的绘制任务了。
下面我们在屏幕上绘制一个三角形和一个圆形,还有一个多边形。
修改nehewidget.cpp的paintGL()就可以了。
 
void NeHeWidget::paintGL() {     // 清除屏幕和深度缓存     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );     glLoadIdentity();     //移到屏幕的左半部分,并且将视图推入屏幕背后足够的距离以便我们可以看见全部的场景     glTranslatef(-2.0f,0.0f,-5.0f);     //设置颜色     glColor3f( 1.0, 1.0, 1.0 );     //绘制一个三角形     glBegin(GL_TRIANGLES);                         // 绘制三角形             glVertex3f( 0.0f, 1.0f, 0.0f);                 // 上顶点             glVertex3f(-1.0f,-1.0f, 0.0f);                   // 左下             glVertex3f( 1.0f,-1.0f, 0.0f);                    // 右下     glEnd();     glLoadIdentity();     glTranslatef(0.0f,0.0f,-5.0f);     //绘制圆形     GLint iCirclePoints = 50;           glBegin (GL_TRIANGLE_FAN );           for (int i = 0; i < 50; ++i )           {                  double dAngle = 2 * PI * i / iCirclePoints ;                  glVertex3f (cos (dAngle ), sin (dAngle ), 0.0);           }           glEnd ();       //绘制多边形           glLoadIdentity();           glTranslatef(2.0f,0.0f,-5.0f);           glBegin(GL_POLYGON);                   glVertex3f( 0.0f, 0.5f, 0.0f);                   glVertex3f(-0.5f,-0.5f, 0.0f);                   glVertex3f( 0.0f,-1.5f, 0.0f);                   glVertex3f( 0.5f,-0.5f, 0.0f);          glEnd(); }
 
        绘制三角和多边形非常简单,就是将对应的参数传给glBegin(),然后给出坐标,glEnd()之后就会绘制。绘制圆形的方法就是将整个圆周分成50份,然后利用三角函数循环计算圆周上的点的值,GL_TRIANGLE_FAN 是指连续地绘制三角形。三角形和多边形的绘制就比较简单了,就是在glBegin()和glEnd()之间插入相应的顶点坐标就可以了,可以去参考红宝书里第二章的内容。
 
四. 着色
        关于着色,其实我们上面已经用到一个函数,就是glColor3f( 1.0, 1.0, 1.0 );原理也是通过设置三个参数,得到想要的颜色,然后用来绘制图形。注意,这里的着色是对于顶点的,也就是说你可以在绘制每个顶点之前设置绘制的颜色,然后它们之间的区域会很平滑的过渡。
        继续修改代码。
 
        void NeHeWidget::paintGL()
        {
            // 清除屏幕和深度缓存
            glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
            glLoadIdentity();
            //移到屏幕的左半部分,并且将视图推入屏幕背后足够的距离以便我们可以看见全部的场景
            glTranslatef(-2.0f,0.0f,-5.0f);
            //绘制一个三角形
            glBegin(GL_TRIANGLES);                           // 绘制三角形
                    glColor3f(1.0f,0.0f,0.0f);
                    glVertex3f( 0.0f, 1.0f, 0.0f);                    // 上顶点
                    glColor3f(0.0f,1.0f,0.0f);
                    glVertex3f(-1.0f,-1.0f, 0.0f);                  // 左下
                    glColor3f(0.0f,0.0f,1.0f);
                    glVertex3f( 1.0f,-1.0f, 0.0f);                   // 右下
            glEnd();
            glLoadIdentity();
            glTranslatef(0.0f,0.0f,-5.0f);
            //绘制圆形
            GLint iCirclePoints = 50;
                  glBegin (GL_TRIANGLE_FAN );
                  for (int i = 0; i < 50; ++i )
                  {
                        glColor3f (0.0/i, 1.0/i, 1.0/i);
                         double dAngle = 2 * PI * i / iCirclePoints ;
                         glVertex3f (cos (dAngle ), sin (dAngle ), 0.0);
                  }
                  glEnd ();
              //绘制多边形
                  glLoadIdentity();
                  glTranslatef(2.0f,0.0f,-5.0f);
                  glColor3f( 1.0, 0.5, 0.0 );
                  glBegin(GL_POLYGON);
                          glVertex3f( 0.0f, 0.5f, 0.0f);                    // 上顶点
                          glVertex3f(-0.5f,-0.5f, 0.0f);
                          glVertex3f( 0.0f,-1.5f, 0.0f);// 左下
                          glVertex3f( 0.5f,-0.5f, 0.0f);                 // 右下
                 glEnd();
    }
 
 
    对于三角形,glEnd()出现后,三角形将被填充。但是因为每个顶点有不同的颜色,因此看起来颜色从每个角喷出,并刚好在三角形的中心汇合,三种颜色相互混合。这就是平滑着色。
    对于圆形,就是利用循环逐渐改变顶点的颜色,最后得到这种渐变的效果。
    对于多边形,因为在glBegin()之前将颜色已经设置好,而在后面也没有改变,所以最后所有顶点都设置成了同一种颜色。
 
五.旋转
    旋转其实已经属于3维的内容了,但实现起来其实非常简单。我们将在NeHeWidget类中增加三个变量来控制这三个对象的旋转。它们是浮点类型的变量,使得我们能够非常精确地旋转对象。新变量中叫做rTri的用来旋转三角形,rCir旋转圆形,rPoly 旋转多边边形。
    旋转所用到的函数是glRotatef( Angle, Xvector, Yvector, Zvector ),
    它负责让对象绕某个轴旋转。这个函数有很多用处。 Angle 通常是个变量代表对象转过的角度。Xvector,Yvector和Zvector三个参数则共同决定旋转轴的方向。比如( 1, 0, 0 )所描述的矢量经过X坐标轴的1个单位处并且方向向右。( -1, 0, 0 )所描述的矢量经过X坐标轴的1个单位处,但方向向左。
    关于旋转的方向的确定,我们可以这样来理解:( Xvector, Yvector, Zvector)表示空间中的一个向量,用右手的大拇指指向这个向量,其他四指抓握的方向就是旋转的方向。
    继续修改代码.
 
    头文件中添加相应的变量:
    protected:
    GLfloat rTri;
    GLfloat rCir;
    GLfloat rPoly;
    在构造函数中初始化
    NeHeWidget::NeHeWidget(QWidget *parent) :
        QGLWidget(parent)
    {
    //初始化旋转量
        rTri = 0;
         rCir = 0;
         rPoly=0;
    void NeHeWidget::paintGL()
    {
        // 清除屏幕和深度缓存
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
        glLoadIdentity();
        //移到屏幕的左半部分,并且将视图推入屏幕背后足够的距离以便我们可以看见全部的场景
        glTranslatef(-2.0f,0.0f,-5.0f);
        //对三角形进行旋转
        glRotatef( rTri,  1.0,  0.0,  0.0 );
        //绘制一个三角形
        glBegin(GL_TRIANGLES);                         // 绘制三角形
                glColor3f(1.0f,0.0f,0.0f);
                glVertex3f( 0.0f, 1.0f, 0.0f);                    // 上顶点
                glColor3f(0.0f,1.0f,0.0f);
                glVertex3f(-1.0f,-1.0f, 0.0f);                  // 左下
                glColor3f(0.0f,0.0f,1.0f);
                glVertex3f( 1.0f,-1.0f, 0.0f);                   // 右下
        glEnd();
        glLoadIdentity();
        glTranslatef(0.0f,0.0f,-5.0f);
        glRotatef( rCir,  0.0,  1.0,  0.0 );
        //绘制圆形
        GLint iCirclePoints = 50;
              glBegin (GL_TRIANGLE_FAN );
              for (int i = 0; i < 50; ++i )
              {
                    glColor3f (0.0/i, 1.0/i, 1.0/i);
                     double dAngle = 2 * PI * i / iCirclePoints ;
                     glVertex3f (cos (dAngle ), sin (dAngle ), 0.0);
              }
              glEnd ();
          //绘制多边形
              glLoadIdentity();
              glTranslatef(2.0f,0.0f,-5.0f);
              glRotatef( rPoly,  0.0,  1.0,  1.0 );
              glColor3f( 1.0, 0.5, 0.0 );
              glBegin(GL_POLYGON);
                      glVertex3f( 0.0f, 0.5f, 0.0f);                 // 上顶点
                      glVertex3f(-0.5f,-0.5f, 0.0f);
                      glVertex3f( 0.0f,-1.5f, 0.0f);// 左下
                      glVertex3f( 0.5f,-0.5f, 0.0f);                 // 右下
             glEnd();
             //每重新绘制一遍窗口就改变一次旋转量。
             rTri += 1.5;
             rCir -= 1.5;
             rPoly+=2;
    }
 
 
    编译运行之后不断按F2改变窗口就可以观察到相应的变化了,这里我通过设定不同的旋转向量来让三个图形按照不同的方向来旋转。
     注意一点:在适当的位置调用glLoadIdentity()重置坐标,不然在后面图形的绘制的时候就是基于之前变换过的坐标了。
    今天就到这。
 
参考资料

1.      《 OpenGL Reference Manual 》, OpenGL 参考手册

2.      《 OpenGL 编程指南》(《 OpenGL Programming Guide 》), Dave Shreiner , Mason Woo , Jackie Neider , Tom Davis 著,徐波译,机械工业出版社

3.         《win32 OpenGL编程 》   一个大牛的博客     http://blog.csdn.net/vagrxie/article/category/628716/3

分享到: 

转载于:https://blog.51cto.com/8672742/1368431

Qt下的OpenGL 编程(3)绘制平面几何体相关推荐

  1. Qt下的OpenGL 编程(1)Qt下的OpenGL编程必须步骤

    一.前言 暑假在家里花了些时间了研究了Ogre,基本是每天一篇wiki教程.最后做完了初级教程后觉得自己进行不下去了,因为里面还有挺多东西都每有理解,所以想来接触一下更"低端"一些 ...

  2. Win32 OpenGL 编程(1)Win32下的OpenGL编程必须步骤

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! Win3 ...

  3. QT下使用OpenGL渲染Mesh的框架

    说说我的QT下使用OpenGL渲染Mesh的框架 http://www.xpc-yx.com/2015/03/13/%E8%AF%B4%E8%AF%B4%E6%88%91%E7%9A%84qt%E4% ...

  4. VC++下的OpenGL编程

    1.值得记住的约定 一般情况下,VC++下进行OpenGL应用程序开发步骤如下: 1.通过PIXELFORMATDESCRIPTOR结构设置备注描述表DC的像素格式属性. 2.创建渲染描述表RC,并与 ...

  5. Qt下使用Shader绘制三角形

    在Qt下使用可编程管线编写OpenGL的流程是怎样的呢? 下面演示了Qt下使用可编程管线的基本代码:(绘制三个不同的三角形,并做些旋转变换) 在Qt中,我们从QGLWidget继承,来实现OpenGL ...

  6. QT openGL 编程 笔记

    据说QT牛,特地花了一个晚上来研究研究.其实我也不想把自己搞得熊猫眼,只是碰到问题了精力就特好,想睡觉都不行.第一次尝试在LINUX下用OpenGL编程,实在是很兴奋,只是感觉碰了不少灰.一个问题从1 ...

  7. Windows下Qt开发环境:OpenGL导入3DMax模型(.3DS)

    参考:http://blog.csdn.net/cq361106306/article/details/41876541 效果: 源代码: 解释: CLoad3DS.h为加载3DMax模型的头文件,C ...

  8. Win32 OpenGL编程系列 2D例子 -- 七巧板图形绘制

    write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie 讨论新闻组及文件 OpenGL系列文章都已经写到3D部分了,但是感觉2D的例子还是少了点,特意弄个外 ...

  9. Win32 OpenGL 编程

    Win32 OpenGL 编程(1)Win32下的OpenGL编程必须步骤 一.    前言 人生在于折腾,继续折腾吧. OpenGL 编程的红宝书< OpenGL Programming Gu ...

最新文章

  1. 发现的一个翻译的不错的elasticsearch 2.3.3 官方文档的API
  2. Cell子刊:根瘤菌微生物群落的模块化特征及其与共生根瘤菌的进化关系
  3. 【鉴轻尘】你说你炒的了币,开发得了项目,然而这些你都知道吗?
  4. 编译时“-nostdlib”的使用
  5. android技巧:apk文件反编译以及签名打包,APKTool 反编译,打包,签名
  6. python主要应用的几个领域
  7. 算法研究:插入类排序(简单插入,折半插入,希尔排序)
  8. 公司打印机的安装和使用
  9. 二年级机器人伙伴看图写话_期末考试一二年级看图写话22篇,附范文!
  10. 简单分享apache封IP的方法
  11. javascript时间戳转换成yyyy-MM-DD格式
  12. 你真的了解Ioc与AOP吗?(1)
  13. python librosa库实现变声
  14. 微信小程序下载Excel到本地
  15. 在进行ISO14001认证审核之前,需要注意什么?
  16. CRM系统更换服务器,CRM系统三种常见安装实施解决方式
  17. 计算机加法器原理,加法器原理
  18. 系统分析与设计小组项目总结报告
  19. 11G rac修改监听端口
  20. 芯片短缺困局难解汽车巨头被迫停工减产---道合顺大数据

热门文章

  1. JAVA 邮件发送工具类
  2. 获取request header的值
  3. 测试build出来的dist文件夹是否编译成功
  4. JS识别不同浏览器信息
  5. ios 消除 字符串 首尾空格
  6. 重新解析 REST Service(REST Service 的最佳实践,第 1 部分)
  7. Mysql 授权控制
  8. 以太坊 p2p Server 原理及实现
  9. Composer 安装(一)
  10. win7 64bit下最新Apahe2.4.18+php7.0.2+MySQL5.7.10配置