Chapter 4: Shaders and Programs
Shaders and Programs
shaders object和program object,可以用c语言的编译器与链接器来类比。
每个program object必须与有且仅有一个shader object和一个fragment object关联。
Creating and Compiling a Shader
shader流程:创建shader、编写shader代码、关联shader代码与创建的shader、编译shader、获取编译结果和编译信息。
若shader已与program object关联,则调用glDeleteShader并不会立即释放shader。它只设置删除标识,并在shader不再与program object关联时才释放。
Creating and Linking a Program
program流程:创建program、绑定program与shader、链接vertex shader及fragment shader、获取链接结果与信息、获取program有效性(仅用于调试)、使用program。
链接检查的包括但不止以下内容:
1. make sure any varying variables that are consumed by the fragment shader are written by the vertex shader (and declared with the same type)
2. make sure any uniforms declared in both the vertex and fragment shader have matching types
3. make sure the final program fits within the limits of the implementation (e.g., the number of attributes, uniforms,
varyings, or instructions consumed).
Uniforms and Attributes
Uniforms:
类似c语言的const变量,存储只读信息,由应用程序传入。
整个program内共享一套Uniforms。若vertex shader和fragment shader中声明了同名uniform,那么他们必须有一样的类型和值。链接时,链接器将会为每个活跃的uniform分配地址,通过这些地址,应用程序可以获取uniform的值。
Tip:只有被program使用到的uniform才被视为活跃uniform,亦即定义未使用的uniform称为非活跃uniform。
可通过glGetActiveUniform获取活跃uniform的信息(是否数组、类型、名称等),得到名称后可通过glGetUniformLocation获取uniform位置,得到位置信息后可通过一位函数(glUniform*,这组函数需要上述获取到的Uniform类型信息作为输入)获取uniform的值。
Attributes:
只有vertex用到attribute。与uniform类似,你可查询活跃attribute,获取活跃attribute的信息。
有很多种设置vertex array来加载vertex attributes的方法。但,需要对原件(primitives)及vertex shader有深入的了解,而这部分内容将在chapter 6中讲到。
Shader Compiler and Shader Binaries
OpenGL ES2.0的目标是尽可能在有限的内存资源的设备上实现API。但是,提供一个shader编译器将耗费巨大的内存资源,尤其对于好的编译器来讲。
因此,OpenGL ES2.0标准允许直接以二进制shader作为输入OpenGL ES2.0的输入,即以编译完成的shader作为输入,而不是shader源码。这种思路,来自OpenGL ES2.0厂商提供离线工具来编译shader成二进制的想法。不同的厂商可能会实现不同的工具,很明显这将带来移植性弱的问题,但也意味着厂商们只需要实现一个不那么复杂繁重的OpenGL ES2.0接口。
可通过glGetBooleanv判断是否实现厂商是否实现了shader编译器,所有厂商提供shader编译器或二进制shader或二者兼有。若支持二进制shader,则可通过glShaderBinary来加载shader。