zoukankan      html  css  js  c++  java
  • OpenGL超级宝典笔记——画三角形(转)

    http://my.oschina.net/sweetdark/blog/161002

    学习了画线的知识,我们可以使用GL_LINE_LOOP来画闭合的多边形。但是使用这种方式画出来的只有线框,多边形没有填充颜色。OpenGL支持绘制实心的多边形,并使用当前的颜色进行填充。

    三角形

    简单的三角形,需要指定三个顶点。

       1: glBegin(GL_TRIANGLES);
       2:     glVertex2f(0.0f, 0.0f);            // V0
       3:     glVertex2f(25.0f, 25.0f);          // V1
       4:     glVertex2f(50.0f, 0.0f);           // V2
       5:     glVertex2f(-50.0f, 0.0f);          // V3
       6:     glVertex2f(-75.0f, 50.0f);         // V4
       7:     glVertex2f(-25.0f, 0.0f);          // V5
       8: glEnd();
       9: 

    这两个三角形会使用当前的颜色进行填充。

    image

    多边形的环绕

    按照顶点指定的顺序和方向组合称为环绕。上图的两个多边形是顺时针环绕的。我们可以通过改变顶点的顺序,从而改变环绕方向。我们把v4和v5的顺序调换过来,则这个三角形的环绕方向为逆时针了。

    image

    OpenGL默认是逆时针环绕方向为正方向,即逆时针环绕的三角形为正面。上图左边的三角形,显示的是正面,而右边的显示的是反面。我们也可以通过函数glFrontFace(GL_CW);来告诉OpenGL顺时针环绕的多边形是正面。环绕方向是多边形一个非常有用的性质,可以用于消除不必要的面。

    三角形带

    我们可以绘制多个三角形连起来形成多个面或者多边形。使用GL_TRIANGLE_STRIP图元,可以绘制一串相连的多边形,来节省大量的时间。

    image

    由上图可以看到,多边形的边的绘制顺序并不是完全按照我们指定的顶点顺序的。而是按照OpenGL指定的顺序逆时针方向绘制的。

    使用三角形带而不是分别指定每个三角形的顶点的优势有两个:

    1. 用前面三个顶点指定一个三角形后,只需再指定一个顶点就能画出第二个三角形。要绘制大量的三角形时,这种方法可以节省大量的代码以及数据存储空间
    2. 运算性能的提高和带宽的节省。更少的顶点,从内存传输的显卡的时间更快,以及参与变换的顶点更少。

    三角形扇

    除了三角形带之外,我们还可以通过GL_TRIANGLE_FAN图元,创建一组围绕一个中心点的三角形扇。通过制定5个顶点我们就可以绘制3个三角形来形成三角形扇。用3个顶点指定一个三角形后,后续的顶点Vn与原点V0以及前面的一个顶点Vn-1形成一个三角形。

    image

    创建实心物体


       1: static void RenderScene()
       2: {
       3:   //清除颜色缓冲区和深度缓冲区
       4:     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
       5: 
       6:     GLfloat x, y, z, angle;
       7:   //用于颜色判断
       8:   bool color;
       9:     glColor3f(1.0f, 1.0f, 0.0f);
      10:   //是否开启深度缓冲
      11:   if (bDepth)
      12:   {
      13:     glEnable(GL_DEPTH_TEST);
      14:   }
      15:   else
      16:   {
      17:     glDisable(GL_DEPTH_TEST);
      18:   }
      19:   //是否开启隐藏面消除
      20:   if (bCull)
      21:   {
      22:     glEnable(GL_CULL_FACE);
      23:   }
      24:   else
      25:   {
      26:     glDisable(GL_CULL_FACE);
      27:   }
      28:   //开启线框模式 
      29:   if (bOutLine)
      30:   {
      31:     glPolygonMode(GL_BACK, GL_LINE) ;
      32:   }
      33:   else
      34:   {
      35:     glPolygonMode(GL_BACK, GL_FILL);
      36:   }
      37:
      38: 
      39:   glPushMatrix();
      40:   glRotatef(xRot, 1.0f, 0.0f, 0.0f);
      41:   glRotatef(yRot, 0.0f, 1.0f, 0.0f);
      42:   //画椎体
      43:   glBegin(GL_TRIANGLE_FAN);
      44:     glVertex3f(0.0f, 0.0f, 70.0f);
      45: 
      46:     for (angle = 0.0f; angle <= (2 * GL_PI); angle += (GL_PI  / 8))
      47:     {
      48:           x = 50.0f * sin(angle);
      49:           y = 50.0f * cos(angle);
      50:           color = !color;
      51:
      52:       glVertex3f(x, y, 0.0f);
      53:           if(color)
      54:               glColor3f(1.0f, 0.0f, 0.0f);
      55:           else
      56:               glColor3f(0.0f, 1.0f, 1.0f);
      57:     }
      58:   glEnd();
      59:   //画椎体的底面
      60:     glBegin(GL_TRIANGLE_FAN);
      61:       glVertex2f(0.0f, 0.0f);
      62: 
      63:       for (angle = 0.0f; angle <= (2 * GL_PI); angle += (GL_PI  / 8))
      64:       {
      65:           x = 50.0f * sin(angle);
      66:           y = 50.0f * cos(angle);
      67:           color = !color;
      68:
      69:           glVertex2f(x, y);
      70: 
      71:           if(color)
      72:               glColor3f(1.0f, 0.0f, 0.0f);
      73:           else
      74:               glColor3f(0.0f, 1.0f, 1.0f);
      75:       }
      76:     glEnd();
      77: 
      78:   glPopMatrix();
      79:     glutSwapBuffers();
      80: }
      81: 
      82: static void SetupRC()
      83: {
      84:     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
      85:   //设置环绕方向
      86:     glEnable(GL_CW);
      87:   //设置填充模式
      88:     glShadeModel(GL_FLAT);
      89:   //设置要消除的隐藏面,这里设置为反面
      90:   glCullFace(GL_BACK);
      91: }

    image

    使用红青相间的方式来绘制一个锥体。

    设置多边形的颜色

    多边形的填充模式有两种一种是单调着色GL_FLAT,一种平滑着色GL_SMOOTH。

    通过glShadeMode(GL_FLAT);和glShadeMode(GL_SMOOTH);来设置。单调着色以三角形的最后一个顶点的颜色来填充三角形。平滑着色则是用三个顶点的颜色值进行内插值运算,来填充三角形的颜色。

    平滑着色效果如下:

    image

    隐藏面消除

    如果没有使用深度缓冲区,来进行深度测试。上面的椎体如何旋转(通过方向键可以旋转),都是把底面显示了出来。因为底面我们是在后面画的,最后一个绘制的物体出现在之前绘制的物体的前面。如果开启了深度测试来解决问题。

    深度测试:当一个像素被绘制时,它将被设置一个值(z值),以表示它和观测者的距离。以后当这个位置要绘制新像素时,新像素的z值就会和旧像素的z值进行比较。如果新像素z值更高,则更靠近观察者,则应该被绘制,反之被忽略。

    启用深度测试只须调用glEnable(GL_DEPTH_TEST);每次场景被渲染之前,应该清楚深度缓冲区,与清楚颜色缓冲区类似。

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    在程序用使用右键点击,弹出菜单,深度测试来切换深度测试。在绘制3D实体时,深度测试往往是必须的。

    image

    剔除

    虽然启用深度测试,可以消除隐藏面。但很多时候,我们清楚那些面是不需要绘制,应该被剔除的。例如:多边形的背面不应该被显示。如果我们告知OpenGL这个图形面不需要被绘制,就不会把这个图形发送给OpenGL驱动程序和硬件,可以提高性能。

    启用剔除面的功能。

    //指定顺时针环绕的面为正面

    glFrontFace(GL_CW);

    //开启剔除面,剔除背面。

    glEnable(GL_CULL_FACE);

    image

    image

    锥体的底面面向锥体内部的是正面。要改变底面的正面,可以再绘制底面时设置glFrontFace(GL_CCW);

    多边形模式

    多边形我们可以指定它的模式,要填充还是只画线框或者只画顶点。

    通过glPolygonMode(GL_BACK, GL_LINE) ;设置多边形的背面只画线。

    通过glPolygonMode(GL_BACK, GL_FILL) ;设置多边形的背面为实体。

    通过glPolygonMode(GL_BACK, GL_POINT) ;设置多边形的背面只画点。

    image

    源代码:https://github.com/sweetdark/openglex/tree/master/triangle

  • 相关阅读:
    C# 删除文件夹
    XML操作类
    C# winform 安装程序打包(自定义操作)
    复制Datatable结构和数据,并按条件进行筛选
    Sql_Case_When
    C# using 与Trycatchfinally的区别和用法
    Winform datagridview Excel 导入导出
    矩阵树定理学习笔记
    minmax容斥笔记及例题
    平衡树学习笔记
  • 原文地址:https://www.cnblogs.com/aminxu/p/4704191.html
Copyright © 2011-2022 走看看