# 01.顶点着色器与片元着色器

> 管道渲染流程 ![渲染流程](https://4193904735-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MI8JgbGh3U6X_oedqkm%2Fsync%2Fff499edf01b00761d25747a5ebf853d1aa4762b2.png?generation=1615822854268731\&alt=media)

## 一：顶点着色器

### 1.1 输入

* 着色器程序
  * 描述顶点上执行操作的顶点着色器程序源代码/可执行文件
* 顶点着⾊器输入(属性)
  * 用顶点数组提供每个顶点的数据
* 统一变量(uniform)
  * 顶点/片元着⾊器使用的不变数据
* 采样器
  * 代表顶点着色器使用纹理的特殊统一变量类型，一般是ID类型，GLSL会根据ID标签查找到纹理

### 1.2 输出

#### 1.2.1 图元装配

* 图元(Primitive)：
  * 点、线、三角形等
* 图元装配
  * 将顶点数据计算成一个个图元，在这个阶段会执行裁剪、透视分割和Viewport变换操作。即确定顶点形成的图形，点或线或三角形等。
  * 对于每个图元，必须确定图元是否位于视锥体(屏幕上可见的3D空间区域)内：
    * 图元没有完全在视锥体内，可能需要进行裁剪。
    * 图元完全处于该区域之外，它就会被抛弃

#### 1.2.2 光栅化

绘制对应的图片(点、线、三角形)，将图元转化成一组二维片段的过程，就是将顶点数据计算成的图片转化成片元，然后这些片元由片元着色器处理。

![顶点](https://4193904735-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MI8JgbGh3U6X_oedqkm%2Fsync%2F87ce063a747581bdea55bd2c7db39d23fc08dc3c.png?generation=1615822854052813\&alt=media)

### 1.3 顶点着色器业务

* 矩阵变换位置
* 计算光照公式生成出顶点颜色
* 生成/变换纹理坐标

## 二：片元着色器

### 2.1 输入

* 着色器程序
  * 描述片段上执行操作的片元着色器程序源代码/可执行文件。
* 输入变量
  * 光栅化单元用插值为每个片段生成的顶点着色器输出
* 统一变量(uniform)
  * 顶点或片元着色器使用的不变数据
* 采样器
  * 代表片元着色器使用纹理的特殊统一变量

### 2.2 插值(Interpolation)：

`光栅器`在三角形的三个顶点之间进行`插值`（或者通过另外一种技术一行一行的插值）并执行片元着色器遍历三角形的每一个像素。 片元着色器会返回光栅器存在`颜色缓存`中用于显示的`像素颜色值`（在其他一些额外的检测之后，比如：`深度测试depth test`等）

### 2.3 片元着色器业务

* 计算颜色
* 获取纹理值
* 往像素点中填充颜色值、纹理值
* 它可以⽤于`图⽚`/`视频`/`图形`中每个像素的颜色填充(比如给视频添加滤镜,实际上就是将视频中每个图片的像素点颜色填充进行修改.)

### 2.4 逐片段操作

* 像素归属测试:&#x20;
  * 确定帧缓存区中位置(Xw,Yw)的像素目前是不是归属于OpenGL ES所有. 例如，如果⼀个显示OpenGL ES帧缓存区View被另外⼀个View所遮蔽.则窗口系统可以确定被遮蔽的像素不属于OpenGL ES上下⽂。从而不全显示这些像素。而像素归属测试是OpenGL ES的一部分，它不由开发者开人为控制，而是由OpenGL ES内部进行.
* 裁剪测试:&#x20;
  * 裁剪测试确定(Xw,Yw)是否位于作为OpenGL ES状态的一部分裁剪矩形范围 内。如果该⽚段位于裁剪区域之外，则被抛弃。
* 深度测试:&#x20;
  * 输⼊片段的深度值进步比较，确定片段是否拒绝测试
* 混合:&#x20;
  * 混合将新生成的⽚段颜色与保存在帧缓存的位置的颜色值组合起来
* 抖动:&#x20;
  * 抖动可用于最小化因为使用有限精度在帧缓存区中保存颜色值⽽产生的伪像.

    ![](https://4193904735-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MI8JgbGh3U6X_oedqkm%2Fsync%2Fd19d96a011fb3fd7b13a2820b353981b98130a30.png?generation=1615822854067841\&alt=media)

## 三：EGL (Embedded Graphics Library )

* `OpenGL ES`命令需要渲染上下文和绘制表面才能完成图形图像的绘制.
  * 渲染上下文:&#x20;
    * 存储相关OpenGL ES状态.
  * 绘制表面:&#x20;
    * 是用于绘制图元的表面，它指定渲染所需要的缓存区类型，例如颜色缓冲区，深度缓冲区和模板缓冲区.
* `OpenGL ES API`并没有提供如何创建渲染上下⽂或者上下⽂如何连接到原生窗口系统。 `EGL`是`Khronos`渲染`API`(如`OpenGL ES`)和原⽣窗口系统之间的接口。唯一⽀持`OpenGL ES`却不⽀持`EGL`的平台是`iOS`。`Apple`提供⾃己的`EGL API`的`iOS`实现,称为`EAGL`。
* 因为每个窗口系统都有不同的定义，所以`EGL`提供基本的不透明类型`EGLDisplay`，这个类型封装了所有系统相关性，用于和原生窗口系统接口.

由于`OpenGL ES`是基于`C`的`API`，因此它⾮常便携且受到广泛支持。作为`C`的`API`，它与`Objective-C` `Cocoa Touch`应⽤程序⽆缝集成。`OpenGL ES`规范没有定义窗口层; 相 反，托管操作系统必须提供函数来创建一个接受命令的`OpenGL ES``渲染上下文`和一个`帧缓冲区`，其中写入任何绘图命令的结果。在`iOS`上使用`OpenGL ES`需要使⽤`iOS类`来设置和呈现绘图表面，并使用`平台中立的API`来呈现其内容。
