将 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及以上版本)中, 变量是通过 inout 关键字来定义的. 一个从顶点着色器出来的变量在顶点着色器中用 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 中,你可以在定义变量时将精度限定词 lowpmediumphighp 放在类型前,根据需要设置单个变量的精度。更多信息请参见着色器语言参考。

Shadertoy

Shadertoy 是一个网站, 它使编写片段着色器和创建 纯正的魔法 变得容易.

Shadertoy 并没有让用户完全控制着色器。它处理所有的输入和 uniform,只让用户编写片段着色器。

类型

Shadertoy使用的是webgl规范, 所以它运行的GLSL版本略有不同. 然而, 它仍然有常规的类型, 包括常量和宏.

mainImage

Shadertoy着色器的主要入口点是 mainImage 函数. mainImage 有两个参数, fragColorfragCoord, 分别对应Godot中的 COLORFRAGCOORD . 这些参数在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.