底纹语言¶
介绍¶
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()
, if
或 clamp()
函数以确保索引在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型) |
|
vec_type step (浮动A,vec_类型B) |
|
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型) |
向量之间的距离,即 |
浮动 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的绝对导数之和 |