学习是一件开心的额事情
编译GLSL 着色器的第一个步骤是由预处理进行解析的。你可能还是不知道干啥的,它的作用就是删除注释、包含其他文件以及执行宏(宏macro是一段重复文字的简短描写)替代。
GLSL 提供了一些指令,用于创建条件编译代码块以及定义一些值。但是,和 c语言的预处理器不同GLSL 并没有提供文件包含命令.你可能会问了什么叫文件包含命令,其实你是知道的,例如:#include<文件名> 接下来,我们看看GLSL 给我们提供了那些预处理指令
|预处理指令|描述| |---| |#define|控制常量和宏的定义| |#undef|控制常量和宏的定义| |#if,#ifdef,#ifndef|条件代码管理| |#else,#elif,#endif|条件表达式,只针对表达式和定义的值进行求值| |#error text|使编译器在着色器信息日志中插入text| |#program options|控制编译器的特定选项| |#extension options|根据指定的GLSL扩展,指定编译器操作| |#version number|强制要求支持一个特定版本的GLSL 版本| |#line options|控制诊断行的信号|
GLSL 预处理器允许使用宏定义,它与C语言的处理器所采用的方式极为相似,只是它并不提供字符串替换和连接工具。它可以定义单个值
#define NUM_ELEMENTS 10
#define LPos(n) gl_LightSource[(n)].position
下表是几个预定义的宏,用于协助诊断信息
|宏|定义| |---| |__LINE__|由#line指令处理和修改的换行符的数量所定义的行号| |__FILE__|当前被处理的源文件的字符串编号| |__VERSION__OpenGL|着色器语言版本的整数表示形式|
我们也可以取消宏
#undef LPos
预处理器的条件 与c语言的预处理器的处理相同,GLSL 预处理器提供了根据宏定义和整型常量求值结果的条件代码包含。 宏定义可以通过两种方式确定:
#ifdef NUM_ELEMENTS ... #endif
另外一种方法是在#if 或者#elif 指令中使用Defined 操作符: #if defined(NUM_ELEMENTS) ... #elif NUM_ELEMENTS < 7 ... #endIf
优化编译器 optimize 指令指示编译器在着色器源文件中这条指令开始的位置开启或者关闭着色器的优化 开启 #program optimize(on) 关闭 #program optimize(off) 这些选项只能在函数定义的外面使用。 调试编译器 debug 选项启用或者禁用着色器的额外诊断输出 启用
#program debug(on)
禁用 #program debug(off) 全局着色器编译选项
#program STDGL invariant(all)
为什么要搞一个扩展处理? 由于开发商可能包含于他们OpenGL 实现特定的扩展,因此着色器可能使用的扩展,对着色器的编译施加一个控制非常的有用。 怎么扩展呢? 使用指令 #extension 向着色编译器提供指令,告诉编译器应该如何处理可用的扩展
#extension extension_name:<directive>
其中,extensions_name 与glGetString(GL_EXTENSION)所返回的扩展名称相同,可以使用这条指令,它将影响所有扩展行为。
#extension all:<directive>
GLSL 扩展指令限定符
|指令|描述| |---| |require|如果不支持这个扩展或者使用了all扩展,则会产生一个错误| |enable|如果指定的特定扩展不收支持,就差生一个警告,如果使用了all扩展规范,则产生一个错误| |warn|如果指定的特定扩展不受支持,就会产生一个警告。如果在编译时,检测到使用了任何扩展,就会产生一个警告| |disable|禁止对所列出的特定扩展的支持(也就是说,这些扩展实际是支持的,编译器就当他们不支持),如果使用了all,则禁止所有的扩展|
这是一些基本的预处理指令,看完留个印象,以后会在实践中,用到的! 如需探讨技术请加群:578734141