OpenGL面细节

来源:互联网 发布:陕西师大网络远程教育 编辑:程序博客网 时间:2024/05/02 01:26

【原文:http://blog.sina.com.cn/s/blog_8e0502b7010198o5.html】

在OpenGL中面的基本单位是凸多边形。而一般绘制时,多边形的正面、反面两个面均以填充形式进行绘制。下面介绍绘制方式可以如何改变。(材质贴图内容太多以后再展开写)

    一、点、轮廓或实心形式
    void glPolygonMode(GLenum face,GLenum mode);
    控制一个多边形的正面和背面的绘图模式。face参数可以是GL_FRONT、GL_BACK或GL_FRONT_AND_BACK(FRONT、BACK位置不可交换);mode参数可以是GL_POINT(只画出多边形的点)、GL_LINE(轮廓)或GL_FILL(填充)。未设置则默认调用(GL_FRONT_AND_BACK,GL_FILL)。
    
    二、反转和剔除面
    大多数涉及图形的学科均将多边形的顶点以逆时针顺序排列的面约定为“正面”,但是有时我们希望将顺时针顺序定为“正面”,这时可以使用glFrontFace()函数。
    void glFrontFace(GLenum mode);
    控制多边形的正面如何决定。mode参数可以是GL_CCW(逆时针,默认)或GL_CW(顺时针)。

    有时面可能被其反面所完全遮挡,这时我们可以让OpenGL丢弃对这些遮挡面的绘制工作,减少不必要的工作是图形处理必须要做的。
    void glCullFace(GLenum mode);
    表示那些多边形的面应该被剔除。mode参数可以是GL_FRONT、GL_BACK或GL_FRONT_AND_BACK(FRONT、BACK位置不可交换)。同时为了使剔除生效,必须以GL_CULL_FACE调用glEnable()函数来启用该功能。

下面给出一个实例,来看看这三个函数的具体功能:
——————————————————————————————————————
依然将下面的代码插入第一节程序glFlush();之前
glPolygonMode(GL_FRONT,GL_POINT);//正面点形式
glBegin(GL_QUADS);               //画
  glVertex3f(-0.8f,0.8f,0.0f);   //一
  glVertex3f(-0.8f,0.4f,0.0f);   //个
  glVertex3f(-0.4f,0.4f,0.0f);   //正
  glVertex3f(-0.4f,0.8f,0.0f);   //方
glEnd();                         //形

glPolygonMode(GL_FRONT,GL_LINE); //正面轮廓形式
glBegin(GL_QUADS);               //画
  glVertex3f(-0.2f,0.8f,0.0f);   //一
  glVertex3f(-0.2f,0.4f,0.0f);   //个
  glVertex3f(0.2f,0.4f,0.0f);    //正
  glVertex3f(0.2f,0.8f,0.0f);    //方
glEnd();                         //形

glPolygonMode(GL_FRONT,GL_FILL); //还原默认值
glBegin(GL_QUADS);               //画
  glVertex3f(0.4f,0.8f,0.0f);    //一
  glVertex3f(0.4f,0.4f,0.0f);    //个
  glVertex3f(0.8f,0.4f,0.0f);    //正
  glVertex3f(0.8f,0.8f,0.0f);    //方
glEnd();                         //形

glPolygonMode(GL_FRONT,GL_LINE); //正面轮廓形式
glEnable(GL_CULL_FACE);          //启用面剔除功能
glCullFace(GL_FRONT);            //只剔除正面
glBegin(GL_QUADS);               //画
  glVertex3f(-0.8f,0.2f,0.0f);   //一
  glVertex3f(-0.8f,-0.2f,0.0f);  //个
  glVertex3f(-0.4f,-0.2f,0.0f);  //正
  glVertex3f(-0.4f,0.2f,0.0f);   //方
glEnd();

glCullFace(GL_BACK);             //只剔除背面
glBegin(GL_QUADS);               //画
  glVertex3f(-0.2f,0.2f,0.0f);   //一
  glVertex3f(-0.2f,-0.2f,0.0f);  //个
  glVertex3f(0.2f,-0.2f,0.0f);   //正
  glVertex3f(0.2f,0.2f,0.0f);    //方
glEnd();

glCullFace(GL_FRONT_AND_BACK);   //两面剔除
glBegin(GL_QUADS);               //画
  glVertex3f(0.4f,0.2f,0.0f);    //一
  glVertex3f(0.4f,-0.2f,0.0f);   //个
  glVertex3f(0.8f,-0.2f,0.0f);   //正
  glVertex3f(0.8f,0.2f,0.0f);    //方
glEnd();

glFrontFace(GL_CW);              //反转顶点方向
glPolygonMode(GL_FRONT,GL_LINE);
glCullFace(GL_FRONT);            //只剔除正面
glBegin(GL_QUADS);               //画
  glVertex3f(-0.8f,-0.4f,0.0f);  //一
  glVertex3f(-0.8f,-0.8f,0.0f);  //个
  glVertex3f(-0.4f,-0.8f,0.0f);  //正
  glVertex3f(-0.4f,-0.4f,0.0f);  //方
glEnd();

glCullFace(GL_BACK);             //只剔除背面
glBegin(GL_QUADS);               //画
  glVertex3f(-0.2f,-0.4f,0.0f);  //一
  glVertex3f(-0.2f,-0.8f,0.0f);  //个
  glVertex3f(0.2f,-0.8f,0.0f);   //正
  glVertex3f(0.2f,-0.4f,0.0f);   //方
glEnd();

glCullFace(GL_FRONT_AND_BACK);   //两面剔除
glBegin(GL_QUADS);               //画
  glVertex3f(0.4f,-0.4f,0.0f);   //一
  glVertex3f(0.4f,-0.8f,0.0f);   //个
  glVertex3f(0.8f,-0.8f,0.0f);   //正
  glVertex3f(0.8f,-0.4f,0.0f);   //方
glEnd();
glDisable(GL_CULL_FACE);         //禁用剔除功能
——————————————————————————————————————++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 运行程序:
OpenGL <wbr>Lesson <wbr>004 <wbr>—— <wbr>面细节
第一行,依次是点、轮廓和填充形式。
第二行,启用剔除设定正面是填充、背面轮廓,依次剔除正面、背面和两面。
第三行,启用并设定反转,依次剔除正面、背面和两面。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    可以看出:在可视面后的面即使剔除可视面人不可见,反转函数只反转顶点顺序,而不反转绘图模式。

    同日    阴转多云    晚上家中书房
 
    三、点画多边形
    一般情况下填充模式是用实心模式绘制的。我们也可以使用一种32*32的窗口对齐的点画模式,给多边形加上纹路。
    void glPolygonStipple(const GLubyte *mask);
    定义填充多边形的点画模式。mask参数是一个指向32*32位图的指针。后者被解释为0和1组成的掩码(可以理解为一个2位的16进制数转为8位的2进制数),1为绘制的像素,0为不绘制的像素。使用时需要以GL_POLYGON_STIPPLE为参数调用glEnable()函数。
    在网上学习时,看到的例子多以苍蝇为题材,我还是算了。换一个题材给出一个实例——中国汉字“面”。
——————————————————————————————————————
将下面的代码插入第一节程序glFlush();之前
GLubyte polygon[] = { //看得出这数组是个“面”字吗?下面用二进制翻译一下    
0x00,0x00,0x00,0x00,  //0000 0000 0000 0000 0000 0000 0000 0000
0x00,0x00,0x00,0x00,  //0000 0000 0000 0000 0000 0000 0000 0000
0x00,0x00,0x00,0x00,  //0000 0000 0000 0000 0000 0000 0000 0000
0x0E,0x00,0x00,0x70,  //0000 1110 0000 0000 0000 0000 0111 0000
0x0F,0xFF,0xFF,0xF0,  //0000 1111 1111 1111 1111 1111 1111 0000
0x0F,0xFF,0xFF,0xF0,  //0000 1111 1111 1111 1111 1111 1111 0000
0x0F,0xFF,0xFF,0xF0,  //0000 1111 1111 1111 1111 1111 1111 0000
0x0E,0x38,0x1C,0x70,  //0000 1110 0011 1000 0001 1100 0111 0000
0x0E,0x38,0x1C,0x70,  //0000 1110 0011 1000 0001 1100 0111 0000
0x0E,0x38,0x1C,0x70,  //0000 1110 0011 1000 0001 1100 0111 0000
0x0E,0x3F,0xFC,0x70,  //0000 1110 0011 1111 1111 1100 0111 0000
0x0E,0x3F,0xFC,0x70,  //0000 1110 0011 1111 1111 1100 0111 0000
0x0E,0x3F,0xFC,0x70,  //0000 1110 0011 1111 1111 1100 0111 0000
0x0E,0x38,0x1C,0x70,  //0000 1110 0011 1000 0001 1100 0111 0000
0x0E,0x38,0x1C,0x70,  //0000 1110 0011 1000 0001 1100 0111 0000
0x0E,0x38,0x1C,0x70,  //0000 1110 0011 1000 0001 1100 0111 0000
0x0E,0x3F,0xFC,0x70,  //0000 1110 0011 1111 1111 1100 0111 0000
0x0E,0x3F,0xFC,0x70,  //0000 1110 0011 1111 1111 1100 0111 0000
0x0E,0x3F,0xFC,0x70,  //0000 1110 0011 1111 1111 1100 0111 0000
0x0E,0x38,0x1C,0x70,  //0000 1110 0011 1000 0001 1100 0111 0000
0x0E,0x38,0x1C,0x70,  //0000 1110 0011 1000 0001 1100 0111 0000
0x0F,0xFF,0xFF,0xF0,  //0000 1111 1111 1111 1111 1111 1111 0000
0x0F,0xFF,0xFF,0xF0,  //0000 1111 1111 1111 1111 1111 1111 0000
0x0F,0xFF,0xFF,0xF0,  //0000 1111 1111 1111 1111 1111 1111 0000
0x00,0x0F,0x00,0x00,  //0000 0000 0000 1111 0000 0000 0000 0000
0x00,0x0F,0x00,0x00,  //0000 0000 0000 1111 0000 0000 0000 0000
0x00,0x07,0x80,0x00,  //0000 0000 0000 0111 1000 0000 0000 0000
0x3F,0xFF,0xFF,0xFC,  //0011 1111 1111 1111 1111 1111 1111 1100
0x3F,0xFF,0xFF,0xFC,  //0011 1111 1111 1111 1111 1111 1111 1100
0x3F,0xFF,0xFF,0xFC,  //0011 1111 1111 1111 1111 1111 1111 1100
0x00,0x00,0x00,0x00,  //0000 0000 0000 0000 0000 0000 0000 0000
0x00,0x00,0x00,0x00   //0000 0000 0000 0000 0000 0000 0000 0000
};
glEnable(GL_POLYGON_STIPPLE);   //启用点画多边形功能
glPolygonStipple(polygon);      //定义polygon数组为当前点画模式 
glBegin(GL_QUADS);              //画
  glVertex3f(0.5f,0.5f,0.0f);   //一
  glVertex3f(0.5f,-0.5f,0.0f);  //个
  glVertex3f(-0.5f,-0.5f,0.0f); //正
  glVertex3f(-0.5f,0.5f,0.0f);  //方
glEnd();                        //形
glDisable(GL_POLYGON_STIPPLE);  //关闭点画多边形功能
——————————————————————————————————————
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
运行程序:
OpenGL <wbr>Lesson <wbr>004 <wbr>—— <wbr>面细节
很犀利的一百个“面”字。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    有一点是要注意,这个模版数组中的纹路在默认设置下,要求倒置的(精确点说是你所需纹路旋转180度后的样子),关于如何改变这个默认设置,以后再写。

    四、标记多边形的边界边

    前面第二节讲过OpenGL只能渲染凸多边形,那凹多边形咋办?一般是将它分解为多个凸多边形的和,然后分别绘制。但是,这时若是要求绘制其轮廓,便会得到多余的线。解决这一问题,我们要用以下函数。
    void glEdgeFlag(GLboolean flag);
    void glEdgeFlagv(const GLboolean *flag);
    表示一个顶点是否被设置为多边形的一条边的起点。flag参数可以为GL_TRUE(是起点,默认)或GL_FALSE(不是起点)。但是无论哪种,点都可以是边的终点。

    2013年1月31日    晴    午间休息
    
    看了前面那段,尼玛,怎么有一种“攻”和“受”的感觉。
    光说不练假把式,继续给出实例。
——————————————————————————————————————
    将下面的代码插入第一节程序glFlush();之前
glBegin(GL_TRIANGLES);             //给出一个凹多边形           
  glVertex3f(-0.8f,0.6f,0.0f);
  glVertex3f(-0.9f,0.0f,0.0f);
  glVertex3f(-0.7f,0.0f,0.0f);

  glVertex3f(-0.9f,0.0f,0.0f);
  glVertex3f(-0.7f,-0.6f,0.0f);
  glVertex3f(-0.5f,0.0f,0.0f);

  glVertex3f(-0.7f,0.0f,0.0f);
  glVertex3f(-0.5f,0.0f,0.0f);
  glVertex3f(-0.6f,0.6f,0.0f);
glEnd();

glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);//改用轮廓形式,重画
glBegin(GL_TRIANGLES);
  glVertex3f(-0.1f,0.6f,0.0f);
  glVertex3f(-0.2f,0.0f,0.0f);
  glVertex3f(0.0f,0.0f,0.0f);

  glVertex3f(-0.2f,0.0f,0.0f);
  glVertex3f(0.0f,-0.6f,0.0f);
  glVertex3f(0.2f,0.0f,0.0f);

  glVertex3f(0.0f,0.0f,0.0f);
  glVertex3f(0.2f,0.0f,0.0f);
  glVertex3f(0.1f,0.6f,0.0f);
glEnd();

glBegin(GL_TRIANGLES);                  //使用glEdgeFlag()后,重画
  glEdgeFlag(GL_TRUE);
  glVertex3f(0.6f,0.6f,0.0f);
  glEdgeFlag(GL_FALSE);
  glVertex3f(0.5f,0.0f,0.0f);
  glEdgeFlag(GL_TRUE);
  glVertex3f(0.7f,0.0f,0.0f);

  glVertex3f(0.5f,0.0f,0.0f);
  glVertex3f(0.7f,-0.6f,0.0f);
  glEdgeFlag(GL_FALSE);
  glVertex3f(0.9f,0.0f,0.0f);

  glVertex3f(0.7f,0.0f,0.0f);
  glEdgeFlag(GL_TRUE);
  glVertex3f(0.9f,0.0f,0.0f);
  glVertex3f(0.8f,0.6f,0.0f);
glEnd();
——————————————————————————————————————
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
运行程序:
OpenGL <wbr>Lesson <wbr>004 <wbr>—— <wbr>面细节
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
本节知识点:
1、面细节简介
2、相关函数的使用

0 0
原创粉丝点击