OpenGL反走样(转载自:曾经白云飞的BLOG)

转载 2015年07月08日 10:18:58

6.2 反走样

void glHint(GLenum target, GLenum hint);    // 控制OpenGL的某些行为
参数target是要控制的行为
参数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_PERSPECTIV_CORRECTION_HINT----颜色和纹理坐标插值的质量
GL_GENERATE_MIPMAP_HINT----自动生成的mipmap的质量和性能
GL_TEXTURE_COMPRESSION_HINT----纹理图案的压缩质量和性能.


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

6.2.1 点和直线的反走样

两种处理点和直线反走样的方法:
1) 使用参数GL_POINT_SMOOTH或GL_LINE_SMOOTH调用函数glEnable(), 以启用反走样功能.使用函数glHint()提出有关质量的建议.
2) 使用多重采样.

1. RGBA模式下的反走样
在RGBA模式中, 需要启用混合功能. 最常用的混合因子是GL_SRC_ALPHA(源)和GL_ONE_MINUS_SRC_ALPHA(目标)或GL_ONE(目标).
使用alpha的值越高, 反走样效果越明显.

2. 颜色索引模式下的反走样
由于颜色索引后的4位表示覆盖比率,因此需要加载16个相邻的索引(第1个必须是16的倍数), 对应的颜色从背景色渐变到物体的颜色.
使用第一个索引值对应的颜色清空颜色缓存, 然后使用你加载的颜色绘制点或直线.

使用颜色索引的时候,程序报错
pixel format with necessary capabilities not found.

将经过反走样处理的点和直线同未经过反走样处理的存储在深度缓存中的多边形进行混合. 首先绘制多边形, 然后将深度缓存设置为只读, 并绘制点和直线.

6.2.2 使用多重采样对几何图元进行反走样处理

多重采样是一种使用更多的颜色,深度和模板信息(样本)对OpenGL图元(点,直线,多边形,位图和图像)进行反走样处理的技术.
每个片元都有多种颜色, 多个深度值和多组纹理坐标. 计算是分散在多个取样位置. 计算反走样覆盖比例时, 使用存储在多重取样缓存中的样本.
多重采样非常适合用于多边形的反走样处理,无需确定物体的绘制顺序.
如何使用多重采样:
(1) 打开一个支持多重采样的窗口. 如果有GLUT函数库, 则调用一下函数
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_MULTISAMPLE);
(2) 打开窗口后, 需要确定它是否支持多重采样.
查询变量GL_SAMPLE_BUFFERS返回1, 变量GL_SAMPLES返回的值大于1, 则可以使用多重采样.
GLint bufs, samples;
glGetIntegerv(GL_SAMPLE_BUFFERS, &bufs);
glGetIntegerv(GL_SAMPLES, &samples);
(3) 打开多重采样,可调用下述函数
glEnable(GL_MULTISAMPLE);

注: 要查询GL_SAMPLE_BUFFERS_ARB的话,需要用glew.h头文件.
我的电脑不支持多重采样....查询的值都为0

如果多重采样功能被启用,且有多重采样缓存, 点,直线和多边形将生成供反走样处理使用的片元.

alpha值和多重采样覆盖比例
默认多重采样在计算片元覆盖比例时不考虑alpha值, 除非启用了以下模式之一:
1) GL_SAMPLE_ALPHA_TO_COVERAGE: 使用片元的alpha来计算最终的覆盖比率
2) GL_SAMPLE_ALPHA_TO_ONE: 将片元的alpha值设置为最大值(1),然后使用这个值来计算覆盖比率
3) GL_SAMPLE_COVERAGE: 将函数glSampleCoverage()设置的值与计算得到的覆盖比例进行AND运算.
void glSampleCoverage(GLclampf value, GLboolean invert);
设置在计算多重采样覆盖比率时用于解释alpha值的参数
value: GL_SAMPLE_COVERAGE或GL_SAMPLE_ALPHA_TO_COVERAGE启用时使用的临时覆盖比例.
invert:对临时覆盖比例和片元覆盖比例执行AND运算之前,是否需要将临时覆盖比例执行按位反转.

6.2.3 多边形的反走样

使用参数GL_POINT或GL_LINE调用函数glPolygonMode()时, 将对点或直线进行反走样处理.

要对多个多边形进行反走样处理, 必须按从前到后的顺序排列多边形, 然后使用调用函数glBlendFunc()将源混合因子设置为GL_SRC_ALPHA_SATURATE, 目标为GL_ONE.
RGBA模式下, 多边形的反走样处理使用alpha值来表示多边形边的覆盖比例; 同时需要使用参数GL_POLYGON_SMOOTH来调用函数glEnable();
也可给GL_POLYGON_SMOOTH_HINT指定一个值.

对重叠的边进行混合:
首先,禁用深度缓存
然后将源混合因子设置为GL_SRC_ALPHA_SATURATE, 目标混合因子设置为GL_ONE;

最后,在绘制多边形之前, 需要按从前到后的顺序对场景中所有的多边形进行排序.

6.3 雾

将雾效用于点和直线也被称为深度提示(depth-cuing)

6.3.1 使用雾

使用参数GL_FOG调用函数glEnable()以启用雾效, 并使用函数glFog*()指定雾颜色和控制雾密度的方程.还可以使用参数GL_FOG_HINT调用glHint().

6.3.2 雾方程

void glFog(if)(GLenum pname, TYPE param);
void glFog(if)v(GLenum pname, TYPE* param);

pname: GL_FOG_MODE, GL_FOG_DENSITY, GL_FOG_START, GL_FOG_END
param: GL_FOG_MODE -- GL_EXP(默认), GL_EXP2, GL_LINEAR
       GL_FOG_DENSITY -- density 默认值为1
       GL_FOG_sTART , GL_FOG_END -- 默认值为0, 1
RGBA模式下, pname --- GL_FOG_COLOR, param则指向颜色值.
颜色索引模式下, pname --- GL_FOG_INDEX, param指定颜色索引.

1. RGBA模式下的雾效
雾效因子f计算最终的颜色
C = fCi + (1-f)Cf
Ci是片元的RGBA值,Cf是使用参数GL_FOG_COLOR指定的雾颜色
2. 颜色索引模式下的雾效
I = Ii + (1-f)If
其中Ii是片元的颜色索引, If是使用参数GL_FOG_INDEX指定的雾的颜色索引.

程序不支持颜色索引模式...

3. 雾坐标
调用glFog(GL_FOG_COORDINATE_SOURCE, GL_FOG_COORDINATE),然后显式地指定每个顶点的z值.用函数glFogCoord*().
void glFogCoord(fd)(TYPE z);
void glFogCoord(fd)v(TYPE *z);
其中z必须大于0

书中的例子使用了扩展,解决方法:
1.定义下面两个宏定义,本来这两个宏在glew.h中定义的,不过包含了glew.h的话,就不能使用wglGetProcAddress函数,只好自己定义了.
#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450
#define GL_FOG_COORDINATE_EXT 0x8451
2. 要包含头文件
#include <gl\glext.h>
3. 有以下语句
PFNGLFOGCOORDFEXTPROC glFogCoordfEXT = NULL;
glFogCoordfEXT = (PFNGLFOGCOORDFEXTPROC) wglGetProcAddress("glFogCoordfEXT");
glFogCoordfEXT(f1);

 

 

6.4 点参数

可使用glPointSize()和glEnable(GL_POINT_SMOOTH)来绘制大型的圆点, 并使用雾效来实现距离改变的效果. 但是, 不能在glBegin()和glEnd()之间调用函数glPointSize().
因此要改变不同点的大小很困难. 必须动态地重新计算点的大小, 并根据大小重新对点进行分组, 以最大限度地提高性能.
点参数能够根据图元距离视点的距离, 自动改变其大小和亮度. 要指定点图元的大小和alpha分量(用于控制亮度)的衰减系统, 可使用函数glPointParameterf*().
void glPointParameterf(GLenum pname, GLfloat param);
void glPointParameterfv(GLenum pname, GLfloat* param);

设置与渲染点图元相关的值
如果pname为GL_POINT_DISTANCE_ATTENUATION, param将是一个包含三个元素(a,b和c)的浮点数组.
这三个元素分别是根据眼坐标距离d对点的大小和亮度进行衰减的常量系统, 线性系数和二次系数:
derivedSize = clamp(size*(1/(a+b*d+c*d*d))的平方根)
如果pname为GL_POINT_SIZE_MIN或GL_POINT_SIZE_MAX, param为点大小截取范围的下限或上限.
如果多重采样被启用, 且pname为GL_FADE_THRESHOLD_SIZE, param降为另一种有关大小的下限(threshold). 如果derivedSize < threshold. 将按下述方式计算fade因子.
该因子用于调整点的alpha值,从而降低其亮度:
fade = (derivedSize / threshold)的平方
点大小的计算方式类似于定位光源的衰减计算方式

当用户选择线性或二次衰减方式时, 如果视点离点图元非常近, 除数将为小数, 导致计算得到的点大于实际大小, 为避免这种情况,可以增大常量衰减系数
或用参数GL_POINT_SIZE_MAX指定一个最大值.

由于希望点不是方形,可启用反走样:
    glEnable(GL_POINT_SMOOTH);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

 

6.5 多边形偏移

要突出实体的边, 可以先使用多边形模式GL_FILL来绘制物体, 然后使用多边形模式GL_LINE和不同的颜色再次绘制该物体.

缝合 --- 相同顶点之间的直线和多边形边, 其像素的深度值并不相同, 导致直线有时在相应多边形的前面,有时在后面.

启用多边形偏移的方式有3种: GL_FILL, GL_LINE和GL_POINT.

使用合适的参数来调用glEnable()---GL_POLYGON_OFFSET_FILL, GL_POLYGON_OFFSET_LINE, GL_POLYGON_OFFSET_POINT

还必须函数调用glPolygonMode()来设置当前的多边形光栅化方法:

void glPolygonOffset(GLfloat factor, GLfloat units);

多边形偏移被启用时, 将每个片元的深度值加上一个计算得到的偏移值, 这种操作是在深度测试以及将深度值写入深度缓存之前完成的.偏移值的计算公式如下:

n = m*factor + r*units

其中m是多边形的最大深度斜率, r是确保窗口坐标深度值能够被区分开来的最小值. r是一个随OpenGL实现而异的常量.

深度斜率指的是,当你穿越多边形时, z值的变化量与x或y坐标的变化量之间的商.

m = max{|dV/ds|, |dV/dt|}


与近裁剪面和远裁剪面平行的多边形深度斜率为0.
对于深度斜率接近0的多边形,只需要使用一个很小的恒定偏移量.
调用glPolygonOffset(),将参数factor和units分为指定为0.0和1.0,可以获得很小的恒定偏移量.

当深度斜率比0大得多的时候,将参数factor设置为很小的非零值(如0.75或1.0),可能足以得到不同的深度值, 从而消除不美观的缝合现象.

在有些情况下,参数factor和units都设置为1.0并不能满足要求. 如用于突出多边形边的直线的线宽大于1,可能需要加大参数factor的值.
另外透视投影时需要找到合适的factor值.

多边形偏移的图形

未偏移的图形

相关文章推荐

OpenGL:反走样

转载自:http://blog.csdn.net/d04421024/article/details/4852698 由于计算机以离散点生成图形,生成图形必然与真实景物存在差距,这种差距表现为:...

OpenGL反走样/抗锯齿实例

1. 反走样         在光栅图形显示器上绘制非水平且非垂直的直线或多边形边界时,或多或少会呈现锯齿状或台阶状外观。这是因为直线、多边形、色彩边界等是连续的,而光栅则是由离散的点组成,在光栅显...

Opengl实现反走样的时钟

  • 2012-05-03 16:54
  • 2.09MB
  • 下载

OpenGL 2D 线 反走样 高效

  • 2013-07-29 16:35
  • 2.86MB
  • 下载

OpenGL(十八) 顶点数组和抗锯齿(反走样)设置

顶点数组函数可以在一个数组里包含大量的与顶点相关的数据,并且可以减少函数的调用。使用顶点数组需要先启用顶点数组功能,使用glEnableClientState函数启用顶点数组,参数可以是GL_VERT...
  • dcrmg
  • dcrmg
  • 2016-11-23 21:50
  • 432

【Qt OpenGL教程】21:线、反走样、正投影和简单的声音

这次教程中,我们将介绍线、反走样、正投影和简单的声音,这是第一个大教程,希望这一课的东西大家能够喜欢。这次教程中,我们最终会实现一个不错的2D游戏!
  • cly116
  • cly116
  • 2015-08-09 18:16
  • 1319

javaProject和webProject----转载自http://sarin.iteye.com/blog/574626(sarin)

想必大家在使用MyEclipse时对这两个概念不去深究。只知道是Java EE类的基本都是Web项目,而Java应用程序就是Java项目。而且很多人都愿意使用MyEclipse作为开发工具,且不说大家...

for_each的用法,转载自蕭鴻森的blog

Abstract 之前在(原創) 如何使用for_each() algorithm? (C/C++) (STL) 曾經討論過for_each(),不過當時功力尚淺,只談到了皮毛而已,這次看了effe...

SVN使用(转载自CSDN Kevin's BLOG)

svn的具体使用

转载自:http://blog.csdn.net/lmj623565791/article/details/24015867

1、请解释下在单线程模型中Message,Handler,Message Queue,Looper之间的关系。 拿主线程来说,主线程启动时会调用Looper.prepare()方法,会初始化一个...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)