OpenGL入门 - 着色器和图形管线(Shaders and the Graphics Pipeline)
1. Ordered vs Indexed: Vertex Data
1.1 定义
之前我们使用的一直是ordered的方式,即提前定义好每个vertex,然后告知GPU渲染的顺序,但是这些vertex中有一些是重复的,当图形复杂的时候这就变得很繁琐,于是我们引入index的方法。
在index方法中,只需要需要两个部分:vertex和index信息,分别记录vertex信息和渲染的顺序index,代码如上图。
1.2 传输至GPU
我们同样需要将index数据输出至GPU中,这里做法和vertexBuffer很类似,也是分三步:
glGenBuffer(); // 生成
glBindBuffer(); // 绑定
glBufferData(); // 传输数据
1.3 绘制
在绘制的过程中也有所差异:
在Orderd方法中,我们在绘制的时候先绑定好vertexBuffer,随后通过glDrawArray来进行绘制。
然而index方法中,我们还需要绑定elementBuffer,随后使用glDrawElemnts方法来进行绘制。
2. Storing Vertex Info: Round 2
作者希望在后续能为每个vertex储存颜色信息,如下图:
这就需要为vertex结构体进行调整,加入Color变量
并在定义的时候为Color变量赋值。
通过前几天的学习,我们了解到vertex渲染到屏幕需要经过vertex shader和fragment shader,所以verte的结构变化后,其中的Color参数也要在shader中进行传递,也需要进行相应修改:
在vertex shader的GLSL中,加入了两个部分:
- 新增输入变量:a_Color,用来接受Color的输入
- 新增输出变量:frag_Color,用来输出Color
在fragment shader中,新增了输入变量frag_Color,用于接受vertex shader输出的Color信息
3. The Graphic PipeLine
接下来将介绍OpenGL ES中的图形管线,即从顶点信息至渲染的全流程
3.1 Vertex Buffer Object
Vertex Buffer Object的作用就是将CPU中的vertex和index数据传输至GPU,相信代码大家也非常熟悉了,就是熟悉的三步骤——生成、绑定和传输。
3.2 Vertex Shader
在这一步骤中,vertex Shader将会按其的GLSL的逻辑来进行,主要功能还是输出vertex的位置信息以及传递相关参数
输入:
attribute 顶点属性(每一次都不一样)
uniform 统一变量(不可变)
sampler 纹理采样器
输出:
varying 可变输出(会自动进行插值)
gl_Position 内建变量,即当前顶点对应的位置,一般是变换后的值
gl_PointSize ?
3.3 Primitive Assembly
Primitive Assembly就是利用vertex shader输出的顶点组合成一个图元的过程,这个过程输出了一个有序的简单图元(点、线或者三角形,通常是三角形)的序列。
3.4 Rasterization
rasterization(光栅化)是一个将几何图元转化为而为fragment的过程,
其决定窗口坐标中的哪些整型栅格区域被图元占用。如图,整个三角形被转化为一个个矩形构成的区域,实质上是由rasterization决定哪些栅格区域被三角形所“选中”
注意,在这一步获取到的屏幕的点是没有颜色的,必须通过下一步去 ”着色“。
3.5 Fragment Shdaer
fragmentShader根据GLSL来进行其中的步骤,输出像素最终的颜色信息。
输入:
varying 从 Vertex Shader 中经过光栅化插值之后得到的变量
uniform 统一变量
Samplers 采样器,通常是 2D 纹理
输出:
gl_FragColor 该片段对应的颜色
3.6 Testing and Blending
原本我们已经在Color Buffer上渲染了背景色,Blending阶段的任务就是将我们上述流程绘制出的内容混合在已经存在的内容之上,GLView就是从color buffer中提取内容,并渲染在屏幕上。有时fragment shader产生了超出边界之外的数据,testing阶段便能够将其清除。
视频链接:https://www.youtube.com/watch?v=f2hbOfT12jU&list=PL23Revp-82LL_XoQEiTT6zsgHHrpjr1D9&index=4