底纹语言

介绍

Godot使用类似于glsl es 3.0的着色语言。大多数数据类型和函数都受支持,剩下的少数数据类型和函数可能会随着时间的推移而添加。

如果您已经熟悉GLSL, Godot Shader Migration Guide 是帮助您从常规GLSL转换为Godot的着色语言的资源。

数据类型

支持大多数glsl es 3.0数据类型:

类型

描述

void

void数据类型,仅对不返回任何值的函数有用。

bool

布尔数据类型,只能包含“true”或“false”。

BVEC2

布尔值的双分量向量。

BVEC3

布尔值的三分量向量。

BVEC4

布尔值的四分量向量。

int

有符号标量整数。

IVEC2

有符号整数的双分量向量。

IVEC3

有符号整数的三分量向量。

IVEC4

有符号整数的四分量向量。

uint

无符号标量整数;不能包含负数。

UVEC2

无符号整数的双分量矢量。

小精灵

无符号整数的三分量矢量。

UVEC4

无符号整数的四分量向量。

浮动

浮点标量。

vec2

浮点值的双分量向量。

vec3

浮点值的三分量向量。

vec4

浮点值的四分量向量。

mat2

2x2矩阵,按主列顺序排列。

mat3

3x3矩阵,按列主顺序排列。

mat4

4x4矩阵,按主列顺序排列。

取样器2d

用于绑定二维纹理的采样器类型,该类型读取为float。

示例2d

用于绑定二维纹理的采样器类型,该类型读取为有符号整数。

示例2d

用于绑定二维纹理的采样器类型,该类型读取为无符号整数。

采样器2阵列

用于绑定二维纹理数组的采样器类型,该数组读取为float。

示例2 darray

用于绑定二维纹理数组的采样器类型,该数组读取为有符号整数。

示例2 darray

用于绑定二维纹理数组的采样器类型,该数组读取为无符号整数。

采样器3D

用于绑定3D纹理的采样器类型,其读作float。

示例3D

用于绑定3D纹理的采样器类型,读取为有符号整数。

示例3D

用于绑定3D纹理的采样器类型,该类型读取为无符号整数。

采样立方体

用于绑定cubemaps的采样器类型,它被读取为浮点数。

铸造

与glsl es 3.0一样,不允许在相同大小但不同类型的标量和向量之间进行隐式强制转换。也不允许铸造不同尺寸的类型。转换必须通过构造函数显式完成。

例子:

float a = 2; // invalid
float a = 2.0; // valid
float a = float(2); // valid

默认整型常量有符号,因此始终需要强制转换为无符号:

int a = 2; // valid
uint a = 2; // invalid
uint a = uint(2); // valid

成员

向量类型的单个标量成员通过“x”、“y”、“z”和“w”成员访问。或者,使用“r”、“g”、“b”和“a”也可以,并且是等效的。使用最适合您需要的工具。

对于矩阵,使用 m[row][column] 访问每个标量的索引语法,或 m[idx] 按行索引访问向量。例如,用于访问Mat4中对象的Y位置 m[3][1] .

构造

矢量类型的构造必须始终通过:

// The required amount of scalars
vec4 a = vec4(0.0, 1.0, 2.0, 3.0);
// Complementary vectors and/or scalars
vec4 a = vec4(vec2(0.0, 1.0), vec2(2.0, 3.0));
vec4 a = vec4(vec3(0.0, 1.0, 2.0), 3.0);
// A single scalar for the whole vector
vec4 a = vec4(0.0);

矩阵类型的构造需要与矩阵具有相同维度的向量。您还可以使用 matx(float) 语法。因此, mat4(1.0) 是一个单位矩阵。

mat2 m2 = mat2(vec2(1.0, 0.0), vec2(0.0, 1.0));
mat3 m3 = mat3(vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0));
mat4 identity = mat4(1.0);

矩阵也可以从另一个维度的矩阵构建。有两条规则:如果一个较大的矩阵是由较小的矩阵构成的,则将额外的行和列设置为它们在标识矩阵中所具有的值。如果较小的矩阵是由较大的矩阵构成的,则使用较大矩阵的左上子矩阵。

mat3 basis = mat3(WORLD_MATRIX);
mat4 m4 = mat4(basis);
mat2 m2 = mat2(m4);

旋转

只要结果是另一个向量类型(或标量),就可以以任何顺序获得组件的任意组合。这比解释更容易显示:

vec4 a = vec4(0.0, 1.0, 2.0, 3.0);
vec3 b = a.rgb; // Creates a vec3 with vec4 components.
vec3 b = a.ggg; // Also valid; creates a vec3 and fills it with a single vec4 component.
vec3 b = a.bgr; // Order does not matter.
vec3 b = a.xyz; // Also rgba, xyzw are equivalent.
float c = b.w; // Invalid, because "w" is not present in vec3 b.

精密度

可以向数据类型添加精度修饰符;将其用于一致性、变量、参数和变量:

lowp vec4 a = vec4(0.0, 1.0, 2.0, 3.0); // low precision, usually 8 bits per component mapped to 0-1
mediump vec4 a = vec4(0.0, 1.0, 2.0, 3.0); // medium precision, usually 16 bits or half float
highp vec4 a = vec4(0.0, 1.0, 2.0, 3.0); // high precision, uses full float or integer range (default)

对某些操作使用较低的精度可以加快所涉及的数学运算(以较低的精度为代价)。这在顶点处理器功能中很少需要(在大多数情况下需要完全精度),但在片段处理器中通常很有用。

请记住,有些架构(主要是移动架构)从中受益匪浅,但也受到限制(精确性之间的转换成本较高)。请阅读有关目标体系结构的相关文档以了解更多信息。不过,老实说,移动驱动程序很麻烦,因此,为了避免麻烦,制作简单的着色器,而不指定精度,除非 真正地 需要。

数组

数组是用于存放类似类型的多个变量的容器。注意:从Godot3.2开始,只实现了本地数组。

本地数组

局部数组在函数中声明。他们可以使用所有允许的数据类型,除了采样器。数组声明遵循C样式语法: typename + identifier + [array size] .

void fragment() {
    float arr[3];
}

它们可以在开始时初始化如下:

float arr[3] = float[3] (1.0, 0.5, 0.0); // first constructor

vec2 arr_v2[2] = { vec2(0.0, 0.0), vec2(1.0, 1.0) }; // second constructor

bool bvec_arr[] = { false, false, true, true }; // third constructor - size is defined automatically from the argument count

可以在一个表达式中声明多个数组(即使大小不同):

float a[3] = float[3] (1.0, 0.5, 0.0),
 b[2] = {1.0, 0.5},
 c[] = { 0.7 },
 d = 0.0,
 e[5];

要访问数组元素,请使用索引语法:

float arr[3];

arr[0] = 1.0; // setter

COLOR.r = arr[0]; // getter

数组还具有内置函数 .length() (不要与内置 length() 功能)。它不接受任何参数,将返回数组的大小。

float arr[] = { 0.0, 1.0, 0.5, -1.0 };
for (int i = 0; i < arr.length(); i++) {
    // ...
}

注意:如果使用小于0或大于数组大小的索引,则着色器将崩溃并中断渲染。要防止这种情况,请使用 length()ifclamp() 函数以确保索引在0和数组长度之间。务必仔细测试和检查您的代码。如果传递常量表达式或简单数字,编辑器将检查其边界,以防止发生此崩溃。

常量

使用 const 关键字前面的变量声明使该变量不可变,这意味着它不能被修改。所有基本类型(采样器除外)都可以声明为常量。访问和使用常量值比使用统一值稍快。

const vec2 a = vec2(0.0, 1.0);
vec2 b;

a = b; // invalid
b = a; // valid

不能修改常量,另外也不能有提示,但可以在单个表达式中声明多个常量(如果它们具有相同的类型),例如

const vec2 V1 = vec2(1, 1), V2 = vec2(2, 2);

与变量类似,数组也可以用 const .

const float arr[] = { 1.0, 0.5, 0.0 };

arr[0] = 1.0; // invalid

COLOR.r = arr[0]; // valid

常量既可以全局(在任何函数外部)声明,也可以本地(在函数内部)声明。当您希望访问不需要修改的整个着色器中的值时,全局常量非常有用。与统一体一样,全局常量在所有明暗器阶段之间共享。但是,它们在明暗器之外是不可访问的,必须在声明时初始化。

shader_type spatial;

const float PI = 3.14159265358979323846;

算子

godot着色语言支持与glsl es 3.0相同的一组运算符。以下是它们的优先顺序列表:

优先

等级

算符

1(最高)

附加分组

()

2

一元的

+, -, !, ~

3

乘法

/, *, %

4

添加剂

+, -

5

逐位移位

<<, >>

6

关系型

<, >, <=, >=

7

平等

==, !=

8

有点聪明和

&

9

位智能独占或

^

10

位包含或

|

11

逻辑与

&&

12(最低)

逻辑包含或

||

流量控制

Godot着色语言支持最常见的流控制类型:

// if and else
if (cond) {

} else {

}

// for loops
for (int i = 0; i < 10; i++) {

}

// while
while (true) {

}

请记住,在现代GPU中,可以存在无限循环,并且可以冻结应用程序(包括编辑器)。Godot保护不了你,所以小心别犯这个错误!

丢弃

碎片和光功能可以使用 丢弃 关键字。如果使用,片段将被丢弃,不会写入任何内容。

功能

可以在godot明暗器中定义函数。它们使用以下语法:

ret_type func_name(args) {
    return ret_type; // if returning a value
}

// a more specific example:

int sum2(int a, int b) {
    return a + b;
}

您只能使用在您从其调用函数的上方(编辑器中的较高位置)定义的函数。

函数参数可以具有特殊限定符:

  • in :表示参数仅用于读取(默认)。

  • out :表示参数仅用于写入。

  • 输入输出 :表示参数通过引用完全传递。

示例如下:

void sum2(int a, int b, inout int result) {
    result = a + b;
}

变容

要将数据从顶点发送到片段处理器函数, 变容 使用。它们被设置为 顶点处理器 ,并为片段处理器中的每个像素插入值。

shader_type spatial;

varying vec3 some_color;
void vertex() {
    some_color = NORMAL; // Make the normal the color.
}

void fragment() {
    ALBEDO = some_color;
}

插值限定符

在着色管道中插入某些值。您可以通过使用 插值限定符 .

shader_type spatial;

varying flat vec3 our_color;

void vertex() {
    our_color = COLOR.rgb;
}

void fragment() {
    ALBEDO = our_color;
}

有两个可能的插值限定符:

限定符

描述

flat

该值不被插值。

光滑的

该值以透视正确的方式插入。这是默认设置。

制服

可以将值传递给着色器。这些对整个明暗器都是全局的,称为 制服 . 稍后将明暗器指定给材质时,制服将在其中显示为可编辑参数。不能从明暗器中写入制服。

shader_type spatial;

uniform float some_value;

可以在材质的编辑器中设置制服。或者您可以通过gdscript设置它们:

material.set_shader_param("some_value", some_value)

注解

第一个论点 set_shader_param 是明暗器中统一体的名称。它必须匹配 确切地 在材质球中统一的名称,否则将无法识别。

任何GLSL类型,除了 void 可以是制服。此外,godot还提供了可选的明暗器提示,以使编译器了解使用什么统一体。

shader_type spatial;

uniform vec4 color : hint_color;
uniform float amount : hint_range(0, 1);
uniform vec4 other_color : hint_color = vec4(1.0);

以下提示的完整列表:

类型

暗示

描述

vec4

hint_color

用作颜色

int,浮点

提示范围(最小,最大 [,步骤] )

用作范围(最小/最大/步进)

取样器2d

hint_albedo

用作反照率颜色,默认为白色

取样器2d

hint_black_albedo

用作反照率颜色,默认为黑色

取样器2d

hint_normal

用作NormalMap

取样器2d

hint_white

默认为白色。

取样器2d

hint_black

作为值,默认为黑色

取样器2d

hint_aniso

作为流程图,默认为右。

gdscript使用的变量类型与glsl不同,因此在将变量从gdscript传递到着色器时,godot会自动转换类型。以下是相应类型的表:

gdscript类型

GLSL类型

bool

bool

int

int

浮动

浮动

二维向量

vec2

矢量3

vec3

颜色

vec4

变换

mat4

变压器2D

mat4

注解

在从gdscript设置shader uniforms时要小心,如果类型不匹配,则不会引发任何错误。您的明暗器将只显示未定义的行为。

由于Godot的3D引擎在线性颜色空间中渲染,因此重要的是要了解作为颜色(即反照率)提供的纹理需要指定为这样才能进行正确的sRGB->线性转换。

也可以为制服指定默认值:

shader_type spatial;

uniform vec4 some_vector = vec4(0.0);
uniform vec4 some_color : hint_color = vec4(1.0);

内置功能

支持大量内置功能,符合GLSL ES 3.0。当使用vec_type(float)、vec_int_type、vec_uint_type、vec_bool_type命名法时,它可以是标量或矢量。

注解

有关gles2后端中不可用的函数列表,请参阅 Differences between GLES2 and GLES3 doc .

功能

描述

vec_type 弧度 (vec_型度数)

将度转换为弧度

vec_type (vec_型弧度)

将弧度转换为度数

vec_type sin (vec_类型x)

正弦

vec_type cos (vec_类型x)

余弦

vec_type tan (vec_类型x)

切线

vec_type asin (vec_类型x)

弧正弦

vec_type acos (vec_类型x)

弧余弦

vec_type atan (vec_type y_over_x)

弧切线

vec_type atan (vec_类型Y,vec_类型X)

弧切线,用于将矢量转换为角度

vec_type sinh (vec_类型x)

双曲正弦

vec_type cosh (vec_类型x)

双曲余弦

vec_type tanh (vec_类型x)

双曲正切

vec_type 反双曲正弦 (vec_类型x)

反双曲正弦

vec_type 阿科什 (vec_类型x)

反双曲余弦

vec_type 反双曲正切 (vec_类型x)

反双曲正切

vec_type pow (vec_类型x,vec_类型y)

功率

vec_type exp (vec_类型x)

基E指数

vec_type exp2 (vec_类型x)

基2指数

vec_type log (vec_类型x)

自然对数

vec_type log2 (vec_类型x)

以2为底的对数

vec_type sqrt (vec_类型x)

平方根

vec_type 逆平方 (vec_类型x)

反平方根

vec_type abs (vec_类型x)

绝对的

ivec_type abs (Ivec_x型)

绝对的

vec_type sign (vec_类型x)

符号

ivec_type sign (Ivec_x型)

符号

vec_type 地板 (vec_类型x)

楼板

vec_type (vec_类型x)

回合

vec_type 圆场 (vec_类型x)

最接近偶数的圆

vec_type 躯干 (vec_类型x)

截断

vec_type ceil (vec_类型x)

塞尔

vec_type 弗兰克 (vec_类型x)

分数的

vec_type mod (vec_类型x,vec_类型y)

余数

vec_type mod (vec_类型x,浮动y)

余数

vec_type modf (vec_类型x,out vec_类型i)

x的分数,i的整数部分

vec_type min (vec_A型,vec_B型)

最小值

vec_type max (vec_A型,vec_B型)

最大值

vec_type 夹紧 (vec_类型x,vec_类型min,vec_类型max)

夹钳至最小最大值

vec_type mix (浮动A、浮动B、浮动C)

线性插值

vec_type mix (vec_A型、vec_B型、float C)

线性插值(标量系数)

vec_type mix (vec_A型、vec_B型、vec_C型)

线性插值(向量系数)

vec_type mix (vec_A型、vec_B型、bvec_C型)

线性插值(布尔向量选择)

vec_type step (vec_A型,vec_B型)

b[i] < a[i] ? 0.0 : 1.0

vec_type step (浮动A,vec_类型B)

b[i] < a ? 0.0 : 1.0

vec_type 光滑的台阶 (vec_A型、vec_B型、vec_C型)

埃尔米特插值

vec_type 光滑的台阶 (浮动A、浮动B、矢量C型)

埃尔米特插值

bvec_type 伊斯南 (vec_类型x)

标量或矢量分量为NaN

bvec_type 伊辛 (vec_类型x)

标量或矢量分量是inf

ivec_type 浮动位图 (vec_类型x)

float->int位复制,无转换

uvec_type 漂浮物 (vec_类型x)

float->uint位复制,无转换

vec_type intbitstofloat (Ivec_x型)

int->浮点复制,无转换

vec_type uintbitstofloat (uvec_型x)

uint->浮点复制,无转换

浮动 长度 (vec_类型x)

矢量长度

浮动 距离 (vec_A型,vec_B型)

向量之间的距离,即 length(a - b)

浮动 dot (vec_A型,vec_B型)

DOT产品

VEC3 交叉 (矢量3 A、矢量3 B)

交叉积

vec_type 归一化 (vec_类型x)

标准化为单位长度

VEC3 反映 (vec3 i,vec3 n)

反射

VEC3 折射 (vec3 i、vec3 n、float eta)

折射

vec_type 正面朝前 (vec_n型、vec_i型、vec_nref型)

如果点(nref,i)<0,返回n,否则–n

mat_type 矩阵复合 (材料类型X,材料类型Y)

矩阵分量乘法

mat_type 外部产品 (vec_类型列,vec_类型行)

矩阵外积

mat_type 转置 (材料类型M)

转置矩阵

浮动 行列式 (材料类型M)

矩阵行列式

mat_type (材料类型M)

逆矩阵

bvec_type 雷斯坦 (vec_类型x,vec_类型y)

bool vector cmp on<int/uint/float vectors

bvec_type 大于 (vec_类型x,vec_类型y)

bool vector cmp on>int/uint/float vectors

bvec_type 不相等 (vec_类型x,vec_类型y)

bool vector cmp on<=int/uint/float vectors

bvec_type 大于等于 (vec_类型x,vec_类型y)

bool vector cmp on>=int/uint/float vectors

bvec_type 平等的 (vec_类型x,vec_类型y)

bool vector cmp on==int/uint/float vectors

bvec_type 不相等 (vec_类型x,vec_类型y)

布尔向量CMP打开!=int/uint/浮点向量

布尔 any (bvec_x型)

任何成分都是真的

布尔 all (bvec_x型)

所有组件都是真的

bvec_type not (bvec_x型)

反转布尔向量

IVEC2 纹理化 (sampler2d_类型S,int lod)

获取二维纹理的大小

IVEC3 纹理化 (sampler2darray_类型S,int lod)

获取二维纹理数组的大小

IVEC3 纹理化 (采样器3d s,int lod)

获取三维纹理的大小

IVEC2 纹理化 (采样立方体S,int lod)

获取立方体纹理的大小

vec4_type 纹理 (S型,Vec2紫外线采样器 [,浮动偏差] )

执行二维纹理读取

vec4_type 纹理 (sampler2darray_类型S,vec3 uv [,浮动偏差] )

执行二维纹理数组读取

vec4_type 纹理 (sampler3d_S型,vec3 uv [,浮动偏差] )

执行3D纹理读取

VEC4 纹理 (采样立方体S,vec3 uv [,浮动偏差] )

执行立方体纹理读取

vec4_type 纹理项目 (S型、Vec3紫外线采样器 [,浮动偏差] )

使用投影执行二维纹理读取

vec4_type 纹理项目 (S型,Vec4-uv采样器 [,浮动偏差] )

使用投影执行二维纹理读取

vec4_type 纹理项目 (sampler3d_S型,vec4 uv [,浮动偏差] )

使用投影执行3D纹理读取

vec4_type 纹理图 (S型、Vec2-UV、Float Lod样品)

在自定义mipmap中执行二维纹理读取

vec4_type 纹理图 (sampler2darray_type S,vec3 uv,float lod)

在自定义mipmap上执行二维纹理数组读取

vec4_type 纹理图 (sampler3d_类型S,vec3 uv,float lod)

在自定义mipmap中执行3D纹理读取

VEC4 纹理图 (采样立方体S、vec3 uv、float lod)

在自定义mipmap中执行3D纹理读取

vec4_type 纹理项目 (S型、Vec3紫外、Float Lod样品)

使用投影/lod执行二维纹理读取

vec4_type 纹理项目 (S型、Vec4紫外线、Float Lod样品)

使用投影/lod执行二维纹理读取

vec4_type 纹理项目 (sampler3d_类型S、vec4 uv、float lod)

使用投影/lod执行三维纹理读取

vec4_type 特赛尔费特 (sampler2d_类型S,ivec2 uv,int lod)

使用整数坐标获取单个texel

vec4_type 特赛尔费特 (sampler2darray_类型S,ivec3 uv,int lod)

使用整数坐标获取单个texel

vec4_type 特赛尔费特 (sampler3d_类型S,ivec3 uv,int lod)

使用整数坐标获取单个texel

vec_type dFdx (P型车辆)

用局部差分法求x的导数

vec_type dFdy (P型车辆)

利用局部差分法求Y的导数

vec_type 宽度 (P型车辆)

x和y的绝对导数之和