程序员

OpenGL ES 3.0编程指南:第五章. OpenGL ES

2016-10-10  本文已影响130人  别卡机

[TOC]

17. Preprocessor and Directives(预处理器和指令)

Shader语言的另一个功能是预处理器,遵循许多C++预处理器的约定。可以使用如下指令来定义宏和条件测试:

#define
#undef
#if
#ifdef
#ifndet
#else
#elif
#endif

注意,shader语言里的宏定义不能使用参数(在C++中可以,这是两者不同的地方)。下面的宏是预定义的:

__LINE__    // Replaced with the current line number in a shader
__FILE    // Always 0 in OpenGL ES 3.0
__VERSION__     // The OpenGL ES shading language version (eg. 300)
GL_ES    // This will be defined for ES shaders to a value of 1

指令#error会在shader编译时引发一个编译错误,并打印出相关日志。指令#pragma用于为编译器指定特定于实现的指令。

另一个重要指令是#extension,用来启用和设置扩展行为。当设备供应商扩展OpenGL ES shader语言时,它们将创建一个语言扩展声明(例如 GL_NV_shadow_samplers_cube)。Shader必须告诉编译器是否允许使用扩展,如果不允许,应该采取什么行动。使用方法:

#extension extension_name : behavior
#extension all : behavior

第一个参数是扩展的名字或者all(对所有扩展都应用该行为),第二个参数是要采取的行为:

扩展行为 描述
require require指明该扩展是必须的,如果该扩展不受支持则预处理器会抛出错误。如果指定了all,将总是抛出错误。
enable enable指明该扩展被启用,如果该扩展不受支持则预处理器会发出警告。如果扩展被启用,语言将会被处理。如果指定了all,将总是抛出错误。
warn warn指明当该扩展被使用时发出警告(除非这种使用是另一个已经被启用的扩展所必须的)。如果指定了all,则在任何该扩展被使用时发出警告。同时,如果该扩展不被支持也会发出警告。
disable disable指明该扩展是禁用的,所有当该扩展被使用时将会抛出错误。如果指定了all(默认),则不启用任何扩展。

18. Uniform and Interpolator Packing

正如前面几个小节中所介绍的,在底层硬件中可用于储存uniform和输入输出变量的资源是有限的。Uniform储存在“常量储存区”,顶点输出变量和片段输入变量储存在插值器中,通常都保存为一个向量数组。那么,这些变量在底层硬件上到底是如何进行实际储存的呢?

在OpenGL ES 3.0中,通过打包规则(packing)来定义这些变量是如何映射到物理储存空间的。打包规则基于这样一个概念,物理储存空间被组织为一个4列的网格(每一行是一个储存位置)。来看一个具体例子:

uniform mat3 m;
uniform float f[6];
uniform vec3 v;

如果不进行打包,那么矩阵m会占用3行,数组f会占用6行,向量v会占用1行,这样会浪费许多空间,如下表所示:

Location X Y Z W
0 m[0].x m[0].y m[0].z --
1 m[1].x m[1].y m[1].z --
2 m[2].x m[2].y m[2].z --
3 f[0] -- -- --
4 f[1] -- -- --
5 f[2] -- -- --
6 f[3] -- -- --
7 f[4] -- -- --
8 f[5] -- -- --
9 v.x v.y v.z -6(书上写的-6,不明白为什么,觉得应该也是空才对)

如果进行打包,这些变量会被组织成下面这样:

Location X Y Z W
0 m[0].x m[0].y m[0].z f[0]
1 m[1].x m[1].y m[1].z f[1]
2 m[2].x m[2].y m[2].z f[2]
3 v.x v.y v.z f[3]
4 -- -- -- f[4]
5 -- -- -- f[5]

如果所示,如果使用了打包规则,只需要使用6个物理常量位置,否则就要使用10个。另外,数组元素需要跨行存储,这是因为GPU通常根据物理常量位置索引来对常量储存进行索引,如果数组的元素没有跨行存储,那么数组的索引将不会起作用。

打包将影响uniform和输入输出变量的计数方式。如果想要编写在所有实现都能正常运行的shader,就要确保使用的变量数不超过OpenGL ES的所有实现所支持的数量。因此,了解打包规则就很重要的。

上一篇 下一篇

猜你喜欢

热点阅读