1. 剔除多边形表面

  在三维空间中,一个多边形虽然有两个面,但我们无法看见背面的那些多边形,而一些多边形虽然是正面的,但被其他多边形所遮挡。如果将无法看见的多边形和可见的多边形同等对待,无疑会降低我们处理图形的效率

  在这种时候,可以将不必要的面剔除。

  首先,使用glEnable(GL_CULL_FACE);来启动剔除功能(使用glDisable(GL_CULL_FACE)可以关闭之) 
  然后,使用glCullFace来进行剔除。 
  glCullFace的参数可以是GL_FRONT,GL_BACK或者GL_FRONT_AND_BACK,分别表示剔除正面、剔除反面、剔除正反两面的多边形。 
  注意:剔除功能只影响多边形,而对点和直线无影响。例如,使用glCullFace(GL_FRONT_AND_BACK)后,所有的多边形都将被剔除,所以看见的就只有点和直线

2. 设定正面与反面

  可以使用glFrontFace函数来调换正面与反面的概念

glFrontFace(GL_CCW);  // 设置CCW方向为“正面”,CCW即CounterClockWise,逆时针 
glFrontFace(GL_CW);   // 设置CW方向为“正面”,CW即ClockWise,顺时针

  下面为使用glFrontFace(GL_CCW)的效果,以顺时针绘制则是反面,逆时针绘制则是正面

  下面设定:以顺时针绘制,则为反面,且绘制为线;以逆时针绘制,则为正面,且绘制填充方式

glFrontFace(GL_CCW)// 一般都是采用逆时针绘制的面为正面
// 设置正面为填充模式
glPolygonMode(GL_FRONT, GL_FILL);
// 设置反面为线形模式
glPolygonMode(GL_BACK, GL_LINE); // 设置逆时针绘制一个正方形(左下角逆时针绘制,正面,填充)
glBegin(GL_POLYGON);
glVertex2f(-0.5f, -0.5f);
glVertex2f(0.0f, -0.5f);
glVertex2f(0.0f, 0.0f);
glVertex2f(-0.5f, 0.0f);
glEnd();
// 设置顺时针绘制一个正方形(右上角顺时针绘制,反面,线)
glBegin(GL_POLYGON);
glVertex2f(0.0f, 0.0f);
glVertex2f(0.0f, 0.5f);
glVertex2f(0.5f, 0.5f);
glVertex2f(0.5f, 0.0f);
glEnd();

通过切管正反面进行切换设置:

如果之前执行替换为:glFrontFace(GL_CW),即顺时针为正面,则左上角为正面,效果即切换

面为使用glFrontFace(GL_CW)的效果

3. 设置绘制模式:

该函数 函数用于控制多边形的显示方式,需要特别注意的是OpenGL3.1只接受GL_FRONT_AND_BACK作为face的值,并且不管是多边形的正面还是背面都以相同的方式渲染。

使用glPolygonMode函数来设置模式,

函数原型:原型是:void glPolygonMode(GLenum face,GLenum mode);

  face这个参数确定显示模式将适用于物体的哪些部分,控制多边形的正面和背面的绘图模式:

  GL_FRONT表示显示模式将适用于物体的前向面(也就是物体能看到的面)
  GL_BACK表示显示模式将适用于物体的后向面(也就是物体上不能看到的面)
  GL_FRONT_AND_BACK表示显示模式将适用于物体的所有面
  mode这个参数确定选中的物体的面以何种方式显示(显示模式)
  GL_POINT表示只显示顶点,多边形用点显示
  GL_LINE表示显示线段,多边形用轮廓显示
  GL_FILL表示显示面,多边形采用填充形式
  例:
  glPolygonMode(GL_FRONT, GL_LINE);表示物体的前向面用线段显示

4 着色模型

  使用glShadeModel函数指定着色模型,默认为GL_FLAT即单色,GL_SMOOTH则可以使得颜色平滑,即渐变色

  默认情况下,是采用单色:

void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f (1.0, 0.0, 0.0);//设置多边形为红色
glBegin(GL_POLYGON);
glVertex2f(,);
glVertex2f(,);
glVertex2f(,);
glEnd();
glFlush ();
}

下面是 glShadeModel(GL_SMOOTH)效果

void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f (1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex2f(,);
glColor3f (1.0, 1.0, 0.0);
glVertex2f(,);
glColor3f (0.0, 1.0, 1.0);
glVertex2f(,);
glEnd();
glFlush ();
}

 5. 在OpenGL中使用颜色混合

  调用glEnable(GL_BLEND)开始混合功能,glDisable(GL_BLEND)关闭混合功能 如果开启,则之后使用glBlendFunc 函数,选择混合选项起作用:

  Blend 混合是将源色和目标色以某种方式混合生成特效的技术。混合常用来绘制透明或半透明的物体。在混合中起关键作用的α值实际上是将源色和目标色按给定比率进行混合,以达到不同程度的透明。α值为0则完全透明,α值为1则完全不透明。混合操作只能在RGBA模式下进行,颜色索引模式下无法指定α值。物体的绘制顺序会影响到OpenGL的混合处理。

glEnable( GL_BLEND );   // 启用混合

glDisable( GL_BLEND );  // 禁用关闭混合

获得混合的信息

glGet( GL_BLEND_SRC );

glGet( GL_BLEND_DST );

glIsEnable( GL_BLEND );

glBlendFunc( GLenum sfactor源中原有的比值 , GLenum dfactor设置的目标比值 );         // 混合函数

    sfactor 源混合因子

    dfactor 目标混合因子

混合因子枚举:

如下:

glBlendFunc( GL_ONE , GL_ZERO );        // 源色将覆盖目标色,在颜色上绘制没有效果

glBlendFunc( GL_ZERO , GL_ONE );        // 目标色将覆盖源色,完全覆盖

glBlendFunc( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ); // 是最常使用的

原色计算:

若源色为 ( 1.0 , 0.9 , 0.7 , 0.8 )

源色使用 GL_SRC_ALPHA

即 0.8*1.0 , 0.8*0.9 , 0.8*0.8 , 0.8*0.7

结果为 0.8 , 0.72 , 0.64 , 0.56

目标色计算:

目标色为 ( 0.6 , 0.5 , 0.4 , 0.3 )

目标色使用GL_ONE_MINUS_SRC_ALPHA

即 1 - 0.8 = 0.2

0.2*0.6 , 0.2*0.5 , 0.2*0.4 , 0.2*0.3

结果为 0.12 , 0.1 , 0.08 , 0.06

由此而见,使用这个混合函数,源色的α值决定了结果颜色的百分比

这里源色的α值为0.8,即结果颜色中源色占80%,目标色占20%。

将多边形从远至近排列,并使用以下函数

glBlendFunc( GL_SRC_ALPHA_SATURATE , GL_ONE );

glEnable( GL_POLYGON_SMOOTH );

可以优化多边形反走样;但必须有α位平面,以用来存储累加的覆盖值。

6 混合 3D 物体

混合 3D 物体时,基本原理和混合2D物体一样,但需要将深度检测关闭或设置为只读。

因为深度检测会剔除被遮挡的部分物体

glEnable( GL_DEPTH_TEST );          // 启用深度缓存

glDisable( GL_DEPTH_TEST );         // 禁用深度缓存

glDepthMask( GL_FALSE );              // 深度缓存为 只读

glDepthMask( GL_TRUE );               // 深度缓存为 读/写

按以下步骤,可以在 3D 场景中使用混合和深度检测

1、使用深度检测

2、绘制不透明的物体

3、设只读 深度检测

4、绘制半透明的物体

5、设 读/写 深度检测

以下对混合算法进行测试,统一使用glBlendFunc(GL_SRC_ALPHA,GL_ONE);模式。

glClearColor(0.0f,1.0f,0.0f,0.5f);               //绿色背景(目标)、先放入帧缓冲区

glColor4f(1.0f,0.0f,0.0f,0.5f);                    //矩形颜色(源色)、片段

计算结果:颜色混合之后的结果:

(0.5f, 1.0f,0.0f,0.75f)

结果:

1、背景色也参与混合过程;

2、利用绿色背景测试可得,RGBA中的A值对单一颜色显示没有效果,但混合和

透明是依靠A值计算的;

3、当输入颜色值为RGB时,混合计算时,A值默认为0.0。

7. 反走样设置

  在光栅图形显示器上绘制非水平且非垂直的直线或多边形边界时,或多或少会呈现锯齿状或台阶状外观。这是因为直线、多边形、色彩边界等是连续的,而光栅则是由离散的点组成在光栅显示设备上表现直线、多边形等,必须在离散位置采样。由于采样不充分重建后造成的信息失真,就叫走样(aliasing)。而用于减少或消除这种效果的技术,就称为反走样(antialiasing)

   计算机生成图像时通常存在三种走样现象中的两种:(1)锯齿形边以及图形细节,(2)纹理绘制失真(3)第三种现象出现在显示非常微小对象的场合。

  基本上反走样方法可分为两类。

(1)第一类是提高分辨率 即增加采样点(提高采样频率)

  然而,CRT光栅扫描设备显示非常精细光栅的能力是有限的,因此人们通常是在较高分辨率上对光栅进行计算,然后采用某种平均算法(滤除高频分量)得到较低分辨率的象素的属性,并显示在分辨率较低的显示器上 。这种方法称为超采样或后置滤波。

(2)另一类反走样是把像素作为一个有限区域,对区域采样来调整像素的亮度,以光顺边界来减小锯齿现象 J。这种方法等价于图像的前置滤波。OpenGL的反走样函数:

  简单地说,计算机通过离散(不连续)的像素来绘制图形,想象一下,真实世界中,我们画直线,是比连续画的,还是一个点一个点画的?计算机就是一个点一个点画的(很小的矩形).

  

  而我们实际想看到的是一个圆点,而不是矩形

  

  OpenGL实现反走样需要满足两个条件,(1)是启用混合,(2)启用针对几何图元的反走样处理。

  在OpenGL中,可通过函数glHint()来对图像质量绘制速度之间的权衡作一些控制,其函数形式为:

   void glHint(GLenum target,GLenum hint);

target 意义
          GL_POINT_SMOOTH_HINT 指定点、
          GL_LINE_SMOOTH_HINT 线、
           GL_POLYGON_SMOOTH_HINT 多边形的采样质量
           GL_FOG_HINT 指出雾化计算是按每个象素进行(GL_NICEST),还是按每个顶点进行(GL_FASTEST)
          GL_PERSPECTIVE_CORRECTION_HINT 指定颜色纹理插值的质量
          其中GL_PERSPECTIVE_CORRECTION_HINT用以纠正单纯线性插值带来的观察错误。

      其中hint可以是:
          GL_FASTEST 给出最有效的选择
          GL_NICEST 给出最高质量的选择
          GL_DONT_CARE 没有选

其中: 参数target说明控制什么的行为,即要使用什么图元进行反走样处理:

    GL_POINT_SMOOTH_HINT、GL_LINE_SMOOTH_HINT和GL_POLYGON_SMOOTH_HINT分别指定点、线和多边形的采样质量

    GL_FOG_HINT指出雾是按像素进行(GL_NICEST)还是按顶点进行(GL_FASTEST)

    GL_PERSPECTIVE_CORRECTION_HINT指定了颜色纹理插值的质量并可纠正由单纯线性插值所带来的一些视觉错误。

使用注意:

   虽然在OpenGL的颜色索引模式下也可以实现反走样,但仍建议在RGBA模式下进行。

因此使用反走样的步骤如下:

  (1)对图元进行反走样时也要先调用glEnable()函数启动反走样(其参数为GL_POINT、GL_LINE_SMOOTH或GL_POLYGON_SMOOTH),即可以对“点, 线,多边形”进行反走样处理,确保其更光滑。

  (2)使用在使用glHint 来分别对相应的图元设置反走样的策略(效率与效果的权衡)

  (3)推荐在RGBA模式执行反走样,则设置开启“混合功能”,即glEnable(GL_BLEND);开启,并使用GL_SRC_ALPHA和GL_ONE_MINUS_SRC_ALPHA分别作为源和目的因子。

反走样的代码示例如下:

//(1)在反走样之前,先使用 glEnable 对指定图元使用反走样对象:可选的参数有(其参数为GL_POINT、GL_LINE_SMOOTH或GL_POLYGON_SMOOTH)

 glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH); //(2)在使用glHint 来分别对相应的图元设置反走样的策略(效率与效果的权衡)
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); // Make round points, not square points
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Antialias the lines //(3)RGBA mode antialias need cooperate with blend function.
//RGBA模式,则反走样要与“混合功能”配合使用,
glEnable(GL_BLEND); //启动混合功能
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //设定混合函数

endl;

OpenGL中的常用绘图的命令与效果(经验设置)的更多相关文章

  1. cmd中测试常用到的命令汇总

    1.最常用的 ping +ip 2.测试到远程服务器之间是否通的命令 telnet +ip +端口 3.路由跟踪,通过跟踪可以找到到哪地方不通 tracert ip      linux系统  tra ...

  2. 工作中一些常用的linux命令

    问题一: 绝对路径用什么符号表示?当前目录.上层目录用什么表示?主目录用什么表示? 切换目录用什么命令? 答案:绝对路径:如/etc/init.d当前目录和上层目录:./  ../主目录:~/切换目录 ...

  3. JAVA swing中JPanel如何实现分组框的效果以及设置边框颜色 分类: Java Game 2014-08-16 12:21 198人阅读 评论(0) 收藏

    代码如下: import java.awt.FlowLayout; import java.awt.Frame; import java.awt.GridLayout; import javax.sw ...

  4. 测试或运维工作过程中最常用的几个linux命令?

     大家在测试工作过程中,可能会遇到需要你去服务器修改一些配置文件,譬如说某个字段的值是1 则关联老版本,是0则关联新版本,这时候你可能就需要会下vi的命令操作:或者查看session设置的时长,可能需 ...

  5. 在工作中常用的Linux命令

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 之前写过一篇 < 在公司做的项目和自己在学校做 ...

  6. Qt Creator中的3D绘图及动画教程(参照NeHe)

    Qt Creator中的3D绘图及动画教程(参照NeHe) http://blog.csdn.net/cly116/article/details/47184729 刚刚学习了Qt Creator,发 ...

  7. 【opengl】OpenGL中三维物体显示在二维屏幕上显示的变换过程

    转自:http://blog.sina.com.cn/s/blog_957b9fdb0100zesv.html 为了说明在三维物体到二维图象之间,需要经过什么样的变换,我们引入了相机(Camera)模 ...

  8. WPF中的常用布局 栈的实现 一个关于素数的神奇性质 C# defualt关键字默认值用法 接口通俗理解 C# Json序列化和反序列化 ASP.NET CORE系列【五】webapi整理以及RESTful风格化

    WPF中的常用布局   一 写在开头1.1 写在开头微软是一家伟大的公司.评价一门技术的好坏得看具体的需求,没有哪门技术是面面俱到地好,应该抛弃对微软和微软的技术的偏见. 1.2 本文内容本文主要内容 ...

  9. Linux上,最常用的一批命令解析【10年精选】

    原文链接:https://mp.weixin.qq.com/s/QkqHexs_kOgy_5OwbwyFww 建议点击原文链接查看 不同平台linux客户端连接工具分享: windos终端神器:SSH ...

随机推荐

  1. laravel框架数据迁移

    迁移就像数据库的版本控制,允许团队简单轻松的编辑并共享应用的数据库表结构,迁移通常和Laravel 的 schema 构建器结对从而可以很容易地构建应用的数据库表结构.如果你曾经告知小组成员需要手动添 ...

  2. url中含有%

    Server.UrlEncode(“参数”)也可以使用javascript 的编码方式href="页面?name=encodeURI("参数")传送页代码编码 接收页代码 ...

  3. 冒泡排序(js版)

    基本思想:两两比较相邻记录的关键字,如果反序则交换,直至没有反序为止. 最初的冒泡排序(初级版): //从小到大 function BubbleSort(arr){ var i,j,temp; for ...

  4. CF487E Tourists - Tarjan缩点 + 树剖 + multiset

    Solution 先Tarjan求出点双联通分量 并缩点. 用$multiset$维护 点双内的最小点权. 容易发现, 点双内的最小点权必须包括与它相连的割边的点权. 所以我们必须想办法来维护. 所以 ...

  5. POJ 3041.Asteroids 最小顶点覆盖

    Asteroids Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22905   Accepted: 12421 Descr ...

  6. djiango控制语句

    {# 从0开始的索引#} {% for foo in value %} {# 从0开始的索引#} <p>{{ forloop.counter0 }}: {{ foo }}</p> ...

  7. Servlet会话管理一(URL重写和表单隐藏域)

    会话可以简单的理解为客户端用户打开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器的整个过程称为一个会话.即一个客户端用户和服务器端进行通讯的过程,也是客户端和服务器端之间的数据传 ...

  8. boost timer代码学习笔记

    socket连接中需要判断超时 所以这几天看了看boost中计时器的文档和示例 一共有五个例子 从简单的同步等待到异步调用超时处理 先看第一个例子 // timer1.cpp: 定义控制台应用程序的入 ...

  9. vs2008 安装部署 启动项

    具体操作办法如下: 鼠标右键安装项目->视图->注册表 依次创建键: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion ...

  10. MathExam

    MathExam 一.预估与实际 PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟) Planning 计划 575 605 • Est ...