引言

Godot 使用的了一种非常接近GLSL ES 3.0的着色器语言,并且支持其绝大多数的数据类型和函数,尚未完全支持的部分也会逐渐增加进去。

如果你对GLSL熟悉的话,可以直接阅读 《Godot Shader Migration Guide》 以帮助你从标准GLSL过渡到Godot Shader。

数据类型

支持绝大多数GLSL ES 3.0数据类型:

类型 描述
void 空类型
bool 布尔型
bvec2 2维布尔
bvec3 3维布尔
bvec4 4维布尔
int 有符号整型
ivec2 2维整型
ivec3 3维整型
ivec4 4维整型
uint 无符号整型
uvec2 2维无符号整型
uvec3 3维无符号整型
uvec4 4维无符号整型
mat2 2维矩阵
mat3 3维矩阵
mat4 4维矩阵
sampler2D 2维采样 用于绑定2维材质,以float形式读取
isampler2D 2维整型采样 用于绑定2维材质,以int形式读取
usampler2D 2维无符号整型采样 用于绑定2维材质,以uint形式读取
samplerCude 3维采样 用于绑定3维立方贴图,以float形式读取
类型转换(Casting)

和GLSL ES 3.0一样,无论是标量(Scalar)还是向量(Vector),即使维度(size)相同,但如果类型不同,也是无法进行隐式(implicit)类型转换。如果连维度都不同,则更加不能够隐式转换。所有的类型转换必须是显式(explicit)的且基于构造函数来实现。

例子

float a = 2; // 非法
float a = 2.0; // 合法
float a = float(2); // 合法

默认的整型是有符号的,因此要赋值给无符号整型也需要进行类型转换

int a = 2; // 合法
uint a = 2; // 非法
uint a = uint(2); // 合法
成员变量(Members)

向量中的分量值可以使用“x”, “y”, “z” 或者“w”来访问,同时也可已使用“r”, “g”, “b” 和“a”来访问,二者是等效的。哪一个更加直观方便就可以使用哪一个。

对于矩阵(matrices),可以使用m[row][colum]的形式访问其每一个元素,或者以m[idx]的形式使用行索引(row index)访问一个行向量。例如访问一个mat4(4x4的矩阵)中的位置y,我们可以这样做m[3][1]

构造(Constructing)

构造向量类型可以按照如下例子传参数:

// 传递所需数量的分量参数
vec4 a = vec4(0.0, 1.0, 2.0, 3.0);
// 传递互补的 向量 及/或 标量
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);
// 也可以为整个向量传一个值
vec4 a = vec4(0.0);

构造矩阵要求向量的维度和矩阵维精度(Precision)度相同,当然你也可以使用matx(float)的形式构造一个对角矩阵(diagonal matrix),例如mat4(1.0)代表一个4维单位矩阵(identity matrix)

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);

矩阵可以由不同维度的矩阵创建,但是要注意两个原则:

  1. 如果用一个小维度矩阵创建一个大维度矩阵,那么剩余的部分,将由大维度矩阵的单位矩阵相对应值填充

  2. 如果用一个大维度矩阵创建一个小维度矩阵,那么将截取大维度矩阵左上角的子矩阵

mat3 basis = mat3(WORLD_MATRIX);
mat4 m4 = mat4(basis);
mat2 m2 = mat2(m4);
混写(Swizzling)

(注:Swizzling直译是旋转,在此处的意译取网上的一种翻译"混写")

混写是指可以获取向量分量任意顺序组合,只要(组合的)结果依然是向量或者标量,举个例子更好理解:

vec4 a = vec4(0.0, 1.0, 2.0, 3.0);
vec3 b = a.rgb; // 用vec4的分量“混写”构造一个vec3
vec3 b = a.ggg; // 依然合法; 用vec4的单一分量“混写”构造一个vec3
vec3 b = a.bgr; // 分量的顺序是无关紧要的
vec3 b = a.xyz; // 用xyzw依然等效
float c = b.w; // 非法, 因为作为vec3的b中不包含"w"分量.
精度(Precision)

可以对uniform, variable, argument 以及 varying等数据添加精度修改器(modifier):

lowp vec4 a = vec4(0.0, 1.0, 2.0, 3.0); // 低精度, 每分量8字节并映射到0-1区间
mediump vec4 a = vec4(0.0, 1.0, 2.0, 3.0); // 中等精度,每分量16字节或半长浮点精度
highp vec4 a = vec4(0.0, 1.0, 2.0, 3.0); // 高精度, 全长浮点精度或整型值域(默认)

对于某些运算以损失精度为代价,使用较低精度,可以换取一些数学运算方面的提速。注意:在顶点处理函数(vertex processor function)几乎不会这样做(此时一般都采用高精度),但是在片元处理器中,使用较低精度是很有效的。

记住,以移动设备为主的一些架构,在这个机制上收益匪浅,但也存在一些约束(主要是不同精度间的转换也存在一些计算量)。请阅读针对目标架构的相关文档获取更多信息。不过说实话,移动设备的驱动Bug很多,所以要避免麻烦的话,请使用简单的shader,而不要指定精度,除非你真的需要。

运算符(Operators)

Godot 着色器语言支持和GLSL ES 3.0一样的运算符集。下面是按照优先级(precedence)排序的运算符列表:

优先级 类目 运算符
1 (最高) 括号(parenthetical grouping) ()
2 一元运算符(unary) +, -, !, ~
3 乘法类(multiplicative) /, *, %
4 加法类(additive) +, -
5 按位移动(bit-wise shift) <<, >>
6 逻辑(relational) <, >, <=, >=`
7 相等(equality) ==, !=
8 按位与(bit-wise and) &
9 逻辑异或(bit-wise exclusive or) ^
10 按位或(bit-wise inclusive or) |
11 逻辑与(logical and) &&
12 (最低) 逻辑或(logical inclusive or) ||
分支控制(Flow control)

Godot着色器语言支持大多数常见的过程控制形式:

// if and else
if (cond) {
​
} else {
​
}
​
// for loops
for (int i = 0; i < 10; i++) {
​
}
​
// while
while (true) {
​
}

注意:在现代GPU中,死循环是可以存在的,并且它可能会冻结你的程序(包括编辑器)。Godot无法保护你远离死循环,所以请小心不要犯这种错误。

丢弃(Discarding)

在片元(fragment)和光处理函数中可以使用discard关键字。它将意味着片元被弃用。

函数(Functions)

在Godot着色器中可以使用如下语法定义函数:

ret_type func_name(args) {return ret_type; // if returning a value
}
​
// 来个更具体的例子:
​
int sum2(int a, int b) {return a + b;
}

注意:当一个函数B要调用函数A时,函数A一定在函数B之前。

函数的参数可以有特殊限定符(qualifier):

in : 只读

out:只写

inout:引用型

例如:

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

从顶点处理器函数(vertex processor function)向片元处理器函数(fragment processor function)传递参数时,会用到变元。在顶点处理器中每一个初始顶点(primitive vertex)会被设置变元。在片元处理器中,变元的值是对每一个像素的插值()interpolated。

shader_type spatial;
​
varying vec3 some_color;
void vertex() {some_color = NORMAL; // Make the normal the color.
}
​
void fragment() {ALBEDO = some_color;
}
插值限定符(Interpolation qualifiers)

某些值会在着色器管线(shading pipeline)中被插值。你可以使用插值限定符来修正这些插值是如何进行的。

shader_type spatial;
​
varying flat vec3 our_color;
​
void vertex() {our_color = COLOR.rgb;
}
​
void fragment() {ALBEDO = our_color;
}

有两种可用的插值限定符:

限定符 描述
flat 不插值
smooth 以透视修正(perspective-correct)的方式插值。 此值为默认值。
Uniform变量

(程序)向着色器传递值是可以实现的。这些值被称为uniform变量,它们对于整个着色器来说是全局的(global)。当一个着色器被指派给一个材质后,uniform变量会作为可编辑参数显示在材质的编辑器上。注意:uniform变量无法由内而外写入

shader_type spatial;
​
uniform float some_value;

你可以在编辑器中的材质栏中设置uniform变量,也可以通过GDScript

material.set_shader_param("some_value", some_value)

注意:set_shader_param的第一个参数是shader中uniform变量的变量名,它必须和shader中的uniform名字严格匹配,否则将不会被识别。

除void以外的任何GLSL类型都可以作为一个uniform变量。特别地,Godot提供了一种可选的着色器提示(shader hint),来使编译器理解这个uniform变量的用途。

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

着色器提示的列表如下:

类型 提示 Description
vec4 hint_color 作为颜色使用
int, float hint_range(min,max [,step] ) 作为范围使用
sampler2D hint_albedo 作为慢反射颜色使用,默认为白色
sampler2D hint_black_albedo 作为慢反射颜色使用,默认为黑色
sampler2D hint_normal 作为法线贴图使用
sampler2D hint_white 作为值使用,默认为白色
sampler2D hint_black 作为值使用,默认为黑色
sampler2D hint_aniso 作为流向图(flowmap)使用,默认向右

GDScript使用不同的数据类型体系,所以当从GDScript传递变量到shader时,Godot会自动转换类型。下面是二者的类型对照表:

GDScript type GLSL type
bool bool
int int
float float
Vector2 vec2
Vector3 vec3
Color vec4
Transform mat4
Transform2D mat4

**注意:**在GDScript设置uniform变量的时候,如果二者的类型不匹配,godot不会抛出任何异常。只是你的着色器会产生一些未预期的行为。

因为Godot的3D 引擎使用的是线性色彩空间(linear color space),所以有必要知道用来充当颜色的纹理(比如慢反射色),需要被设置为sRGB->linear。

Uniform变量也可以指定默认值:

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

译者注:以下部分内容涉及大量数学专业名词,能力有限不确保翻译准确,建议大家以英文版为准

内置函数(Built-in functions)

Godot提供大量的内置函数,这些函数的形式和GLSL ES 3.0一致。函数的参数及返回值可以是标量也可以是向量。

注意:在文档Differences between GLES2 and GLES3 doc 可以查到GLES2所不支持的函数列表。

函数 描述
vec_type radians ( vec_type ) 将角度转为弧度
vec_type degrees ( vec_type ) 将弧度转为角度
vec_type sin ( vec_type ) 正弦
vec_type cos ( vec_type ) 余弦
vec_type tan ( vec_type ) 正切
vec_type asin ( vec_type ) 反正弦
vec_type acos ( vec_type ) 反余
vec_type atan ( vec_type ) 反正切
vec_type atan ( vec_type x, vec_type y ) Arc-Tangent to convert vector to angle
vec_type sinh ( vec_type ) 双曲正弦
vec_type cosh ( vec_type ) 双曲余弦
vec_type tanh ( vec_type ) 双曲正切
vec_type asinh ( vec_type ) 反双曲正弦
vec_type acosh ( vec_type ) 反双曲余弦
vec_type atanh ( vec_type ) 反双曲正切
vec_type pow ( vec_type, vec_type ) 幂运算
vec_type exp ( vec_type ) e基指数
vec_type exp2 ( vec_type ) 2基指数
vec_type log ( vec_type ) e基(自然)对数
vec_type log2 ( vec_type ) 2基对数
vec_type sqrt ( vec_type ) 平方根
vec_type inversesqrt ( vec_type ) 平方根倒数
vec_type abs ( vec_type ) 绝对值
vec_int_type abs ( vec_int_type ) 绝对值
vec_type sign ( vec_type ) Sign
vec_int_type sign ( vec_int_type ) Sign
vec_type floor ( vec_type ) 向下取整
vec_type round ( vec_type ) 四舍五入
vec_type roundEven ( vec_type ) 四舍五入到临近偶数(Round nearest even)
vec_type trunc ( vec_type ) 截断
vec_type ceil ( vec_type ) 向上取整
vec_type fract ( vec_type ) 取小数部分
vec_type mod ( vec_type, vec_type ) 取余
vec_type mod ( vec_type, float ) 取余
vec_type modf ( vec_type x, out vec_type i ) Fractional of x, with i has integer part
vec_scalar_type min ( vec_scalar_type a, vec_scalar_type b ) 最小值
vec_scalar_type max ( vec_scalar_type a, vec_scalar_type b ) 最大值
vec_scalar_type clamp ( vec_scalar_type value, vec_scalar_type min, vec_scalar_type max ) 约束至最大值与最小值之间
vec_type mix ( vec_type a, vec_type b, float c ) 线性插值 (Scalar Coef.)
vec_type mix ( vec_type a, vec_type b, vec_type c ) 线性插值 (Vector Coef.)
vec_type mix ( vec_type a, vec_type b, bool c ) 线性插值 (Bool Selection)
vec_type mix ( vec_type a, vec_type b, vec_bool_type c ) 线性插值 (Bool-Vector Selection)
vec_type step ( vec_type a, vec_type b ) b[i] < a[i] ? 0.0 : 1.0
vec_type step ( float a, vec_type b ) b[i] < a ? 0.0 : 1.0
vec_type smoothstep ( vec_type a, vec_type b, vec_type c ) 艾米插值
vec_type smoothstep ( float a, float b, vec_type c ) 艾米插值
vec_bool_type isnan ( vec_type ) 当标量或者向量分量为nan时,返回true
vec_bool_type isinf ( vec_type ) 当标量或者向量分量为inf时,返回true
vec_int_type floatBitsToInt ( vec_type ) 将Float按字节复制成Int, 不做类型转换
vec_uint_type floatBitsToUint ( vec_type ) 将Float按字节复制成UInt, 不做类型转换
vec_type intBitsToFloat ( vec_int_type ) 将Int按字节复制成Float, 不做类型转换
vec_type uintBitsToFloat ( vec_uint_type ) 将UInt按字节复制成Float, 不做类型转换
float length ( vec_type ) 向量长度
float distance ( vec_type, vec_type ) 向量间距离
float dot ( vec_type, vec_type ) 点积(Dot Product)
vec3 cross ( vec3, vec3 ) 叉积(Cross Product)
vec_type normalize ( vec_type ) 标准化成UInt长度
vec3 reflect ( vec3 I, vec3 N ) 反射
vec3 refract ( vec3 I, vec3 N, float eta ) 折射
vec_type faceforward ( vec_type N, vec_type I, vec_type Nref ) If dot(Nref, I) < 0, return N, otherwise –N
mat_type matrixCompMult ( mat_type, mat_type ) Matrix Component Multiplication
mat_type outerProduct ( vec_type, vec_type ) 矩阵外积
mat_type transpose ( mat_type ) 转置矩阵
float determinant ( mat_type ) 矩阵行列式
mat_type inverse ( mat_type ) 逆矩阵
vec_bool_type lessThan ( vec_scalar_type, vec_scalar_type ) Bool vector cmp on < int/uint/float vectors
vec_bool_type greaterThan ( vec_scalar_type, vec_scalar_type ) Bool vector cmp on > int/uint/float vectors
vec_bool_type lessThanEqual ( vec_scalar_type, vec_scalar_type ) Bool vector cmp on <= int/uint/float vectors
vec_bool_type greaterThanEqual ( vec_scalar_type, vec_scalar_type ) Bool vector cmp on >= int/uint/float vectors
vec_bool_type equal ( vec_scalar_type, vec_scalar_type ) Bool vector cmp on == int/uint/float vectors
vec_bool_type notEqual ( vec_scalar_type, vec_scalar_type ) Bool vector cmp on != int/uint/float vectors
bool any ( vec_bool_type ) 有任何一个分量为true,则值为true
bool all ( vec_bool_type ) 所有分量均为true
bool not ( vec_bool_type ) 所有分量均为false
ivec2 textureSize ( sampler2D_type s, int lod ) 获取纹理大小
ivec2 textureSize ( samplerCube s, int lod ) 获取立方映射(cubemap)的大小
vec4_type texture ( sampler2D_type s, vec2 uv [, float bias] ) Perform a 2D texture read
vec4_type texture ( samplerCube s, vec3 uv [, float bias] ) Perform a Cube texture read
vec4_type textureProj ( sampler2D_type s, vec3 uv [, float bias] ) Perform a texture read with projection
vec4_type textureProj ( sampler2D_type s, vec4 uv [, float bias] ) Perform a texture read with projection
vec4_type textureLod ( sampler2D_type s, vec2 uv, float lod ) Perform a 2D texture read at custom mipmap
vec4_type textureLod ( samplerCube s, vec3 uv, float lod ) Perform a Cube texture read at custom mipmap
vec4_type textureProjLod ( sampler2D_type s, vec3 uv, float lod ) Perform a texture read with projection/lod
vec4_type textureProjLod ( sampler2D_type s, vec4 uv, float lod ) Perform a texture read with projection/lod
vec4_type texelFetch ( sampler2D_type s, ivec2 uv, int lod ) 用整数坐标获取一个纹理影像元件(texel)
vec_type dFdx ( vec_type ) 用局部差分对x求导
vec_type dFdy ( vec_type ) 用局部差分对y求导
vec_type fwidth ( vec_type ) x和y的绝对导数之和

Godot着色器语言相关推荐

  1. Godot着色器基础

    原文地址:Docs>Shading>Shading reference>Shaders 简介 着色器是一种运行在GPU上的独特程序.它们会决定如何拾取网格模型的数据(诸如顶点位置,颜 ...

  2. OpenGL ES着色器语言之变量和数据类型

    所有变量和函数在使用前必须声明.变量和函数名是标识符. 没有默认类型,所有变量和函数声明必须包含一个声明类型以及可选的修饰符.变量在声明的时候首先要标明类型,后边可以跟多个变量,之间用逗号隔开.很多情 ...

  3. OpenGL ES着色器语言之语句和结构体(官方文档第六章)内建变量(官方文档第七、八章)...

    OpenGL ES着色器语言之语句和结构体(官方文档第六章) OpenGL ES着色器语言的程序块基本构成如下: 语句和声明 函数定义 选择(if-else) 迭代(for, while, do-wh ...

  4. OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章)

    OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章) 4.5精度和精度修饰符 4.5.1范围和精度 用于存储和展示浮点数.整数变量的范围和精度依赖于数值的源(varying,unifo ...

  5. 可编程渲染管线与着色器语言

    Programming pipeline & shading language 大家好,今天想给大家介绍一下可编程渲染管线和着色器语言的相关基础知识,使想上手SHADER编程的童鞋们可以快速揭 ...

  6. GLSL三种基本类型(着色器语言三种变量)

    着色器语言和C语言一样,通过一个表示特定数据类型的关键词声明一个变量,比如int num;通过int关键字声明一个整数型变量num,不过着色器语言还提供了三个关键字attribute.uniform和 ...

  7. OpenGL ES着色器语言(GLSL ES)规范 ——下篇

    文章目录 前言 分支和循环 if.if-else for continue.break.discard 着色器内置变量 函数 函数定义 规范声明 webgl内置函数 存储限定字 const attri ...

  8. OpenGLES2.0着色器语言glsl

    OpenGLES2.0中是强制使用可编程的渲染管线的,使用的是glsl着色器语言,因为着色器语言是使用的GPU,即图形处理单元,而不是CPU,这样可以使CPU从繁重的几何计算和像素的处理中解脱出来了. ...

  9. OpenGL着色器语言GLSL语法总结

    GLSL语法与C语言类似. 1.变量类型 基础类型:bool,int,uint,float,double与C语言的类型类似. 向量类型:vecN,bvecN,ivecN,uvecN,dvecN,N表示 ...

最新文章

  1. Python+opencv 机器视觉 - 基于霍夫圈变换算法检测图像中的圆形实例演示
  2. AtCoder Beginner Contest 055题解
  3. 人工智能之知识图谱-学习笔记
  4. tomcat如何部署.net程序_.NET 程序员如何学习Vue
  5. mfc程序转化为qt_小峰的QT学习笔记
  6. supersocket新的配置属性 textEncoding
  7. gogs 默认的管理员账号密码是什么
  8. 聚类分析 距离 matlab,matlab聚类分析_matlab
  9. java汇编指令_汇编指令test的用法
  10. MacOS罗技鼠标定义的功能键经常失灵
  11. 软件测试人员必备的7种思维方式
  12. 在Novell NetWare中支持IP
  13. 汤姆猫代码python_IOS 汤姆猫核心代码
  14. conda 使用清华大学开源软件镜像
  15. alert弹出[object Object]解决方法
  16. TensorFlow2 -官方教程 :保存和恢复模型
  17. android 世界各国英文简写代码 资源文件
  18. 湖北智禾网店指导:入门卖家一定要了解的淘宝宝贝发布规则及注意事项。
  19. Git学习-Git时光机之版本回退(二)
  20. 程序设计入门——C语言

热门文章

  1. 学计算机高考英语听力考试时间,北京:2020年高考英语听力机考问答
  2. JDK动态代理过程中报错interface ** is not visible from class loader
  3. 直接让Windows注销的脚本
  4. 外汇天眼:开仓、平仓、持仓、锁仓是什么意思?
  5. 二元函数最大最小值定理证明_求函数最小最大值定理的证明
  6. 汇智动力学员最新就业喜报,最高薪资16K!
  7. 《算法导论》第十二章——二叉搜索树
  8. 谷歌Imagen,人工智能对语言更加深入理解
  9. Kettle构建Hadoop ETL实践(八-2):维度表技术
  10. 大数据人才如此稀缺,学什么专业才能从事大数据?