将 GLSL 转换为 Godot 着色器
本文档解释了Godot的着色语言和GLSL之间的区别, 并提供了有关如何将着色器从其他来源(如Shadertoy和The Book of Shaders)迁移到Godot着色器的实用建议.
关于Godot的着色语言的详细信息, 请参考 Shading Language .
GLSL
Godot使用基于GLSL的着色语言, 增加了一些生活质量特征. 因此,GLSL中提供的大多数功能都可以使用Godot的着色语言.
着色器程序
在GLSL中, 每个着色器使用一个单独的程序. 你有一个用于顶点着色器的程序和一个用于片段着色器的程序. 在Godot中, 你有一个包含 vertex
和/或 fragment
函数的单一着色器. 如果你只选择写一个,Godot会提供另一个.
Godot允许通过在一个文件中定义片段和顶点着色器来共享uniform的变量和函数. 在GLSL中, 顶点和片段程序不能共享变量, 除非是使用varyings的时候.
顶点属性
在GLSL中, 你可以使用属性来传递每个顶点的信息, 并且可以灵活地传递你想要的信息, 或多或少. 在Godot中, 你有一系列的输入属性, 包括 VERTEX
(坐标), COLOR
, UV
, UV2
, NORMAL
. 完整的列表, 请参见 Shading language reference .
gl_Position
gl_Position
接收在顶点着色器中指定的顶点的最终坐标. 它是由用户在裁剪空间中指定的. 通常, 在GLSL中, 模型空间的顶点位置是通过一个名为 position
的顶点属性来传递的, 你可以手动处理从模型空间到裁剪空间的转换.
在Godot中, VERTEX
指定了 vertex
函数开始时在模型空间的顶点位置. 在用户定义的 vertex
函数运行后,Godot也会处理最终转换到裁剪空间的过程. 如果你想跳过从模型空间到视图空间的转换, 你可以将 render_mode
设置为 skip_vertex_transform
. 如果你想跳过所有的转换, 将 render_mode
设置为 skip_vertex_transform
并将 PROJECTION_MATRIX
设置为 mat4(1.0)
, 以便使从视图空间到裁剪空间的最终转换失效.
Varying
varyings是一种变量, 可以从顶点着色器传递到片段着色器. 在现代GLSL(3.0及以上版本)中, 变量是通过 in
和 out
关键字来定义的. 一个从顶点着色器出来的变量在顶点着色器中用 out
定义, 在片段着色器中用 in
定义.
主要
在GLSL中, 每个着色器程序看起来都像是一个独立的C风格程序. 因此, 主要入口点是 main
. 如果要复制顶点着色器, 请将 main
重命名为 vertex
, 如果要复制片段着色器, 请将 main
重命名为 fragment
.
常量
全局数组常量在Godot 3.x中不被支持. 你可以通过使用一个初始化为该值的uniform来伪造功能, 但你不会从使用常量所带来的速度提升中获益.
宏
为了与C的相似性,GLSL允许您使用宏. 通常 #define
用于定义常量或小段函数. 没有直接的方法将定义翻译成Godot的着色语言. 如果它是一个已定义的函数, 则用函数替换, 如果它是常量, 则用uniform替换. 对于其他宏( #if
, #ifdef
等), 没有等价物, 因为它们在编译的预处理阶段运行.
变量
GLSL 有许多内置的硬编码变量。这些变量不是 uniform,因此它们不能从主程序中编辑。
变量 | 类型 | 等价物 | 描述 |
---|---|---|---|
gl_FragColor | out vec4 | COLOR | 每个像素的输出颜色. |
gl_FragCoord | vec4 | FRAGCOORD | 用于全屏四边形. 对于较小的四边形, 使用UV. |
gl_Position | vec4 | VERTEX | 顶点的位置, 从顶点着色器输出. |
gl_PointSize | 浮点数 | POINT_SIZE | Point原语的大小. |
gl_PointCoord | vec2 | POINT_COORD | 绘制Point基元时在点上的位置. |
gl_FrontFacing | bool | FRONT_FACING | 如果原始的正面, 则为真. |
坐标
GLSL中的 gl_FragCoord
和Godot着色语言中的 FRAGCOORD
使用相同的坐标系. 如果在Godot中使用UV, 则y坐标将颠倒翻转.
精度
在GLSL中,你可以用 precision
关键字在着色器的顶部定义一个给定类型的精度(float 或 int)。在 Godot 中,你可以在定义变量时将精度限定词 lowp
、mediump
、highp
放在类型前,根据需要设置单个变量的精度。更多信息请参见着色器语言参考。
Shadertoy
Shadertoy 是一个网站, 它使编写片段着色器和创建 纯正的魔法 变得容易.
Shadertoy 并没有让用户完全控制着色器。它处理所有的输入和 uniform,只让用户编写片段着色器。
类型
Shadertoy使用的是webgl规范, 所以它运行的GLSL版本略有不同. 然而, 它仍然有常规的类型, 包括常量和宏.
mainImage
Shadertoy着色器的主要入口点是 mainImage
函数. mainImage
有两个参数, fragColor
和 fragCoord
, 分别对应Godot中的 COLOR
和 FRAGCOORD
. 这些参数在Godot中是自动处理的, 所以你不需要自己把它们作为参数. 移植到Godot时, mainImage
函数中的任何内容都应复制到 fragment
函数中.
变量
为了让编写片段着色器变得简单明了,Shadertoy为你处理了从主程序传递到片段着色器中的许多有用信息. 其中有一些在Godot中没有对应的信息, 因为Godot选择不在默认情况下提供这些信息. 这没关系, 因为Godot让你有能力制作自己的 uniform。对于那些等价物被列为 “Provide with Uniform” 的变量, 用户有责任自己创建该uniform . 该描述给了读者一个提示, 告诉他们可以传入什么作为替代物.
变量 | 类型 | 等价物 | 描述 |
---|---|---|---|
fragColor | out vec4 | COLOR | 每个像素的输出颜色. |
fragCoord | vec2 | FRAGCOORD.xy | 用于全屏四边形. 对于较小的四边形, 使用UV. |
iResolution | vec3 | 1.0 / SCREEN_PIXEL_SIZE | 也可以手动传递. |
iTime | 浮点数 | TIME | 着色器启动后的时间. |
iTimeDelta | 浮点数 | 提供Uniform | 渲染前一帧的时间. |
iFrame | 浮点数 | 提供Uniform | 帧号. |
iChannelTime[4] | 浮点数 | 提供Uniform | 自该特定纹理开始的时间。 |
iMouse | vec4 | 提供Uniform | 鼠标在像素坐标中的位置. |
iDate | vec4 | 提供Uniform | 当前日期, 以秒为单位表示. |
iChannelResolution[4] | vec3 | 1.0 / TEXTURE_PIXEL_SIZE | 特殊纹理的分辨率. |
iChanneli | Sampler2D | TEXTURE | Godot只提供一个内置;用户可以制作更多. |
坐标
fragCoord
的行为与 gl_FragCoord
相同 GLSL 和Godot中的 FRAGCOORD
.
着色之书
与 Shadertoy 类似,The Book of Shaders 提供了在网络浏览器中访问片段着色器的机会,用户可以与之互动,但只限于编写片段着色器代码,其中有一组传入的 uniform 列表,不能添加额外的 uniform。
有关将着色器移植到各种框架的进一步帮助,The Book of Shaders在各种框架中运行着色器时提供了一个 page .
类型
The Book of Shaders使用webgl规范, 因此它运行的GLSL略有不同. 但是, 它仍然具有常规类型, 包括常量和宏.
主要
Book of Shaders片段着色器的入口点是 main
, 就像在GLSL中一样. 使用着色器 main
函数编写的所有内容都应该复制到Godot的 fragment
函数中.
变量
着色书比Shadertoy更接近普通GLSL. 它也比Shadertoy实施更少的制服.
变量 | 类型 | 等价物 | 描述 |
---|---|---|---|
gl_FragColor | out vec4 | COLOR | 每个像素的输出颜色. |
gl_FragCoord | vec4 | FRAGCOORD | 用于全屏四边形. 对于较小的四边形, 使用UV. |
u_resolution | vec2 | 1.0 / SCREEN_PIXEL_SIZE | 也可以手动传递. |
u_time | 浮点数 | TIME | 着色器启动后的时间. |
u_mouse | vec2 | 提供Uniform | 鼠标在像素坐标中的位置. |
坐标
Shaders使用相同的坐标系 GLSL.