多边形
(1)多边形的两面以及绘制方式。
虽然我们目前还没有真正的使用三维坐标来画图,但是建立一些三维的概念还是必要的。
从三维的角度来看,一个多边形具有两个面。每一个面都可以设置不同的绘制方式:填充、只绘制边缘轮廓线、只绘制顶点,其中“填充”是默认的方式

可以为两个面分别设置不同的方式。
glPolygonMode(GL_FRONT, GL_FILL);            // 设置正面为填充方式
glPolygonMode(GL_BACK, GL_LINE);             // 设置反面为边缘绘制方式
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); // 设置两面均为顶点绘制方式

(2)反转
一般约定为“顶点以逆时针顺序出现在屏幕上的面”为“正面”,另一个面即成为“反面”。
但也有一些表面比较特殊。例如“麦比乌斯带”(请自己Google一下),可以全部使用“正面”或全部使用“背面”来表示。

可以通过glFrontFace函数来交换“正面”和“反面”的概念。
glFrontFace(GL_CCW);   // 设置CCW方向为“正面”,CCW即CounterClockWise,逆时针
glFrontFace(GL_CW);    // 设置CW方向为“正面”,CW即ClockWise,顺时针
下面是一个示例程序,请用它替换第一课中的myDisplay函数,并将glFrontFace(GL_CCW)修改为glFrontFace(GL_CW),并观察结果的变化。

void myDisplay(void)
{glClear(GL_COLOR_BUFFER_BIT);glPolygonMode(GL_FRONT, GL_FILL); // 设置正面为填充模式glPolygonMode(GL_BACK, GL_LINE);   // 设置反面为线形模式glFrontFace(GL_CW);               // 设置顺时针方向为正面,默认为逆时针GL_CCWglBegin(GL_POLYGON);               // 按逆时针绘制一个正方形,在左下方glVertex2f(-0.5f, -0.5f);glVertex2f(0.0f, -0.5f);glVertex2f(0.0f, 0.0f);glVertex2f(-0.5f, 0.0f);glEnd();glColor3f(0.0f, 1.0f, 0.0f);glBegin(GL_POLYGON);               // 按顺时针绘制一个正方形,在右上方glVertex2f(0.0f, 0.0f);glVertex2f(0.0f, 0.5f);glVertex2f(0.5f, 0.5f);glVertex2f(0.5f, 0.0f);glEnd();glFlush();
}

(3)剔除多边形表面
在三维空间中,一个多边形虽然有两个面,但我们无法看见背面的那些多边形,而一些多边形虽然是正面的,但被其他多边形所遮挡。如果将无法看见的多边形和可见的多边形同等对待,无疑会降低我们处理图形的效率。在这种时候,可以将不必要的面剔除。
首先,使用glEnable(GL_CULL_FACE);来启动剔除功能(使用glDisable(GL_CULL_FACE)可以关闭之)
然后,使用glCullFace来进行剔除。
glCullFace的参数可以是GL_FRONT,GL_BACK或者GL_FRONT_AND_BACK,分别表示剔除正面、剔除反面、剔除正反两面的多边形。
注意:剔除功能只影响多边形,而对点和直线无影响。例如,使用glCullFace(GL_FRONT_AND_BACK)后,所有的多边形都将被剔除,所以看见的就只有点和直线。

下面画两个面一条线一个点测试一下:

void myDisplay(void)
{glClear(GL_COLOR_BUFFER_BIT);glPolygonMode(GL_FRONT, GL_FILL); // 设置正面为填充模式glPolygonMode(GL_BACK, GL_LINE);   // 设置反面为线形模式glFrontFace(GL_CW);               // 设置顺时针方向为正面,默认为逆时针GL_CCWglBegin(GL_POLYGON);               // 按逆时针绘制一个正方形,在左下方glVertex2f(-0.5f, -0.5f);glVertex2f(0.0f, -0.5f);glVertex2f(0.0f, 0.0f);glVertex2f(-0.5f, 0.0f);glEnd();glColor3f(0.0f, 1.0f, 0.0f);glBegin(GL_POLYGON);               // 按顺时针绘制一个正方形,在右上方glVertex2f(0.0f, 0.0f);glVertex2f(0.0f, 0.5f);glVertex2f(0.5f, 0.5f);glVertex2f(0.5f, 0.0f);glEnd();//画一个点测试一下,剔除面不会影响点和线glPointSize(10);glBegin(GL_POINTS);glVertex2f(-0.5f, 0.5f);glEnd();glLineWidth(4);glBegin(GL_LINES);glVertex2f(-0.7f, 0.3f);glVertex2f(-0.6f, -0.5f);glEnd();glEnable(GL_CULL_FACE);//启动剔除功能(使用glDisable(GL_CULL_FACE)可以关闭之)glCullFace(GL_FRONT_AND_BACK);glFlush();
}

开始的图是这样,右边为剔除后的效果

     

(4)镂空多边形
直线可以被画成虚线,而多边形则可以进行镂空。
首先,使用glEnable(GL_POLYGON_STIPPLE);来启动镂空模式(使用glDisable(GL_POLYGON_STIPPLE)可以关闭之)。
然后,使用glPolygonStipple来设置镂空的样式。
void glPolygonStipple(const GLubyte *mask);
其中的参数mask指向一个长度为128字节的空间,它表示了一个32*32的矩形应该如何镂空。其中:第一个字节表示了最左下方的从左到右(也可以是从右到左,这个可以修改)8个像素是否镂空(1表示不镂空,显示该像素;0表示镂空,显示其后面的颜色),最后一个字节表示了最右上方的8个像素是否镂空。
但是,如果我们直接定义这个mask数组,像这样:

static GLubyte Mask[128] =
{0x00, 0x00, 0x00, 0x00,    //   这是最下面的一行0x00, 0x00, 0x00, 0x00,0x03, 0x80, 0x01, 0xC0,    //   麻0x06, 0xC0, 0x03, 0x60,    //   烦0x04, 0x60, 0x06, 0x20,    //   的0x04, 0x30, 0x0C, 0x20,    //   初0x04, 0x18, 0x18, 0x20,    //   始0x04, 0x0C, 0x30, 0x20,    //   化0x04, 0x06, 0x60, 0x20,    //   ,0x44, 0x03, 0xC0, 0x22,    //   不0x44, 0x01, 0x80, 0x22,    //   建0x44, 0x01, 0x80, 0x22,    //   议0x44, 0x01, 0x80, 0x22,    //   使0x44, 0x01, 0x80, 0x22,    //   用0x44, 0x01, 0x80, 0x22,0x44, 0x01, 0x80, 0x22,0x66, 0x01, 0x80, 0x66,0x33, 0x01, 0x80, 0xCC,0x19, 0x81, 0x81, 0x98,0x0C, 0xC1, 0x83, 0x30,0x07, 0xE1, 0x87, 0xE0,0x03, 0x3F, 0xFC, 0xC0,0x03, 0x31, 0x8C, 0xC0,0x03, 0x3F, 0xFC, 0xC0,0x06, 0x64, 0x26, 0x60,0x0C, 0xCC, 0x33, 0x30,0x18, 0xCC, 0x33, 0x18,0x10, 0xC4, 0x23, 0x08,0x10, 0x63, 0xC6, 0x08,0x10, 0x30, 0x0C, 0x08,0x10, 0x18, 0x18, 0x08,0x10, 0x00, 0x00, 0x08    // 这是最上面的一行
};

这样一堆数据非常缺乏直观性,我们需要很费劲的去分析,才会发现它表示的竟然是一只苍蝇。
如果将这样的数据保存成图片,并用专门的工具进行编辑,显然会方便很多。下面介绍如何做到这一点。

首先,用Windows自带的画笔程序新建一副图片,取名为mask.bmp,注意保存时,应该选择“单色位图”。在“图象”->“属性”对话框中,设置图片的高度和宽度均为32。
用放大镜观察图片,并编辑之。黑色对应二进制零(镂空),白色对应二进制一(不镂空),编辑完毕后保存。
然后,就可以使用以下代码来获得这个Mask数组了。
static GLubyte Mask[128];
FILE *fp;
fp = fopen("mask.bmp", "rb");
if( !fp )
     exit(0);
// 移动文件指针到这个位置,使得再读sizeof(Mask)个字节就会遇到文件结束
// 注意-(int)sizeof(Mask)虽然不是什么好的写法,但这里它确实是正确有效的
// 如果直接写-sizeof(Mask)的话,因为sizeof取得的是一个无符号数,取负号会有问题
if( fseek(fp, -(int)sizeof(Mask), SEEK_END) )
     exit(0);
// 读取sizeof(Mask)个字节到Mask
if( !fread(Mask, sizeof(Mask), 1, fp) )
     exit(0);
fclose(fp);

好的,现在请自己编辑一个图片作为mask,并用上述方法取得Mask数组,运行后观察效果。
说明:绘制虚线时可以设置factor因子,但多边形的镂空无法设置factor因子。请用鼠标改变窗口的大小,观察镂空效果的变化情况。


#include <GL/freeglut.h>
//本来OpenGL程序一般还要包含<GL/gl.h>和<GL/glu.h>
//但GLUT的头文件中已经自动将这两个文件包含了,不必再次包含。
#include <iostream>
using namespace std;
//static GLubyte Mask[128] =
//{
//     0x00, 0x00, 0x00, 0x00,    //   这是最下面的一行
//     0x00, 0x00, 0x00, 0x00,
//     0x03, 0x80, 0x01, 0xC0,    //   麻
//     0x06, 0xC0, 0x03, 0x60,    //   烦
//     0x04, 0x60, 0x06, 0x20,    //   的
//     0x04, 0x30, 0x0C, 0x20,    //   初
//     0x04, 0x18, 0x18, 0x20,    //   始
//     0x04, 0x0C, 0x30, 0x20,    //   化
//     0x04, 0x06, 0x60, 0x20,    //   ,
//     0x44, 0x03, 0xC0, 0x22,    //   不
//     0x44, 0x01, 0x80, 0x22,    //   建
//     0x44, 0x01, 0x80, 0x22,    //   议
//     0x44, 0x01, 0x80, 0x22,    //   使
//     0x44, 0x01, 0x80, 0x22,    //   用
//     0x44, 0x01, 0x80, 0x22,
//     0x44, 0x01, 0x80, 0x22,
//     0x66, 0x01, 0x80, 0x66,
//     0x33, 0x01, 0x80, 0xCC,
//     0x19, 0x81, 0x81, 0x98,
//     0x0C, 0xC1, 0x83, 0x30,
//     0x07, 0xE1, 0x87, 0xE0,
//     0x03, 0x3F, 0xFC, 0xC0,
//     0x03, 0x31, 0x8C, 0xC0,
//     0x03, 0x3F, 0xFC, 0xC0,
//     0x06, 0x64, 0x26, 0x60,
//     0x0C, 0xCC, 0x33, 0x30,
//     0x18, 0xCC, 0x33, 0x18,
//     0x10, 0xC4, 0x23, 0x08,
//     0x10, 0x63, 0xC6, 0x08,
//     0x10, 0x30, 0x0C, 0x08,
//     0x10, 0x18, 0x18, 0x08,
//     0x10, 0x00, 0x00, 0x08    // 这是最上面的一行
//};
void myDisplay(void)
{static GLubyte Mask[128];FILE* fp;fp = fopen("mask.bmp", "rb");if (!fp)exit(0);if (fseek(fp, -(int)sizeof(Mask), SEEK_END))exit(0);if (!fread(Mask, sizeof(Mask), 1, fp))exit(0);fclose(fp);glClear(GL_COLOR_BUFFER_BIT);glEnable(GL_POLYGON_STIPPLE);//启动镂空模式(使用glDisable(GL_POLYGON_STIPPLE)可以关闭之)。glPolygonStipple(Mask);glRectf(-0.5f, -0.5f, 0.0f, 0.0f);   // 在左下方绘制一个有镂空效果的正方形glDisable(GL_POLYGON_STIPPLE);glRectf(0.0f, 0.0f, 0.5f, 0.5f);     // 在右上方绘制一个无镂空效果的正方形glFlush();
}int main(int argc, char* argv[])
{glutInit(&argc, argv); //对GLUT进行初始化,这个函数必须在其它的GLUT使用之前调用一次。//其格式比较死板,一般照抄这句glutInit(&argc, argv)就可以了。glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);//设置显示方式,其中GLUT_RGB表示使用RGB颜色,//与之对应的还有GLUT_INDEX(表示使用索引颜色)。//GLUT_SINGLE表示使用单缓冲,与之对应的还有GLUT_DOUBLE(使用双缓冲)。glutInitWindowPosition(0, 0);glutInitWindowSize(400, 400);glutCreateWindow("第一个OpenGL程序");//根据前面设置的信息创建窗口。参数将被作为窗口的标题。//注意:窗口被创建后,并不立即显示到屏幕上。需要调用glutMainLoop才能看到窗口。glutDisplayFunc(&myDisplay);//调用显示函数glutMainLoop();//不断循环return 0;
}

左图时显示结果,有图为mask图像

    

小结
本课学习了绘制几何图形的一些细节:
1、点可以设置大小。
2、直线可以设置宽度;可以将直线画成虚线。
3、多边形的两个面的绘制方法可以分别设置;在三维空间中,不可见的多边形可以被剔除;可以将填充多边形绘制成镂空的样式。
了解这些细节会使我们在一些图象绘制中更加得心应手。
另外,把一些数据写到程序之外的文件中,并用专门的工具编辑之,有时可以显得更方便。

OpenGL入门-3-绘制多边形相关推荐

  1. [Python图像处理] 二十七.OpenGL入门及绘制基本图形(一)

    八年前,我正是通过学习OpenGL和C++,通过做"采蘑菇的小矮人"游戏,慢慢走上并爱上了编程.回过头来,我希望通过Python和OpenGL分享一些有趣的知识,提升您的编程兴趣, ...

  2. OpenGL入门学习[二] 绘制简单的几何图形

    OpenGL入门学习[二] 本次课程所要讲的是绘制简单的几何图形,在实际绘制之前,让我们先熟悉一些概念. 一.点.直线和多边形 我们知道数学(具体的说,是几何学)中有点.直线和多边形的概念,但这些概念 ...

  3. 【OpenGL ES】入门及绘制一个三角形

    本文首发于个人博客:Lam's Blog - [OpenGL ES]入门及绘制一个三角形,文章由MarkDown语法编写,可能不同平台渲染效果不一,如果有存在排版错误图片无法显示等问题,烦请移至个人博 ...

  4. OpenGL入门北斗星点绘制

    ** OpenGL入门–北斗星点的绘制 C++代码 唯一遇到的问题就是glFlush()这个函数的问题 #include <GL/glut.h> #include<gl/GLU.h& ...

  5. 【OpenGL】十八、OpenGL 绘制多边形 ( 绘制 GL_POLYGON 模式多边形 )

    文章目录 一.绘制 GL_POLYGON 模式多边形 二.多边形绘制顺序分析 三.相关资源 一.绘制 GL_POLYGON 模式多边形 使用 glBegin(GL_POLYGON) 设置绘制多边形 , ...

  6. SCARA——OpenGL入门学习一、二

    参考博客:http://www.cppblog.com/doing5552/archive/2009/01/08/71532.html 简介 最近开始一个机械手臂的安装调试,平面关节型机器人又称SCA ...

  7. Python pyglet 自制3D引擎入门(一) -- 绘制几何体、创建3D场景

    Python作为目前较广泛的编程语言, 用于制作3D游戏可谓得心应手.本文讲解应用Python pyglet库绘制3D场景的入门知识. 下篇:Python pyglet 自制3D引擎入门(二) – 绘 ...

  8. 最全面的openGL 入门学习

    自己在找openGL学习资料的时候,找到此篇openGL入门学习(虽然不是移动开发,但给我提供了非常好的思路),所以转一下让更多人知道,本文来自http://www.cppblog.com/doing ...

  9. OpenGL入门学习 (转)

    OpenGL入门学习 (转) 说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜 ...

最新文章

  1. 【机器学习知识体系】- 机器学习问题的一般流程
  2. 设计模式之结构型(4)-桥接模式(Bridge)
  3. 全球黑客盛会:2008年黑帽大会要闻摘要(2)
  4. JavaScript之闭包
  5. js设置html不可复制,用JS实现用户禁止WEB复制
  6. Script:查找表或索引增长的历史信息
  7. Angular2的input和output(原先的properties和events)
  8. Family.Show:一个很好玩的东东
  9. FusionCharts 3.2.1 flash 图表展示、数据钻取
  10. 【3D文件格式解析】.obj + .mtl
  11. 完美解决“运行引擎需要DX11特性等级10.0”
  12. 快速使用注解方式实现aop切面编程
  13. 20几岁要懂点经济学【笔记】
  14. GAN的Loss为什么降不下去
  15. 史上最全无线通信频率分配表
  16. mysql中存储ip地址,将ip转换为整数存储
  17. 直线检测算法博文中缺失的几个源码(Hough_line、LSD、FLD、EDlines、LSWMS、CannyLines、MCMLSD、LSM)
  18. C++ 修改注册表的方法
  19. Spring 注解读取配置文件
  20. VMware虚拟机黑屏不显示画面

热门文章

  1. 收藏!架构师需要掌握的99条铁律
  2. 银行大数据风控平台的建设要点与应用
  3. 教你使用Vue.js的DevTools来调试你的vue项目
  4. JEECG 3.6.3版本发布 企业级JAVA快速开发平台
  5. JEECG Framework 3.5.2 (快速开发平台) ACE版本发布
  6. 利用shell命令操作Memcached
  7. JEECG第16期架构培训班15号开班,每期只有10个名额!想报名的同学速度啦!
  8. Socket编程实践(11) --epoll原理与封装
  9. 数据产品-数据可视化大作“数据大屏”
  10. JVM内存的那些事,你了解多少?