Shader 入门:GLSL ES(运算符和限定符)

2020-07-10 17:08:03 浏览数 (1)

正文

运算符(Operators)

使用括号包裹的内容优先级最高!

优先级

操作符

描述

1

--

后置自增、自减

2

--

前置自增、自减

2

- ~ !

一元运算

3

* % /

乘、取余、除

4

-

加、减

5

<< >>

位运算

6

< > <= >= == !=

关系运算

7

& ^ |

位与、位异或、位同或

8

&& ^^ ||

逻辑与、逻辑异或、逻辑同或

9

?:

三目运算

10

=

赋值

10

= -= *= /= %= <<= >>= &= ^= |=

算术赋值

限定符(Qualifiers)

储存限定符(Storage Qualifiers)

声明变量时可以在类型前面添加一个储存限定符。

限定词

含义

无(默认)

用于局部作用域。

const

声明为只读的常量。

in

从上一阶段输入到当前着色器。

out

从当前着色器输出到下一阶段。

uniform

在着色器、OpenGL ES 和程序之间共享的变量。

const

使用 const 限定符修饰的变量即为常量,常量一但定义就不可再修改。

适用于标量、向量、矩阵、数组和结构体,但不适用于采样器:

代码语言:javascript复制
// 声明定义常量
const int age = 18;
const vec4 color = vec4(0.5, 0.5, 0.5, 0.5);

// 也可以用于限定函数的参数
void doSomething(const float param) {
    param = 0.1; // Error! 不可!
    // ...
}
in

in 限定符常用于接收从上一阶段输出的变量:

代码语言:javascript复制
in vec3 a_position; // 接收一个顶点坐标向量
in vec2 a_uv0; // 接收一个纹理坐标向量
in vec4 a_color; // 接受一个颜色向量
out

out 限定符常用于将当前着色器中的变量输出到下一阶段:

代码语言:javascript复制
out vec2 v_uv0; // 输出一个纹理坐标向量
out vec4 v_color; // 输出一个颜色向量
uniform

使用 uniform 限定符来表示一个统一且只读的全局变量,该变量为所有着色器所共用。

注意:声明了却没有使用的 uniform 变量会在编译时被静默移除!

代码语言:javascript复制
uniform sampler2D texture;

另外 uniform 变量只能在程序中使用 OpenGL ES 的一系列 glUniform API 进行赋值:

代码语言:javascript复制
// 程序代码
int location = glGetUniformLocation(shaderProgram, "color"); // 查找 color 的位置(索引)
glUniform4f(location, 0.0f, 0.1f, 0.0f, 1.0f); // 给 color 赋值

// 着色器代码
uniform vec4 color; // vec4(0.0, 0.1, 0.0, 1.0)

参数限定符(Parameter Qualifiers)

函数的参数也可以使用限定符。

代码语言:javascript复制
和 in
 的作用一致。

使用示例:

代码语言:javascript复制
// in
void doo(in float param) { ... } // 和普通不加限定词的参数一样

// out
void foo(out int param) {
    param = 666;
}
int a; // 声明了但是没有初始化
foo(a); // a = 666
 
// inout
void goo(inout int param) {
    param = param  ;
}
int b = 1;
goo(b); // b = 2

精度限定符(Precision Qualifiers)

浮点数、整数和采样器类型声明可以添加精度限定词来设置精度范围(精度控制可以扩展至向量和矩阵)。

精度限定符不适用于常量、布尔类型和构造函数!

代码语言:javascript复制
满足顶点语言的最低要求(使用 highp
 可以获得最大的范围和精度,但是也有可能会降低运行速度)。
代码语言:javascript复制
// 变量声明
lowp float a;
mediump vec2 p;
highp mat4 m;

// 函数声明(返回值和参数)也适用
highp float foo(highp param);
默认精度限定符(Default Precision Qualifiers)

我们可以用 precision 关键字来声明指定类型的默认精度:

代码语言:javascript复制
// 声明方式
precision 精度限定符 类型;

// 示例:声明 float 类型的默认精度为 highp
precision highp float;

「未主动声明精度」的情况下,在顶点着色器中有以下默认精度声明:

代码语言:javascript复制
precision highp float;
precision highp int;
precision lowp sampler2D;
precision lowp samplerCube;

而在片段着色器中有以下默认精度声明:

代码语言:javascript复制
precision mediump int;
precision lowp sampler2D;
precision lowp samplerCube;

在片段着色器中浮点类型、浮点向量和浮点矩阵都没有默认的精度,所以使用时就必须声明其精度,或者事先声明默认精度!

另外,上面没有提到的类型都没有默认精度!

相关资料

「OpenGL ES Registry(OpenGL ES 资料页)」 https://www.khronos.org/registry/OpenGL/index_es.php

「OpenGL ES 3 Quick Reference Card(OpenGL ES 3 快速参考卡片)」 https://www.khronos.org/files/opengles3-quick-reference-card.pdf

「GLSL ES Specification 3.00(GLSL ES 规范 3.0)」 https://www.khronos.org/registry/OpenGL/specs/es/3.0/GLSL_ES_Specification_3.00.pdf

「OpenGL ES 3.0 Online Reference Pages(OpenGL ES 3.0 在线参考页)」 https://www.khronos.org/registry/OpenGL-Refpages/es3.0/

0 人点赞