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(120,100); glVertex2f(280,100); glVertex2f(150,240); glEnd(); glFlush (); }
下面是 glShadeModel(GL_SMOOTH)效果
void display(void) { glClear(GL_COLOR_BUFFER_BIT); glColor3f (1.0, 0.0, 0.0); glBegin(GL_POLYGON); glVertex2f(120,100); glColor3f (1.0, 1.0, 0.0); glVertex2f(280,100); glColor3f (0.0, 1.0, 1.0); glVertex2f(150,240); 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;