咱们之前说了一下 GLSL 的基础知识,详情可参见 Android OpenGL ES – GLSL 根底篇
上一张呢咱们也理解了一下纹理,实现了咱们的 OpenGL 的第一张图片,不过可能咱们对 gl_Position
,gl_Fragcolor
,texture2D (uTexture, vCoordinate)
等一些 GLSL 语法不是特地相熟,本篇博客呢,是对 GLSL 的一些补充,也是为前面的博客打下基础。
PS:
无非凡阐明,文中的 GLSL 均指 OpenGL ES 2.0 的着色语言。
GLSL 高级篇
invariant 限定符
invariant 能够作用于顶点着色器输入的任何一个 varying 变量。
当着色器被编译时,编译器会对其进行优化,这种优化操作可能引起指令重排序(instruction reordering),指令重排序可能引起的后果是当两个着色器进行雷同的计算时无奈保障失去雷同的后果。
例如,在两个顶点着色器中,变量 gl_Position
应用雷同的表达式赋值,并且当着色程序运行时,在表达式中传入相等的变量值,则两个着色器中 gl_Position
的值无奈保障相等,这是因为两个着色器是别离独自编译的。这将会引起 multi-pass 算法的几何不统一问题。
通常状况下,不同着色器之间的这种值的差别是容许存在的。如果要防止这种差别,则能够将变量申明为 invariant,能够独自指定某个变量或进行全局设置。
应用 invariant 限定符能够使输入的变量放弃不变。invariant 限定符能够作用于之前已申明的变量使其具备不变性,也能够在申明变量时间接作为申明的一部分,可参考以下两段示例代码:
varying mediump vec3 Color;
// 使已存在的 color 变量不可变
invariant Color;
或
invariant varying mediump vec3 Color;
以上是仅有的应用 invariant 限定符情境。如果在申明时应用 invariant 限定符,则必须保障其放在存储限定符(varying)之前。
只有以下变量能够申明为 invariant:
- 由顶点着色器输入的内置的非凡变量
- 由顶点着色器输入的 varying 变量
- 向片段着色器输出的内置的非凡变量
- 向片段着色器输出的 varying 变量
- 由片段着色器输入的内置的非凡变量
为保障由两个着色器输入的特定变量的不变性,必须遵循以下几点:
- 该输入变量在两个着色器中都被申明为 invariant
- 影响输入变量的所有表达式、流程管制语句的输出值必须雷同
- 对于影响输入值的所有纹理函数,纹理格局、纹理元素值和纹理过滤必须统一
- 对输出值的所有操作都必须统一。表达式及插值计算的所有操作必须统一,雷同的运算数程序,雷同的联合性,并且按雷同程序计算。插值变量和插值函数的申明,必须有雷同类型,雷同的显式或隐式的精度 precision 限定符。影响输入值的所有管制流程必须雷同,影响决定管制流程的表达式也必须遵循不变性的规定。
最根本的一点是:所有的 invariant 输出量的上游数据流或控制流必须统一。
此限定符情境比拟少,这里就一笔带过了
内置变量
顶点着色器 (Vertex Shader) 内置变量
内置变量(输入) | 形容 | 单位或坐标系 |
---|---|---|
highp vec4 gl_Position; | 变换后的顶点地位 | 裁剪坐标系 Vclip |
mediump float gl_PointSize; | 变换后的点大小(仅仅表白光栅化后点的大小) | 像素 |
gl_Position
,此变量用于写入齐次顶点地位坐标。一个残缺的顶点着色器的所有执行命令都应该向此变量写入值。该值的输出同时也是图元拆卸、剪切(clipping)、剔除(culling)等对于图元的固定性能操作中的输出值。其决定了一个几何图形的地位与形态。
片段着色器 (Fragment Shader) 内置变量
内置变量(输出) | 形容 | 单位或坐标系 |
---|---|---|
mediump vec4 gl_FragCoord; | 片段在帧缓冲区窗口坐标内的地位 | 窗口坐标系 |
bool gl_FrontFacing; | 片段是否属于正面图元 | Bool |
mediump int gl_PointCoord | 片段所在点图元的二维坐标 | 范畴是 0.0 到 1.0 |
片段着色器能够写入 gl_FragColor 或 gl_FragData []的一个或多个元素,但不能同时写入两者。gl_FragData 数组的大小由内置常量 gl_MaxDrawBuffers 给出。
内置变量(输入) | 形容 | 单位或坐标系 |
---|---|---|
mediump vec4 gl_FragColor; | 片段色彩 | RGBA color |
mediump vec4 gl_FragData[n] | 用于色彩附件 n 的片段色彩 | RGBA color |
uniform 状态变量
GLSL 中还有一种内置的 uniform 状态变量, gl_DepthRange
它用来表明全局深度范畴。
构造如下:
struct gl_DepthRangeParameters {
highp float near; // n
highp float far; // f
highp float diff; // f - n
};
uniform gl_DepthRangeParameters gl_DepthRange;
除了 gl_DepthRange 外的所有 uniform 状态常量都已在 GLSL 1.30 中废除。
内置常量
内置常量 | 形容 | 最小值 |
---|---|---|
const mediump int gl_MaxVertexAttribs | 示意在 vertex shader(顶点着色器)中可用的最大 attributes 数. 这个值的大小取决于 OpenGL ES 在某设施上的具体实现,但不小于最小值 | 8 |
const mediump int gl_MaxVertexUniformVectors | 示意在 vertex shader(顶点着色器)中可用的最大 uniform vectors 数. 这个值的大小取决于 OpenGL ES 在某设施上的具体实现,但不小于最小值 | 128 |
const mediump int gl_MaxVaryingVectors | 示意在 vertex shader(顶点着色器)中可用的最大 varying vectors 数. 这个值的大小取决于 OpenGL ES 在某设施上的具体实现, 但不小于最小值 | 8 |
const mediump int gl_MaxVertexTextureImageUnits | 示意在 vertex shader(顶点着色器)中可用的最大纹理单元数(贴图). 这个值的大小取决于 OpenGL ES 在某设施上的具体实现, 甚至能够一个都没有(无奈获取顶点纹理) | 0 |
const mediump int gl_MaxCombinedTextureImageUnits | 示意在 vertex Shader 和 fragment Shader 总共最多反对多少个纹理单元. 这个值的大小取决于 OpenGL ES 在某设施上的具体实现,但不小于最小值 | 8 |
const mediump int gl_MaxTextureImageUnits | 示意在 fragment Shader(片元着色器)中能拜访的最大纹理单元数, 这个值的大小取决于 OpenGL ES 在某设施上的具体实现,但不小于最小值 | 8 |
const mediump int gl_MaxFragmentUniformVectors | 示意在 fragment Shader(片元着色器)中可用的最大 uniform vectors 数, 这个值的大小取决于 OpenGL ES 在某设施上的具体实现,但不小于最小值 | 16 |
const mediump int gl_MaxDrawBuffers | 示意可用的 drawBuffers 数, 在 OpenGL ES 2.0 中这个值为 1, 在未来的版本可能会有所变动 | 1 |
内置函数
OpenGL 提供了很多的内置函数,这些函数咱们之后会常常用到,咱们当初只贴出对于这些函数的官网文档阐明,这对咱们来说曾经足够了,至于每个函数的实际,咱们当前会在之后的博客中亲自领会。
GLSL2.0 官网文档
小结
本章作为见 Android OpenGL ES – GLSL 根底篇的补充,可作为工具文档时而进行查阅。