GLSL-语法基础

3.1 字符集

GLSL用到的字符集是ASCII码的子集,主要包含下面的几部分:

  1. 字母 a-z,A-Z,以及下划线“_”。
  2. 数字 0-9
  3. 符号 .+-/*%<>[]{}()|$~=!:;,?
  4. 预处理器专用符号 #
  5. 空白符,包括各种回车、换行、TAB等等

该字符集不包含反斜杠**,也不包含任何字符或字符串。 一般来说,GLSL是大小写敏感的。

3.2 Source Strings

不管是Vertex Shader还是Fragment Shader,其实都有一段对应的代码,称为Source Strings,它包含多个string,每个string一行。

对于本版本的GLSL来说,每个Shader对应着一个可编程单元,一个Vertex Shader对应着一个Fragment Shader,二者连接起来组成一个program

3.3 编译的逻辑阶段

编译程序使用C++标准的一个子集。 Vertex Shader和Fragment Shader在各自编译之后连接到一起。

编译的步骤如下:

  1. .glsl文件中得到Source String
  2. Source Strings被转成一系列的预处理Token,这些Token包括预处理行号、预处理标识、预处理操作。注释被替换成空格。保留换行。
  3. 预处理器执行。执行命令,执行宏扩展。
  4. 预处理Token被转换成Token
  5. 空白符、换行符被丢弃。
  6. 根据GLSL语法进行语法分析。
  7. 根据GLSL语义规则进行语义检查。
  8. Vertex Shader和Fragment Shader连接到一起,丢弃没有被二者同时使用的varying变量。
  9. 生成二进制文件。

3.4 预处理器

作为编译的其中一个步骤,预处理器会处理source strings。

预处理指令以#开头,#号之前不能有除了空白字符之外的任何字符。每一个指令独占一行。 预处理指令只能使用上面列出的指令,使用其他未定义指令会报错。

完整的预处理器指令如下:

#
#define
#undef
#if
#ifdef
#ifndef
#else
#elif
#endif
#error
#pragma
#extension
#version
#line

下面的这个操作符也是合法的:

defined

#define and #undef

这两个和C++中的用法完全一样,不做过多说明

#if, #ifdef, #ifndef, #else, #elif, and #endif

这几个也基本和C++的用法一样,不过有下面几点差别。

1. #if和#elif只能判断int类型,0为false,非0为true
2. 不支持string类型

#pragma

编译指示。用来控制编译器的一些行为。

#pragma optimize(on)
#pragma optimize(off)

在开发和调试时可以设置为off,默认设为on。

#pragma debug(on)
#pragma debug(off)

在开发和调试时可以打开debug选项,以便获取更多的调试信息。默认设为off。

#version

每一个编译单元都要指定GLSL的版本,如下:

#version number

一般默认即可。这个命令必须放到编译单元的最前面,其前面只能有注释或空白,不能有其他字符。

#extension

如果想使用GLGL默认不支持的操作,则必须启用对应的扩展,启用一个扩展可以使用下面的命令:

#extension : behavior
#extension all : behavior

其中,extension_name是扩展的名称,all是指所有的编译器支持的扩展。 behavior是指对该扩展的具体操作。比如启用、禁用等等。详情如下:

behavior

作用

require

启用该扩展。如果不支持,则报错。

enable

启用该扩展。如果不支持,则会警告。extension_name是all的时候会报错。

warn

启用该扩展。但是会检测到所有使用该扩展的地方,提出警告。

disable

禁用该扩展。如果该扩展不被支持,则提出警告。

默认是不会启用任何扩展,就像是执行了下面的命令:

#extension all : disable

对于每一个被支持的扩展,都有一个对应的宏定义,我们可以用它来判断编译器是否支持该扩展。

#ifdef OES_extension_name
#extension OES_extension_name : enable
    // code that requires the extension
#else
    // alternative code
#endif

一些预定义的变量

除此之外,还预定义了一些变量:

  • __LINE__ :int类型,当前的行号,也就是在Source String中是第一行
  • __FILE__ :int类型,当前Source String的唯一ID标识
  • __VERSION__ :int类型,GLGL的版本
  • GL_ES :对于嵌入式系统(Embed System,简称 ES),它的值为1,否则为0

所有的以两个下划线__开头的变量都是系统保留的,不允许私自定义和篡改。

操作符

优先级

类型

操作符

结合性

1

括号

()

2

一元运算符

defined + - ~ !

| 从右往左 | | 3 | 乘除法 | * / % | 从左往右 | | 4 | 加减法 | + - | 从左往右 | | 5 | 位运算 移位 | << >> | 从左往右 | | 6 | 大小关系 | < > <= >= | 从左往右 | | 7 | 相等性判断 | == != | 从左往右 | | 8 | 位运算 与 | & | 从左往右 | | 9 | 位或算 非 | ^ | 从左往右 | | 10 | 位或算 或 | | | 从左往右 | | 11 | 逻辑与 | && | 从左往右 | | 12 | 逻辑或 | || | 从左往右 |

defined操作符一般有下面两种使用方式:

defined identifier
defined ( identifier )

注释

和Java里的注释没啥区别。主要有下面两种注释方法。

// 我是注释
/* 我是注释 */

Tokens

Source String会被转成一系列的Tokens。可以这么理解,代码中的每一个单词都属于某一种Token。比如关键词、数字、变量等等。GLSL中,Token主要有下面几种:

Token

解释

举例

keyword

关键词

if elif ...

identifier

标识符

自定义的函数名、变量名 ...

integer-constant

int常量

1 2 3 ...

float-constant

float常量

1.1 1.2 1.3 ...

operator

操作符

+ - * / ...

关键词

列举一下GLSL中的关键词,这些全部是系统保留的,不可私自篡改。

attribute const uniform varying
break continue do for while
if else
in out inout
float int void bool true false
lowp mediump highp precision invariant
discard return
mat2 mat3 mat4
vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4
sampler2D samplerCube
struct

下面的这些也被系统预留了,使用它们会报错。

asm
class union enum typedef template this packed
goto switch default
inline noinline volatile public static extern external interface flat
long short double half fixed unsigned superp
input output
hvec2 hvec3 hvec4 dvec2 dvec3 dvec4 fvec2 fvec3 fvec4
sampler1D sampler3D
sampler1DShadow sampler2DShadow
sampler2DRect sampler3DRect sampler2DRectShadow
sizeof cast
namespace using

除此之外,所有的以"__"开头的变量全部是预留的,自定义的变量不能以“__”开头。

标识符

标识符其实就是指用户自定义的变量名、函数名、结构体名等等。

变量名可以由下面的字符组成:

_ a b c d e f g h i j k l m n o p q r s t u v w x y z
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
0 1 2 3 4 5 6 7 8 9

用户可以随便定义标识符,但是不能以gl_开头,因为以gl_开头的都是系统预留的。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏魂祭心

原 canvas绘制clock

4164
来自专栏Ceph对象存储方案

Luminous版本PG 分布调优

Luminous版本开始新增的balancer模块在PG分布优化方面效果非常明显,操作也非常简便,强烈推荐各位在集群上线之前进行这一操作,能够极大的提升整个集群...

3185
来自专栏我和未来有约会

Silverlight第三方控件专题

这里我收集整理了目前网上silverlight第三方控件的专题,若果有所遗漏请告知我一下。 名称 简介 截图 telerik 商 RadC...

4045
来自专栏一个爱瞎折腾的程序猿

sqlserver使用存储过程跟踪SQL

USE [master] GO /****** Object: StoredProcedure [dbo].[sp_perfworkload_trace_s...

2070
来自专栏pangguoming

Spring Boot集成JasperReports生成PDF文档

由于工作需要,要实现后端根据模板动态填充数据生成PDF文档,通过技术选型,使用Ireport5.6来设计模板,结合JasperReports5.6工具库来调用渲...

1.2K7
来自专栏张善友的专栏

Silverlight + Model-View-ViewModel (MVVM)

     早在2005年,John Gossman写了一篇关于Model-View-ViewModel模式的博文,这种模式被他所在的微软的项目组用来创建Expr...

2978
来自专栏我和未来有约会

Kit 3D 更新

Kit3D is a 3D graphics engine written for Microsoft Silverlight. Kit3D was inita...

2576
来自专栏跟着阿笨一起玩NET

c#实现打印功能

2802
来自专栏转载gongluck的CSDN博客

cocos2dx 打灰机

#include "GamePlane.h" #include "PlaneSprite.h" #include "BulletNode.h" #include...

5556
来自专栏陈仁松博客

ASP.NET Core 'Microsoft.Win32.Registry' 错误修复

今天在发布Asp.net Core应用到Azure的时候出现错误InvalidOperationException: Cannot find compilati...

4868

扫码关注云+社区