美文网首页OpenGL ES
第七章 图元和光栅化

第七章 图元和光栅化

作者: 大旺旺的弟弟小旺旺 | 来源:发表于2021-06-26 08:49 被阅读0次

    顶点着色器之后是图元装配,在装配阶段完成裁剪、透视和视口变换,最后执行光栅化。

    图元

    他是一种几何对象,可以通过glDrawArrays和glDrawElements来绘制,图元有顶点位置和其他一些其它的信息来描述。opengles支持的图元:

    • 三角形
    • 线

    三角形

    三角形是绘制的最常用的方法,三角形支持的有三角形,三角带,扇形。

    • TRIANGLES绘制一系列独立的三角形。画出了由顶点(V0,V1,V2)和(V3,V4,V5)给出的两个三角形。总共绘制了n/3个三角形,其中n是在glDrawArrays或glDrawElements中指定为计数的索引数。
    • TRIANGLE _ STRIP绘制一系列相连的三角形。三个三角形由(V0,V1,V2),(V2,V1,V3)(注意顺序)和(V2,V3,V4)给出。总共绘制了(n–2)个三角形,其中n是在glDrawArrays或glDrawElements中指定为计数的索引数。
    • TRIANGLE _ FAN也画一系列相连的三角形。画出的三角形是(V0,V1,V2),(V0,V2,V3)和(V0,V3,V4)。总共绘制了(n–2)个三角形,其中n是在glDrawArrays或glDrawElements中指定为计数的索引数。

    总结 :
    总结一下就是,opengl使用顶点来进行绘制,点决定了绘制的位置信息,在这里支持了点 、直线、三角形。

    • 三角形:可以绘制单个三角形,绘制相连的三角形,绘制一系列。

    线

    OpenGL ES支持的线图元有GL_LINES、GL_LINE_STRIP、GL_LINE_LOOP。

    • GL_LINES绘制一系列不相连的线段。由(V0,V1),(V2,V3)和(V4,V5)给出了三条单独的线。总共绘制了n/2个线段,其中n是在glDrawArrays或glDrawElements中指定为计数的索引数。

    • GL_LINE_STRIP绘制一系列相连的线段。在图7-2所示的例子中,三条线段由(V0,V1),(V1,V2)和(V2,V3)给出。总共绘制了(n–1)条线段,其中n是在glDrawArrays或glDrawElements中指定为计数的索引数。

    • GL_LINE_LOOP的工作方式与GL_LINE_STRIP相似。绘制的线段是(V0,V1),(V1,V2),(V2,V3),(V3,V4)和(V4,V0)。总共绘制了n条线段,其中n是在glDrawArrays或glDrawElements中指定为计数的索引数。

    线的宽度可以使用glLineWidth API调用来指定。
    glLineWidth指定的宽度将被限制在OpenGL ES 2.0实现支持的线宽范围内。可以使用以下命令查询支持的线宽范围。不要求支持宽度大于1的线条。

    GLfloat   lineWidthRange[2];
    glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, lineWidthRange);
    

    总结:
    线的绘制包括了一条直线,绘制相连的直线,绘制一个闭合的,绘制的可以设置它的宽度,但是宽度必须在该规定范围之内的。

    点精灵

    点精灵使用的图元是GL_POINTS,为每个顶点进行绘制,点精灵将每个点创建为一个点而不是一个四边形,它是一个屏幕对其的四边形,指定位置半径,位置是指它在的中心位置,半径描述点精灵的四个坐标。

    • gl_pointSize:内置变量,输出点的半径
      默认情况下,OpenGL ES 2.0将窗口原点(0,0)描述为(左,下)区域。但是,对于点精灵,点坐标原点是(左侧,顶部)。

    • gl_pointCoord一个内置变量,渲染一个点精灵的时候,在片段中可用,他是一个0,1范围的大小。

    uniform sampler2D s_texSprite;
    void
    main(void)
    {
       gl_FragColor = texture2D(s_texSprite, gl_PointCoord);
    }
    

    绘制图元

    绘制图元:glDrawArrays和glDrawElements。

    glDrawArrays:

    • 参数一:指定模式
    • 参数二:数据的那个位置开始
    • 参数三:一共几个点。

    案例:

    #define VERTEX_POS_INDX 0
    #define NUM_FACES       6
    GLfloat vertices[] = { … };  // (x, y, z) per vertex
    glEnableVertexAttribArray(VERTEX_POS_INDX);
    glVertexAttribPointer(VERTEX_POS_INDX, 3, GL_FLOAT, GL_FALSE, 
                          0, vertices);
    for (i=0; i<NUM_FACES; i++)
    {
       glDrawArrays(GL_TRIANGLE_FAN, first, 4);
       first += 4;
    }
    or
    glDrawArrays(GL_TRIANGLES, 0, 36);
    

    一般使用第二个就可以了,比较方便。告诉GPU,读取那些点的数据。

    为了用Gldraw Arrales绘制这个立方体,我们将为立方体的每个面调用Gldraw Arrales。共享的顶点将需要复制,这意味着我们现在需要分配24个(如果我们将每个面绘制为GL 三角形扇形)或36个顶点(如果我们使用GL _三角形),而不是8个顶点。这不是一个非常有效的方法。

    总结:
    绘制的时候一个面需要6个点,一共是6个面,就需要36个点,一个点是xyz,也就是108个点,就可以使用索引来优化,它指示的是每个点读取那个几个数据,指定的是索引。

    这是使用glDrawElements绘制同一个立方体的方式。

    #define VERTEX_POS_INDX 0
    GLfloat vertices[] = { … };// (x, y, z) per vertex
    GLubyte indices[36] = { 0, 1, 2, 0, 2, 3, 
                            0, 3, 4, 0, 4, 5, 
                            0, 5, 6, 0, 6, 1, 
                            7, 6, 1, 7, 1, 2,
                            7, 4, 5, 7, 5, 6,
                            7, 2, 3, 7, 3, 4 };
    glEnableVertexAttribArray(VERTEX_POS_INDX);
    glVertexAttribPointer(VERTEX_POS_INDX, 3, GL_FLOAT, GL_FALSE, 
                          0, vertices);
    glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(GLubyte),
                   GL_UNSIGNED_BYTE, indices);
    

    即使我们在用glDrawElements画三角形,用glDrawArrays画一个三角扇,glDrawElements在一个GPU上运行速度会比glDrawArrays快很多;例如,当顶点被重用时,使用glDrawElements时,顶点属性数据的大小会更小。这也降低了内存占用和内存带宽要求。

    原始装配

    顶点着色器执行通过glDrawArrays或glDrawElements提供的顶点。由顶点着色器变换的每个顶点都包括描述顶点(x,y,z,w)值的顶点位置。图元类型和顶点索引决定了将要渲染的单个图元。对于每个单独的图元(三角形、直线和点)及其对应的顶点,下来会执行裁剪、透视分割,视口变换

    坐标系

    顶点通过顶点着色器和图元装配阶段时的坐标系。顶点输入到物体或局部坐标空间中的OpenGL ES。这是一个对象最有可能被建模和存储的坐标空间。执行顶点着色器后,顶点位置被视为在剪辑坐标空间中。顶点位置从局部坐标系(即,对象坐标)到剪辑坐标的转换是通过加载适当的矩阵来完成的,该矩阵以顶点着色器中定义的适当的统一方式执行该转换。第8章描述了如何将顶点位置从对象转换到剪辑坐标,以及如何在顶点着色器中加载适当的矩阵来执行这种转换。

    裁剪

    顶点着色器执行后的顶点位置在剪辑坐标空间中。剪辑坐标是由(xc,yc,zc,wc)给出的齐次坐标。在剪辑空间中定义的顶点坐标(xc,yc,zc,wc)会根据查看体积(也称为剪辑体积)进行剪辑。
    裁剪体由六个裁剪平面定义,分别称为近裁剪平面、远裁剪平面、左裁剪平面、右裁剪平面、顶裁剪平面和底裁剪平面。在片段坐标中,片段体积表示为:

    -wc <= xc <= wc
    -wc <= yc <= wc
    -wc <= zc <= wc
    

    前面的六个检查有助于确定图元需要修剪的平面列表。
    裁剪阶段会将每个图元裁剪到裁剪体积中。我们通过一个图元来暗示使用GL _ TRIANGLES绘制的一系列独立三角形中的每个三角形,或者三角形条或扇形的三角形,或者使用GL_LINES绘制的一系列独立线条中的一条线,或者线条条或线条循环中的一条线,或者点精灵列表中的特定点。
    对于每个图元类型,执行以下操作:

    • 裁剪三角形-如果三角形完全在查看体积内,则不执行裁剪。如果三角形完全在观看体积之外,则三角形被丢弃。如果三角形部分位于观察体积内,则根据适当的平面裁剪三角形。裁剪操作将生成被裁剪到平面上的新顶点,这些顶点被排列成三角形扇形。
    • 裁剪线-如果线完全在查看体积内,则不执行裁剪。如果该行完全在观看体积之外,则该行被丢弃。如果线部分位于观察体积内,则线被修剪,并生成适当的新顶点
    • 剪辑点精灵-如果点位置位于近或远剪辑平面之外,或者表示点精灵的四边形位于剪辑体积之外,剪辑阶段将丢弃点精灵。否则,它将保持不变,当点精灵从剪辑卷内部移动到外部时,它将被剪切,反之亦然。
    • 在图元相对于六个裁剪平面被裁剪之后,顶点坐标经历透视分割以成为归一化的设备坐标。归一化设备坐标在-1.0到+1.0的范围内。
      裁剪之后变为归一化的坐标
      注意:在硬件中执行裁剪操作(尤其是线和三角形)可能相当昂贵。观察体积有六个裁剪平面,图元必须靠着这些平面裁剪。部分位于近平面和远平面之外的图元会经历剪裁操作。但是,部分位于x和y平面之外的图元不一定需要修剪。通过渲染到比用glViewport指定的视口尺寸更大的视口中,在x和y平面中的裁剪变成了剪切操作。剪枝是由GPU非常高效地实现的。这个较大的视口区域称为防护带区域。虽然OpenGL ES不允许应用程序指定保护带区域,但大多数(如果不是所有的话)OpenGL ES实现都实现了保护带。

    透视

    透视分割将由剪辑坐标(xc,yc,zc,wc)给出的点投影到屏幕或视口上。这个投影是通过用wc分割(xc,yc,zc)坐标来实现的。(xc/wc)、(yc/wc),(zc/wc)我们得到归一化的器件坐标(xd,yd,zd)。这些被称为标准化设备坐标,因为它们将在[–1.0…1.0]范围内。这些标准化的(xd,yd)坐标将根据视口的尺寸转换成实际的屏幕(或窗口)坐标。使用glDepthRange指定的近深度值和远深度值,将归一化(zd)坐标转换为屏幕z值。这些转换在视口转换阶段执行

    视口变换

    可以使用Viewport 来进行。从标准化设备坐标(xd,yd,zd)到窗口坐标(xw,yw,zw)的转换由以下转换给出:

    • 在变换ox = (x + w)/2和oy = (y + h)/2中,n和f代表所需的深度范围。

    深度范围值n和f可以使用下面的应用编程接口调用来设置,glDepthRange和glViewport指定的值用于将顶点位置从归一化设备坐标转换为窗口(屏幕)坐标。初始(或默认)视口状态设置为w =宽度,h = OpenGL ES要在其中进行渲染的应用程序创建的窗口的高度。该窗口eglCreateWindowSurface中指定的EGLNativeWindowType win参数给出。

    光栅化

    就是将需要绘制点变为一个二维数组的形式,并且这里也会计算差值。
    在顶点已经被变换并且图元已经被裁剪之后,光栅化流水线获取单个图元,例如三角形、线段或点子画面,并且为该图元生成适当的片段。每个片段由它在屏幕空间中的整数位置(x,y)来标识。片段表示屏幕空间中由(x,y)给定的像素位置以及将由片段着色器处理以产生片段颜色的附加片段数据。

    剔除

    在三角形被栅格化之前,我们需要确定它们是面向前(即面向观察者)还是面向后(即背离观察者)。剔除操作会丢弃背离查看者的三角形。为了确定三角形是正面还是背面,我们首先需要知道三角形的方向。、
    三角形的方向指定路径的缠绕顺序,该路径从第一个顶点开始,经过第二个和第三个顶点,并在第一个顶点结束。图7-10描述了顺时针和逆时针缠绕顺序的两个三角形例子。
    剔除也可以开启和禁用。

    相关文章

      网友评论

        本文标题:第七章 图元和光栅化

        本文链接:https://www.haomeiwen.com/subject/cwiayltx.html