我的OpenGL学习进阶之旅介绍一下OpenGL ES的 光栅化 : 剔除多边形偏移

Posted 字节卷动

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我的OpenGL学习进阶之旅介绍一下OpenGL ES的 光栅化 : 剔除多边形偏移相关的知识,希望对你有一定的参考价值。

在上一篇文章【我的OpenGL学习进阶之旅】介绍一下 绘制图元中,我们介绍了如何绘制图元。

在上一篇文章【我的OpenGL学习进阶之旅】介绍一下OpenGL ES的图元装配:坐标系统、透视分割、视口变化中,我们介绍了 图元装配。

这篇我们来介绍一下 光栅化。

一、光栅化

下图展示了光栅化管线。在顶点变化和图元裁剪之后,光栅化管线取得单独图元(如三角形、线段或者点精灵),并为该图元生成对于的片段。每个片段由屏幕空间中的整数位置(x,y)标识。

片段代表了屏幕空间中(x,y)指定的像素位置和由片段着色器处理而生成片段颜色的附加片段数据。这些操作将在后续的博客在详细说明。


在本节中,我们讨论用于程序可以用于控制三角形、条带和扇形光栅化的各种选项。

1.1 剔除

在三角形被光栅化之前,我们需要确定它们是正面(也就是面向观看者)或者背面(也就是背向光看者)。

剔除(Culling)操作抛弃背向光看者的三角形。

要确定三角形是正面还是背面,首先需要知道它的方向。

三角形的方向指定从第一个顶点开始,经过第二个和第三个顶点,最后回到第一个顶点的弯曲方向或者路径顺序。下图展示了弯曲顺序为顺时针和逆时针的两个三角形示例。


三角形的方向通过以窗口坐标表示的有符号三角形的面积来计算。

我们现在需要将计算出来的三角形面积符号翻译为顺时针(CW) 或者 逆时针(CCW)方向。

1.1.1 指定三角形方向的方法

这种从三角形面积的符号到顺时针(CW) 或者 逆时针(CCW)方向的映射由应用程序如下API调用指定:

void glFrontFace(GLenum dir)

参数说明:

  • dir
    指定正面三角形的方向。有效值为GL_CW或者GL_CCW,默认值为GL_CCW

1.1.2 指定三角形要被剔除的面的方法

我们已经讨论了计算三角形方向的方法。要确定需要剔除的三角形,需要知道三角形将要被剔除的面。这通过应用程序使用如下API调用指定:

void glCullFace(GLenum mode)

参数说明:

  • mode
    指定要被剔除的三角形的面。有效值为:GL_FRONT、GL_BACK、GL_FRONT_AND_BACK。默认值为GL_BACK

1.1.3 启用或者禁用 GL_CULL_FACE状态

最后一个要点是,需要知道剔除操作是否应该执行。

如果GL_CULL_FACE状态启用,剔除操作将被执行。GL_CULL_FACE状态可以由应用程序用如下API调用启用或者禁用。

void glEnable (GLenum cap);
void glDisable (GLenum cap);

参数说明:

  • cap
    cap被设置为GL_CULL_FACE,默认情况下剔除被禁用

1.1.4 剔除总结

概括取来,要剔除合适的三角形,OpenGL ES应用程序首先必须用glEnable(GL_CULL_FACE)启用剔除,用glCullFace设置相应的剔除面,并用glFrontFace设置正面三角形的方向

1.2 多边形偏移

考虑绘制两个相互重叠的多边形情况。你很有可能注意到伪像,如下图所示。

这些伪像被称为深度冲突伪像,是因为三角形光栅化的精度有限而发生的,这种精度限制可能影响逐片段生成的深度值的精度,造成伪像。

三角形光栅化使用的参数和生成逐片段深度值的有限精度将越来越好,但这个问题永远无法完全解决。

上图展示了两个共面多边形。 不使用多边形偏移绘制这两个共面多边形的diam如下:

    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    // load vertex shader
    
    // set the appropriate transformation matrices
    
    // set the vertex attribute state
    
    // draw the SMALLER quad
    glDrawArrays(GL_TRIANGLE_FAN , 0 , 4);
    
    // set the depth func to <= as polygons are coplanar
    glDepthFunc( GL_LEQUAL );
    
    // set the vertex attribute state
    
    // draw the LARGER quad
    glDrawArrays(GL_TRIANGLE_FAN , 0 , 4);

为了避免上图看到的伪像,我们需要在执行深度测试和深度值写入深度缓冲区之前,在计算出来的深度值上添加一个偏移量。

如果深度测试通过,原始的深度值-------而不是原始深度值+偏移-------- 将被保存到深度缓冲区中。

多边形偏移用如下API调用设置:

void glPolygonOffset (GLfloat factor, GLfloat units);

偏移深度的计算如下:

深度偏移 = m * 因数 + r * 单位数

在上述公式中,m是三角形的最大深度斜率,计算方法如下:


m也可以这样计算:

斜率项 ∂z/∂x 和 ∂z/∂y在三角形光栅化阶段期间由OpenGL ES 实现计算。

r是一个OpenGL ES 实现定义的常量,代表深度值中可以保证产生差异的最小值。

多边形偏移可以用如下代码启用

 glEnable(GL_POLYGON_OFFSET_FILL)

多边形偏移可以用如下代码禁用

 glDisable(GL_POLYGON_OFFSET_FILL)

启用多边形偏移是,渲染上图中国三角形的代码如下:


    const float polygonOffsetFactor = -1.0f;
    const float polygonOffsetUnits = -2.0f;


    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // load vertex shader
    
    // set the appropriate transformation matrices

    // set the vertex attribute state

    // draw the SMALLER quad
    glDrawArrays(GL_TRIANGLE_FAN , 0 , 4);

    // set the depth func to <= as polygons are coplanar
    glDepthFunc( GL_LEQUAL );
    
    
    glEnable( GL_POLYGON_OFFSET_FILL );
    
    glPolygonOffset( polygonOffsetFactor, polygonOffsetUnits );

    // set the vertex attribute state

    // draw the LARGER quad
    glDrawArrays(GL_TRIANGLE_FAN , 0 , 4);

以上是关于我的OpenGL学习进阶之旅介绍一下OpenGL ES的 光栅化 : 剔除多边形偏移的主要内容,如果未能解决你的问题,请参考以下文章

我的OpenGL学习进阶之旅介绍 顶点数组对象VAO并实战一下

我的OpenGL学习进阶之旅介绍一下OpenGL ES的图元装配:坐标系统透视分割视口变化

我的OpenGL学习进阶之旅介绍一下OpenGL ES的图元装配:坐标系统透视分割视口变化

我的OpenGL学习进阶之旅介绍一下 映射缓冲区对象和复制缓冲区对象

我的OpenGL学习进阶之旅介绍一下 绘制图元

我的OpenGL学习进阶之旅介绍一下 绘制图元