OpenGL ES 图形管线

36 阅读5分钟

1. pipeline

Pasted image 20251103204313.png

1.1 顶点着色器

顶点着色器实现了顶点操作的通用可编程方法。顶点着色器可以实现基于顶点的传统操作,如通过矩阵来变换顶点位置、计算照明公式生成逐顶点颜色、生成或者变换纹理坐标等。

Pasted image 20251103204507.png

1.1.1 输入

顶点着色器的输入包括:

  1. 着色器程序(shader program):描述顶点上执行操作的顶点着色器程序源代码或可执行文件。
  2. 顶点属性(vertex atrribute):使用顶点数组提供的每个顶点的属性。
  3. 统一变量(uniform):顶点着色器中使用的不变的数据。
  4. 采样器(sampler):使用纹理时的特殊的unform变量,可用于纹理采样。

1.1.2 输出

顶点着色器的输出:又称为varying变量,在图元光栅化阶段,会为每个片段计算顶点着色器的输出,并将其作为输入传递给片段着色器。 顶点着色器的顶点输出,实际上是在裁剪坐标系内

1.1.3 MVP矩阵

Model Matrix 模型矩阵:用于变换物体对象,将物体坐标从模型空间(相对于物体原点)转换到世界空(相对于世界原点,全局唯一)中。

View Matrix 视图矩阵/观察矩阵:它定义了相机在世界坐标系中的位置和观察方向,将物体顶点从世界空间转换至观察空间(相对于相机)。

ModelView矩阵都是线性变换(包括齐次坐标的平移操作),一般几何属性,如法线,光照等的计算,都在经过此变换后的观察空间中进行。

Projection Matrix 投影矩阵:投影矩阵是为了模拟人眼看待世界的“近大远小”透视效果,或正交投影效果。它将顶点从观察空间,转换至裁剪空间。
裁剪空间的坐标是(xc,yc,zc,wc)(x_c, y_c, z_c, w_c)所指定的齐次坐标,裁剪空间中的坐标范围是wcxcwc-w_c \leq x_c \leq w_cwcycwc-w_c \leq y_c \leq w_cwczcwc-w_c \leq z_c \leq w_c,其归一化后的坐标会限制在一个视景体内。

Pasted image 20251103212825.png

1.2 图元装配

1.2.1 图元组装

根据用户的opengl绘制调用命令(如 glDrawArrays或 glDrawElements)和指定的图元类型(如 三角形GL_TRIANGLES、连续线段GL_LINE_STRIP等),管线将连续的顶点数据“连接”成具体的形状。组装好的图元仍然位于裁剪空间

1.2.2 裁剪

裁剪发生在裁剪空间,目的是丢弃那些完全不在视锥体内的图元,以及对部分位于视锥体内的图元进行裁剪,只保留可见部分(可能会生成多的点)。 裁剪必须在裁剪空间中进行,因为如果到NDC中的映射是非线性的,如要新加点和属性,则会不对。(非线性,如裁剪空间平行线映射后在NDC中会相交,「铁轨」)

1.2.3 透视除法

裁剪完后,会进行透视除法,对于裁剪坐标中的每个分量,都除以ww分量。则有 (x,y,z,w)>(x/w,y/w,z/w)(x, y, z, w)->(x/w, y/w, z/w),顶点坐标经过透视除法,从裁剪空间转换至归一化的设备坐标NDC空间,其表示范围在一个标准的立方体内:[1,1]3{[-1, 1]^3}。顶点的1/w1/w分量被保留,需要用于透视矫正插值。

1.2.4 视口变化

NDC 坐标被变换到窗口坐标(也称为屏幕坐标)。这个变换可以通过 glViewport和 glDepthRange函数定义的参数控制。此时z坐标也会变换到视锥体的far和near两个平面范围间,记录到zbuffer里面。

1.2.5 背面剔除

剔除背向摄像机的三角形。

1.3 光栅化

光栅化是将图元转换为一组二维片元的过程。(片元区别于像素,可能会被后面的测试丢弃或修改)。光栅化发生在视口变换后,此时有片元顶点的窗口坐标,z坐标。

1.3.1 确定片元

确定哪些片元被图元覆盖,如通过重心坐标系来来判断像素中心点是否在三角形内。

1.3.2 片元属性插值

利用重心坐标来平滑地计算三角形内部任意一点的属性值。它会根据三个顶点的属性值,按比例进行混合。(重心坐标是,基于窗口坐标系下的像素位置计算得到) Pasted image 20251103220710.png

1.4 片段着色器

片段着色器为片元操作实现了通用的可编程方法。光栅化阶段中生成的每一个片元,都会执行该着色器程序。 Pasted image 20251103221216.png

1.4.1 输入

片段着色器的输入:

  1. 着色器程序(shader program):描述片段上所执行的片段着色器程序的源代码或可执行文件。
  2. 输入可变变量(varying):光栅化阶段为每个片段插值生成的顶点着色器的输出。
  3. 统一变量(uniform):片段着色器中使用的不变的数据。
  4. 采样器(sampler):使用纹理时的特殊的unform变量,可用于纹理采样。

1.4.2 输出

片段着色器可以抛弃片元(discard关键字),或者生成一个或多个颜色值作为输出(framebuffer + 多个attachments + drawbuffers)

1.5 逐片段操作

Pasted image 20251103223011.png

  1. 像素归属测试:确定帧缓存中像素目前是否归当前OpenGL ES上下文所有,确认是否可以不显示这些像素,如OpenGL ES窗口被另外一个窗口所覆盖,则可以完全不显示这些像素。这些实在OpenGL 内部控制,不由开发人员管理。
  2. 裁剪测试scissor test,允许定义一个屏幕空间的二维矩形区域,只有该范围内的可以写入帧缓存,之外的会被丢弃。
  3. 模版测试stencil test,允许定义一个特定的模版mask,来检测片元是否写入还是丢弃。相比裁剪测试,可以定义更高级的图案类型。
  4. 深度测试depth test,解决3D场景中物体的可见性(遮挡关系),根据深度值对片元颜色进行覆盖。
  5. 混合Blend :将源片元的颜色与帧缓冲区中目标像素的颜色进行组合,常用于绘制透明物体。