Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

著色語言

前言

Godot 使用類似於 GLSL ES 3.0 的著色語言。支援大多數資料型別和函式,並且可能會隨著時間的推移新增剩餘的幾種型別和函式。

如果您已經熟悉 GLSL,:ref:`Godot 著色器遷移指南 <doc_converting_glsl_to_godot_shaders>`是一個説明您從常規 GLSL 轉換到 Godot 著色語言的資源。

資料型別

支援大多數GLSL ES 3.0資料型別:

型別

說明

void

Void資料型別, 只對不返回任何內容的函式有用.

bool

布林資料型別,只能包含 truefalse

bvec2

布林值的兩個分量向量.

bvec3

布林值的三分量向量.

bvec4

布林值的四分量向量.

int

帶正負的符號標量整數.

ivec2

有符號整數的雙分量向量.

ivec3

有符號整數的三分量向量.

ivec4

有符號整數的四分量向量.

uint

無符號標量整數, 不能包含負數.

uvec2

不帶正負號的整數的兩分量向量.

uvec3

不帶正負號的整數的三分量向量.

uvec4

不帶正負號的整數的四分量向量.

float

浮點標量.

vec2

浮點值的兩分量向量.

vec3

浮點值的三分量向量.

vec4

浮點值的四分量向量.

mat2

2x2矩陣, 按主要順序排列.

mat3

3x3矩陣, 在列的主要順序.

mat4

4x4矩陣, 按主要順序排列.

sampler2D

用於綁定2D紋理的取樣器型別, 以浮點形式讀取.

isampler2D

用於綁定2D紋理的取樣器型別, 它們被讀取為有符號整數.

usampler2D

用於綁定2D紋理的取樣器型別, 讀取為不帶正負號的整數.

sampler2DArray

用於綁定2D紋理陣列的取樣器型別, 以浮點數形式讀取.

isampler2DArray

用於綁定2D紋理陣列的取樣器型別, 以有符號整數形式讀取.

usampler2DArray

用於綁定2D紋理陣列的取樣器型別, 以不帶正負號的整數形式讀取.

sampler3D

用於綁定3D紋理的取樣器型別, 以浮點形式讀取.

isampler3D

用於綁定3D紋理的取樣器型別, 以有符號整數形式讀取.

usampler3D

用於綁定3D紋理的取樣器型別, 以不帶正負號的整數形式讀取.

samplerCube

用於綁定立方體貼圖的取樣器型別,作為 float 讀取。

samplerCubeArray

用於綁定立方體貼圖陣列的取樣器型別,作為 float 讀取。

型別轉換

就像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[column][row] 索引語法來存取每個標量,或者 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(MODEL_MATRIX);
mat4 m4 = mat4(basis);
mat2 m2 = mat2(m4);

混寫Swizzling

只要結果是另一種向量型別(或標量), 就可以以任何順序獲得元件的組合. 這一點展示起來比解釋起來容易:

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; // "b" will be vec3(2.0, 1.0, 0.0).
vec3 b = a.xyz; // Also rgba, xyzw are equivalent.
vec3 b = a.stp; // And stpq (for texture coordinates).
float c = b.w; // Invalid, because "w" is not present in vec3 b.
vec3 c = b.xrt; // Invalid, mixing different styles is forbidden.
b.rrr = a.rgb; // Invalid, assignment with duplication.
b.bgr = a.rgb; // Valid assignment. "b"'s "blue" component will be "a"'s "red" and vice versa.

精度

可以為資料型別新增精度修飾符;將它們用於 uniform、變數、參數、varying:

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-style的語法. [const] + [precision] + typename + identifier + [array size].

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

它們可以在開始時進行初始化, 例如:

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

int int_arr[3] = int[] (2, 1, 0); // second constructor

vec2 vec2_arr[3] = { vec2(1.0, 1.0), vec2(0.5, 0.5), vec2(0.0, 0.0) }; // third constructor

bool bool_arr[] = { true, true, false }; // fourth constructor - size is defined automatically from the element 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和陣列的長度之間. 總是仔細測試和檢查你的程式碼. 如果你傳遞了一個常數運算式或一個簡單的數字, 編輯器會檢查它的邊界以防止這種當機.

本地坐標

您可以在全域空間宣告陣列,如下所示:

shader_type spatial;

const lowp vec3 v[1] = lowp vec3[1] ( vec3(0, 0, 1) );

void fragment() {
  ALBEDO = v[0];
}

備註

全域陣列必須宣告為全域常數,否則可以像局部陣列一樣宣告。

常數

在變數宣告前使用 const 關鍵字, 可以使該變數成為不可變的, 這意味著它不能被修改. 所有的基本型別, 除了取樣器, 都可以被宣告為常數. 存取和使用常數值的速度比使用uniform的速度略快. 常數必須在其宣告時被初始化.

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

常數可以在全域(在任何函式之外)或局部(在一個函式之內)進行宣告. 當你想在整個著色器中存取一個不需要修改的值時, 全域常數很有用. 像uniform一樣, 全域常數在所有著色器階段之間共用, 但它們在著色器之外是不可存取的.

shader_type spatial;

const float PI = 3.14159265358979323846;

float 型別的常數必須使用小數部分後的 . 符號或科學記數法初始化。也支援可選的“f”後綴。

float a = 1.0;
float b = 1.0f; // same, using suffix for clarity
float c = 1e-1; // gives 0.1 by using the scientific notation

「uint」(無符號整數)型別的常數必須具有「u」後綴,以將其與有符號整數區分開來。或者,可以透過使用「uint(x)」內建轉換函式來完成。

uint a = 1u;
uint b = uint(1);

建構子

結構體是一種複合型別,可以對著色器程式碼進行更好的抽象。你可以像這樣在全域作用域進行宣告:

struct PointLight {
    vec3 position;
    vec3 color;
    float intensity;
};

宣告後可以這樣進行產生實體和初始化:

void fragment()
{
    PointLight light;
    light.position = vec3(0.0);
    light.color = vec3(1.0, 0.0, 0.0);
    light.intensity = 0.5;
}

或者使用結構體的建構子達到同樣的效果:

PointLight light = PointLight(vec3(0.0), vec3(1.0, 0.0, 0.0), 0.5);

結構體中可以包含其他結構體或者陣列,你還可以把它們作為全域常數產生實體:

shader_type spatial;

...

struct Scene {
    PointLight lights[2];
};

const Scene scene = Scene(PointLight[2](PointLight(vec3(0.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0), 1.0), PointLight(vec3(0.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0), 1.0)));

void fragment()
{
    ALBEDO = scene.lights[0].color;
}

你還可以把它們傳遞給函式:

shader_type canvas_item;

...

Scene construct_scene(PointLight light1, PointLight light2) {
    return Scene({light1, light2});
}

void fragment()
{
    COLOR.rgb = construct_scene(PointLight(vec3(0.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0), 1.0), PointLight(vec3(0.0, 0.0, 0.0), vec3(1.0, 0.0, 1.0), 1.0)).lights[0].color;
}

運算子

Godot 著色器語言支援與GLSL ES 3.0相同的運算子集. 下面是它們的優先順序列表:

優先順序

類別

運算子

1(最高)

括弧群組

()

2

單目

+, -, !, ~

3

乘除法

/, *, %

4

加減法

+, -

5

移位

<<, >>

6

關係比較

<, >, <=, >=

7

相等比較

==, !=

8

按位與

&

9

按位異或

^

10

按位或

|

11

邏輯與

&&

12(最低)

邏輯或

||

流控制

Godot 著色器語言支援最常見的控制流型別:

// `if` and `else`.
if (cond) {

} else {

}

// Ternary operator.
// This is an expression that behaves like `if`/`else` and returns the value.
// If `cond` evaluates to `true`, `result` will be `9`.
// Otherwise, `result` will be `5`.
int result = cond ? 9 : 5;

// `switch`.
switch (i) { // `i` should be a signed integer expression.
    case -1:
        break;
    case 0:
        return; // `break` or `return` to avoid running the next `case`.
    case 1: // Fallthrough (no `break` or `return`): will run the next `case`.
    case 2:
        break;
    //...
    default: // Only run if no `case` above matches. Optional.
        break;
}

// `for` loop. Best used when the number of elements to iterate on
// is known in advance.
for (int i = 0; i < 10; i++) {

}

// `while` loop. Best used when the number of elements to iterate on
// is not known in advance.
while (cond) {

}

// `do while`. Like `while`, but always runs at least once even if `cond`
// never evaluates to `true`.
do {

} while (cond);

請記住, 在現代GPU中, 無限迴圈可能存在, 並可能凍結你的應用程式(包括編輯器).Godot不能保護你不受影響, 所以要小心不要犯這個錯誤!

此外,在將浮點值與數字進行比較時,請確保將它們與*範圍*而不是精確數字進行比較。

像「if (value == 0.3)」這樣的比較可能不會計算為「true」。浮點數學通常是近似的並且可能超出預期。根據硬體的不同,它的行為也可能有所不同。

不要 寫成「of the X」:

float value = 0.1 + 0.2;

// May not evaluate to `true`!
if (value == 0.3) {
    // ...
}

相反,始終與 epsilon 值執行範圍比較。浮點數越大(浮點數精度越低),epsilon 值應該越大。

const float EPSILON = 0.0001;
if (value >= 0.3 - EPSILON && value <= 0.3 + EPSILON) {
    // ...
}

請參閱 floating-point-gui.de 以了解更多資訊。

丟棄

片段和燈光功能可以使用 discard 關鍵字. 如果使用, 則丟棄該片段並且不寫入任何內容.

請注意,「丟棄」在使用時會產生效能成本,因為它將阻止深度預通道在使用著色器的任何表面上發揮作用。此外,丟棄的像素仍然需要在頂點著色器中渲染,這意味著與首先不渲染任何物件相比,在所有像素上使用「丟棄」的著色器的渲染成本仍然更高。

函式

可以在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 : 表示該參數只用於寫入.

  • inout : 表示該參數以引用傳遞.

  • const:表示參數是常數,不能更改,可以與 in 限定符結合使用。

範例:

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

備註

與 GLSL 不同,Godot 的著色器語言**不**支援函式重載。這意味著不能使用不同的參數型別或參數數量來多次定義函式。作為解決方法,請為接受不同數量的參數或不同型別的參數的函式使用不同的名稱。

Varying

要從頂點處理器函式往片段(或者燈光)處理器函式裡發送資料,可以使用 varying*頂點處理器*中的每一個像素頂點都是 varying 的,會為*片段處理器*中的每一個像素做插值。

shader_type spatial;

varying vec3 some_color;

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

void fragment() {
    ALBEDO = some_color;
}

void light() {
    DIFFUSE_LIGHT = some_color * 100; // optionally
}

Varying 也可以是陣列:

shader_type spatial;

varying float var_arr[3];

void vertex() {
    var_arr[0] = 1.0;
    var_arr[1] = 0.0;
}

void fragment() {
    ALBEDO = vec3(var_arr[0], var_arr[1], var_arr[2]); // red color
}

也可以使用 varying 關鍵字將資料從*片段*處理器送往*燈光*處理器。在 fragment 函式中賦值,然後在 light 函式中使用即可。

shader_type spatial;

varying vec3 some_light;

void fragment() {
    some_light = ALBEDO * 100.0; // Make a shining light.
}

void light() {
    DIFFUSE_LIGHT = some_light;
}

注意,在自訂函式或*燈光處理器*中是不能為 varying 賦值的:

shader_type spatial;

varying float test;

void foo() {
    test = 0.0; // Error.
}

void vertex() {
    test = 0.0;
}

void light() {
    test = 0.0; // Error too.
}

加入這一限制的目的是為了防止在初始化前進行錯誤的使用。

插值限定詞

在著色管線期間內插某些值. 您可以使用 插值限定詞 修改這些插值的完成方式.

shader_type spatial;

varying flat vec3 our_color;

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

void fragment() {
    ALBEDO = our_color;
}

有兩種可能的插值限定詞:

修飾符

說明

flat

該值未插值.

smooth

該值以透視正確的方式進行插值. 這是預設值.

Uniform

可以將值傳遞給著色器。這些值對整個著色器來說是全域的,被稱為 uniform。當一個著色器後來被分配給一個材質時,uniform 將作為可編輯的參數出現在其中。uniform 不能從著色器內部寫入。

shader_type spatial;

uniform float some_value;

uniform vec3 colors[3];

你可以在編輯器中設定材質中的 uniform。或者你可以通過 GDScript 來設定它們:

material.set_shader_parameter("some_value", some_value)

material.set_shader_parameter("colors", [Vector3(1, 0, 0), Vector3(0, 1, 0), Vector3(0, 0, 1)])

備註

set_shader_param 的第一個參數是著色器中的 uniform 名稱。它必須與著色器中的 uniform 名稱*完全*一致,否則將無法被識別。

除了 void 之外,任何 GLSL 型別都可以成為 uniform。此外,Godot 還提供了可選的著色器提示,以使編譯器瞭解 uniform 是用來幹什麼的,以及編輯器應該讓使用者進行何種修改。

shader_type spatial;

uniform vec4 color : source_color;
uniform float amount : hint_range(0, 1);
uniform vec4 other_color : source_color = vec4(1.0); // Default values go after the hint.
uniform sampler2D image : source_color;

It's important to understand that textures that are supplied as color require hints for proper sRGB -> linear conversion (i.e. source_color), as Godot's 3D engine renders in linear color space. If this is not done, the texture will appear washed out.

備註

The 2D renderer also renders in linear color space if the Rendering > Viewport > HDR 2D project setting is enabled, so source_color must also be used in canvas_item shaders. If 2D HDR is disabled, source_color will keep working correctly in canvas_item shaders, so it's recommend to use it either way.

以下是完整的提示列表:

型別

提示

說明

vec4

source_color

用作顏色。

int、float

hint_range(min,max [,step] )

限制取值範圍(最小值/最大值/步長)。

sampler2D

source_color

用作顏色。

sampler2D

hint_normal

用作法線貼圖。

sampler2D

hint_default_white

用作反照率顏色,預設為白色。

sampler2D

hint_default_black

用作反照率顏色,預設為黑色。

sampler2D

hint_default_transparent

用作反照率顏色,預設為黑色。

sampler2D

異向性

作為 FlowMap,預設為右。

sampler2D

提示_粗糙度[_r、_g、_b、_a、_正常、_灰色]

用於匯入時的粗糙度限制器(嘗試減少鏡面鋸齒)。 「_normal」是一個法線貼圖,用於指導粗糙度限制器,在具有高頻細節的區域中粗糙度會增加。

sampler2D

篩選器[_最近,_線性][_mipmap][_各向異性]

啟用指定的紋理篩選。

sampler2D

repeat[_enable, _disable]

啟用紋理重複。

sampler2D

hint_screen_texture

紋理是螢幕紋理。

sampler2D

hint_depth_texture

紋理是深度紋理。

sampler2D

hint_normal_roughness_texture

Texture is the normal roughness texture (only supported in Forward+).

GDScript 使用的變數型別與 GLSL 不同,所以當把變數從 GDScript 傳遞到著色器時,Godot 會自動轉換型別。以下是相應型別的表格:

GLSL 型別

GDScript 型別

請注意

bool

bool

bvec2

int

按位打包 int,其中位元 0 (LSB) 對應於 x。

例如,(bx, by) 的 bvec2 可以透過以下方式建立:

bvec2_input: int = (int(bx)) | (int(by) << 1)

bvec3

int

按位打包 int,其中位元 0 (LSB) 對應於 x。

bvec4

int

按位打包 int,其中位元 0 (LSB) 對應於 x。

int

int

ivec2

版本

ivec3

版本

ivec4

版本

uint

int

uvec2

版本

uvec3

版本

uvec4

版本

float

float

vec2

Vector2

vec3

Vector3

當使用 Color 時,它將被解釋為 (r, g, b)。

vec4

向量4顏色矩形2平面四元數

當使用 Color 時,它將被解釋為 (r, g, b, a)。

當使用 Rect2 時,它將被解釋為(position.x,position.y,size.x,size.y)。

當使用 Plane 時,它將被解釋為(normal.x、normal.y、normal.z、d)。

mat2

Transform2D

mat3

Basis

mat4

Transform2D

當使用 Transform3D 時,w Vector 設定為恆等式。

sampler2D

紋理貼圖

isampler2D

紋理貼圖

usampler2D

紋理貼圖

sampler2DArray

功能標籤

isampler2DArray

功能標籤

usampler2DArray

功能標籤

sampler3D

紋理貼圖

isampler3D

紋理貼圖

usampler3D

紋理貼圖

samplerCube

Cubemap

samplerCubeArray

CubemapArray

備註

當從 GDScript 中設定著色器 uniform 時要小心,如果型別不配對,不會產生錯誤。你的著色器只會表現出未定義的行為。

Uniform 也可以分配預設值:

shader_type spatial;

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

Note that when adding a default value and a hint, the default value goes after the hint.

如果您需要將多個制服群組到檢查員的特定類別中,您可以使用「group_uniform」關鍵字,例如:

group_uniforms MyGroup;
uniform sampler2D test;

你也可以通過程式碼來修改該屬性:

group_uniforms;

此語法也支援子組(在此之前不強制宣告基組):

group_uniforms MyGroup.MySubgroup;

定數

有時,您會想要同時修改許多不同著色器中的參數。對於常規制服,這需要大量工作,因為需要追蹤所有這些著色器並且需要為每個著色器設定制服。全域制服可讓您建立和更新所有著色器中、每種著色器型別(「canvas_item」、「spatial」、「articles」、「sky」和「fog」)中可用的製服`)。

全域制服對於影響場景中許多物件的環境效果特別有用,例如玩家在附近時樹葉彎曲,或物件隨風移動。

若要建立全域均勻,請開啟 專案設定,然後前往 著色器全域 標籤。指定制服的名稱(區分大小寫)和型別,然後按一下對話方塊右上角的「新增」。然後,您可以透過點擊制服列表中的值來編輯指派給制服的值:

在專案設定的「著色器全域」標籤中新增全域均勻

在專案設定的「著色器全域」標籤中新增全域均勻

建立全域均勻後,您可以在著色器中使用它,如下所示:

shader_type canvas_item;

global uniform vec4 my_color;

void fragment() {
    COLOR = my_color.rgb;
}

請注意,儲存著色器時,全域均勻*必須*存在於專案設定中,否則編譯將失敗。雖然您可以在著色器程式碼中使用「全域均勻 vec4 my_color = ...」 來指派預設值,但它將被忽略,因為無論如何全域均勻必須始終在專案設定中定義。

若要在執行時間變更全域均勻的值,請在腳本中使用 RenderingServer.global_shader_parameter_set <class_RenderingServer_method_global_shader_parameter_set>` 方法:

RenderingServer.global_shader_parameter_set("my_color", Color(0.3, 0.6, 1.0))

可以根據需要多次分配全域均勻值,而不會影響效能,因為設定資料不需要 CPU 和 GPU 之間的同步。

也可以使用自定節點來作為回傳型別:

RenderingServer.global_shader_parameter_add("my_color", RenderingServer.GLOBAL_VAR_TYPE_COLOR, Color(0.3, 0.6, 1.0))
RenderingServer.global_shader_parameter_remove("my_color")

在執行時間新增或刪除全域均勻會產生效能成本,儘管與從腳本取得全域均勻值相比並不那麼明顯(請參閱下方的警告)。

警告

雖然您*可以*使用 RenderingServer.global_shader_parameter_get("uniform_name")`` 在腳本中執行時查詢全域均勻的值,但這會帶來很大的效能損失,因為渲染執行緒需要與呼叫執行緒同步。

因此,不建議在腳本中連續讀取全域著色器均勻值。如果您需要在設定後讀取腳本中的值,請考慮建立 autoload <doc_singletons_autoload>` ,您可以在其中儲存需要查詢的值,同時將它們設定為全域均勻值。

每個實例的製服

備註

每個實例的製服僅在「空間」(3D)著色器中可用。

有時,您會想要使用材質來修改每個節點上的參數。舉個例子,在一片樹木繁茂的森林中,您希望每棵樹的顏色略有不同,並且可以手動編輯。如果沒有每個實例的製服,這需要為每棵樹建立獨特的材質(每棵樹的色調略有不同)。這使得材質管理更加複雜,並且由於場景需要更多獨特的材質實例而產生效能開銷。這裡也可以使用頂點顏色,但它們需要為每種不同的顏色建立唯一的網格副本,這也會帶來效能開銷。

每個實例的製服是在每個 GeometryInstance3D 上設定的,而不是在每個 Material 實例上設定的。在處理分配有多種材質的網格體或多重網格體設定時,請考慮這一點。

shader_type spatial;

// Provide a hint to edit as a color. Optionally, a default value can be provided.
// If no default value is provided, the type's default is used (e.g. opaque black for colors).
instance uniform vec4 my_color : source_color = vec4(1.0, 0.5, 0.0, 1.0);

void fragment() {
    ALBEDO = my_color.rgb;
}

儲存著色器後,您可以使用屬性面板變更每個實例的製服值:

在屬性面板的 GeometryInstance3D 部分設定每個實例的製服值

在屬性面板的 GeometryInstance3D 部分設定每個實例的製服值

每個實例的均勻值也可以在執行時使用繼承自 class_GeometryInstance3D 的節點上的 set_instance_shader_parameter<class_GeometryInstance3D_method_set_instance_shader_parameter>` 方法設定:

$MeshInstance3D.set_instance_shader_parameter("my_color", Color(0.3, 0.6, 1.0))

使用每個實例的製服時,您應該注意一些限制:

  • 每個實例的製服不支援紋理,僅支援常規標量和向量型別。作為解決方法,您可以將紋理陣列作為常規制服傳遞,然後傳遞要使用每個實例制服繪製的紋理的索引。

  • 每個著色器的實際最大限制為 16 個實例制服。

  • 如果您的網格使用多種材質,則找到的第一個網格材質的參數將「勝過」後續網格材質,除非它們具有相同的名稱、索引*和*型別。在這種情況下,所有參數都會受到正確影響。

  • 如果遇到上述情況,可以透過使用「instance_index」提示手動指定實例均勻的索引(0-15)來避免衝突:

instance uniform vec4 my_color : source_color, instance_index(5);

本地坐標

有大量類似 UVCOLORVERTEX 的內建變數可用。具體有哪些變數可用取決於著色器的型別( spatialcanvas_item 以及 particle )和所在的函式( vertexfragment 以及 light )。可用的內建變數列表見對應的頁面:

內建函式

支援大量的內建函式, 符合GLSL ES 3.0. 當使用 vec_type (float), vec_int_type, vec_uint_type, vec_bool_type 命名法時, 它可以是標量或向量.

函式

描述/傳回值

vec_type radians (vec_type degrees度)

轉換縮排為 Tab

vec_type degrees ( vec_type radians弧度)

轉換縮排為空白

vec_type sin (vec_type x)

正弦。

vec_type cos (vec_type x)

餘弦。

vec_type tan (vec_type x)

切線陣列

vec_type asin (vec_type x)

反正弦。

vec_type acos (vec_type x)

反餘弦。

vec_type atan (vec_type y_over_x)

反正切。

vec_type atan (vec_type y, vec_type x)

反正切。

vec_type sinh (vec_type x)

雙曲正弦。

vec_type cosh (vec_type x)

雙曲餘弦。

vec_type tanh (vec_type x)

雙曲正切。

vec_type asinh (vec_type x)

反雙曲正弦。

vec_type acosh (vec_type x)

反雙曲餘弦。

vec_type atanh (vec_type x)

反雙曲正切。

vec_type pow (vec_type x, vec_type y)

冪(x < 0 或 x = 0 且 y <= 0 時未定義)。

vec_type exp (vec_type x)

基數 e 的指數。

vec_type exp2 (vec_type x)

基數 2 的指數。

vec_type log (vec_type x)

自然對數。

vec_type log2 (vec_type x)

以 2 為底的對數。

vec_type sqrt (vec_type x)

平方根。

vec_type inversesqrt (vec_type x)

反平方根。

vec_type abs (vec_type x)

ivec_type abs (ivec_type x)

絕對值(如果為負則傳回正值)。

vec_type sign ( vec_type )

ivec_type sign (ivec_type x)

符號(如果為正則傳回“1.0”,如果為負則傳回“-1.0”,如果為零則傳回“0.0”)。

vec_type floor (vec_type x)

向下四捨五入為整數。

vec_type round (vec_type x)

四捨五入到最接近的整數。

vec_type roundEven (vec_type x)

四捨五入到最接近的偶數。

vec_type trunc (vec_type x)

函式

vec_type ceil (vec_type x)

向上四捨五入為整數。

vec_type fract (vec_type x)

小數(返回“x - Floor(x)”)。

vec_type mod (vec_type x, vec_type y)

vec_type mod (vec_type x, float y)

乘法/除法/餘數

vec_type modf (vec_type x, out vec_type i)

x 的小數部分,i 為整數部分。

vec_type min (vec_type a, vec_type b)

ab 之間的較小值。

vec_type max (vec_type a, vec_type b)

ab 之間的較大值。

vec_type clamp (vec_type x, vec_type min, vec_type max)

將“x”夾在“min”和“max”(含)之間。

float mix (float a, float b, float c)

vec_type mix (vec_type a, vec_type b, float c)

vec_type mix (vec_type a, vec_type b, bvec_type c)

根據 cab 之間進行線性插值。

vec_type fma (vec_type a, vec_type b, vec_type c)

執行融合乘加運算:「(a * b + c)」(比手動執行更快)。

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)

Hermite 在 ab 之間透過 c 進行內插。

bvec_type isnan (vec_type x)

如果標量或向量分量是 NaN 則返回 true

bvec_type isinf (vec_type x)

如果標量或向量分量是 INF , 則返回 true

ivec_type floatBitsToInt (vec_type x)

Float->Int 位複製,無轉換。

uvec_type floatBitsToUint (vec_type x)

Float->UInt 位複製,無轉換。

vec_type intBitsToFloat (ivec_type x)

Int-> Float 位複製,無轉換。

vec_type uintBitsToFloat (uvec_type x)

UInt->Float 位複製,無轉換。

float length (vec_type x)

每行字數限制

float distance (vec_type a, vec_type b)

向量間距,即 length(a - b)

float dot (vec_type a, vec_type b)

點積。

vec3 cross (vec3 a, vec3 b)

外積。

vec_type normalize (vec_type x)

標準化為單位長度。

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)

如果 dot(Nref, I) <0, 則返回N, 否則返回-N。

mat_type matrixCompMult (mat_type x, mat_type y)

矩陣分量乘法。

mat_type outerProduct (vec_type column, vec_type row)

矩陣外積。

mat_type transpose (mat_type m)

切換行列(縱橫)顯示

float determinant (mat_type m)

矩陣行列式。

mat_type inverse (mat_type m)

逆矩陣。

bvec_type lessThan (vec_type x, vec_type y)

Bool vector 對比 < int/uint/float vectors。

bvec_type greaterThan (vec_type x, vec_type y)

Bool vector 對比 > int/uint/float vectors。

bvec_type lessThanEqual (vec_type x, vec_type y)

Bool vector 對比 <= int/uint/float vectors。

bvec_type greaterThanEqual (vec_type x, vec_type y)

Bool vector 對比 >= int/uint/float vectors。

bvec_type equal (vec_type x, vec_type y)

Bool vector 對比 == int/uint/float vectors。

bvec_type notEqual (vec_type x, vec_type y)

Bool vector 對比 != int/uint/float vectors。

bool any (bvec_type x)

如果任何組件為“true”,則為“true”,否則為“false”。

bool all (bvec_type x)

如果所有元件都是“true”,則為“true”,否則為“false”。

bvec_type not (bvec_type x)

翻轉顏色

ivec2 textureSize (gsampler2D s, int lod)

ivec3 textureSize (gsampler2DArray s, int lod)

ivec3 textureSize (gsampler3D s, int lod)

ivec2 textureSize (samplerCube s, int lod)

ivec2 textureSize (samplerCubeArray s, int lod)

匯入紋理

LOD 定義使用哪個 mipmap 等級。 LOD 值為“0”將使用全解析度紋理。

vec2 textureQueryLod (gsampler2D s, vec2 p)

vec3 textureQueryLod (gsampler2DArray s, vec2 p)

vec2 textureQueryLod (gsampler3D s, vec3 p)

vec2 textureQueryLod (samplerCube s, vec3 p)

計算用於從紋理取樣的細節等級。結果值的「x」元件是要存取的 mipmap 陣列。 「y」 分量是相對於基本層級的細節層級計算的(無論紋理的 mipmap 層級為何)。

int textureQueryLevels (gsampler2D s)

int textureQueryLevels (gsampler2DArray s)

int textureQueryLevels (gsampler3D s)

int textureQueryLevels (samplerCube s)

獲取cubemap紋理的大小。

如果紋理未指派給取樣器,則傳回「0」。

gvec4_type texture (gsampler2D s, vec2 p [, float bias])

gvec4_type texture (gsampler2DArray s, vec3 p [, float bias])

gvec4_type texture (gsampler3D s, vec3 p [, float bias])

vec4 texture (samplerCube s, vec3 p [, float bias])

vec4 texture (samplerCubeArray s, vec4 p [, float bias])

執行紋理讀取。

gvec4_type textureProj (gsampler2D s, vec3 p [, float bias])

gvec4_type textureProj (gsampler2D s, vec4 p [, float bias])

gvec4_type textureProj (gsampler3D s, vec4 p [, float bias])

執行帶投影的紋理讀取。

gvec4_type textureLod (gsampler2D s, vec2 p, float lod)

gvec4_type textureLod (gsampler2DArray s, vec3 p, float lod)

gvec4_type textureLod (gsampler3D s, vec3 p, float lod)

vec4 textureLod (samplerCube s, vec3 p, float lod)

vec4 textureLod (samplerCubeArray s, vec4 p, float lod)

在自訂 mipmap 上執行紋理讀取。

The LOD defines which mipmap level is used. An LOD value of 0.0 will use the full resolution texture. If the texture lacks mipmaps, all LOD values will act like 0.0.

gvec4_type textureProjLod (gsampler2D s, vec3 p, float lod)

gvec4_type textureProjLod (gsampler2D s, vec4 p, float lod)

gvec4_type textureProjLod (gsampler3D s, vec4 p, float lod)

執行帶投影/LOD的2D紋理讀取。

The LOD defines which mipmap level is used. An LOD value of 0.0 will use the full resolution texture. If the texture lacks mipmaps, all LOD values will act like 0.0.

gvec4_type textureGrad (gsampler2D s, vec2 p, vec2 dPdx, vec2 dPdy)

gvec4_type textureGrad (gsampler2DArray s, vec3 p, vec2 dPdx, vec2 dPdy)

gvec4_type textureGrad (gsampler3D s, vec3 p, vec2 dPdx, vec2 dPdy)

vec4 textureGrad (samplerCube s, vec3 p, vec3 dPdx, vec3 dPdy)

vec4 textureGrad (samplerCubeArray s, vec3 p, vec3 dPdx, vec3 dPdy)

執行帶明確的漸變的紋理讀取。

gvec4_type textureProjGrad (gsampler2D s, vec3 p, vec2 dPdx, vec2 dPdy)

gvec4_type textureProjGrad (gsampler2D s, vec4 p, vec2 dPdx, vec2 dPdy)

gvec4_type textureProjGrad (gsampler3D s, vec4 p, vec3 dPdx, vec3 dPdy)

Performs a texture read with projection/LOD and with explicit gradients.

gvec4_type texelFetch (gsampler2D s, ivec2 p, int lod)

gvec4_type texelFetch (gsampler2DArray s, ivec3 p, int lod)

gvec4_type texelFetch (gsampler3D s, ivec3 p, int lod)

使用整數座標獲取單個紋素。

LOD 定義使用哪個 mipmap 等級。 LOD 值為“0”將使用全解析度紋理。

gvec4_type textureGather (gsampler2D s, vec2 p [, int comps])

gvec4_type textureGather (gsampler2DArray s, vec3 p [, int comps])

vec4 textureGather (samplerCube s, vec3 p [, int comps])

從紋理中收集四個紋理像素。使用 0..3 範圍內的 comps 來定義傳回哪一個分量 (x, y, z, w)。如果未提供“comps”:使用 0(或 x 分量)。

vec_type dFdx (vec_type p)

使用局部差分在「x」中求導。在內部,可以使用“dFdxCoarse”或“dFdxFine”,但使用哪一個由 GPU 驅動程式決定。

vec_type dFdxCoarse (vec_type p)

使用基於目前片段鄰居的“p”值的局部差分來計算相對於“x”視窗座標的導數,並且可能但不一定包括目前片段的值。此功能在「gl_compatibility」設定檔上不可用。

vec_type dFdxFine (vec_type p)

使用基於目前片段及其直接鄰居的“p”值的局部差分來計算相對於“x”視窗座標的導數。此功能在「gl_compatibility」設定檔上不可用。

vec_type dFdy (vec_type p)

使用局部差分在 y 中求導。在內部,可以使用“dFdyCoarse”或“dFdyFine”,但使用哪一個由 GPU 驅動程式決定。

vec_type dFdyCoarse (vec_type p)

使用基於目前片段鄰居的“p”值的局部差分來計算相對於“y”視窗座標的導數,並且可能但不一定包括目前片段的值。此功能在「gl_compatibility」設定檔上不可用。

vec_type dFdyFine (vec_type p)

使用基於目前片段及其直接鄰居的“p”值的局部差分來計算相對於“y”視窗座標的導數。此功能在「gl_compatibility」設定檔上不可用。

vec_type fwidth (vec_type p)

“x” 和 “y” 的絕對導數總和。這相當於使用「abs(dFdx(p)) + abs(dFdy(p))」。

vec_type fwidthCoarse (vec_type p)

“x” 和 “y” 的絕對導數總和。這相當於使用「abs(dFdxCoarse(p)) + abs(dFdyCoarse(p))」。此功能在「gl_compatibility」設定檔上不可用。

vec_type fwidthFine (vec_type p)

“x” 和 “y” 的絕對導數總和。這相當於使用「abs(dFdxFine(p)) + abs(dFdyFine(p))」。此功能在「gl_compatibility」設定檔上不可用。

uint packHalf2x16 (vec2 v)

vec2 unpackHalf2x16 (uint v)

將兩個 32 位元浮點數轉換為 16 位元,並將它們打包為 32 位元無符號整數,反之亦然。

uint packUnorm2x16 (vec2 v)

vec2 unpackUnorm2x16 (uint v)

將兩個 32 位浮點數(限制在 0..1 範圍內)轉換為 16 位,並將它們打包為 32 位無符號整數,反之亦然。

uint packSnorm2x16 (vec2 v)

vec2 unpackSnorm2x16 (uint v)

將兩個 32 位浮點數(限制在 -1..1 範圍內)轉換為 16 位,並將它們打包為 32 位無符號整數,反之亦然。

uint packUnorm4x8 (vec4 v)

vec4 unpackUnorm4x8 (uint v)

將四個 32 位浮點數(限制在 0..1 範圍內)轉換為 8 位,並將它們打包為 32 位無符號整數,反之亦然。

uint packSnorm4x8 (vec4 v)

vec4 unpackSnorm4x8 (uint v)

將四個 32 位浮點數(限制在 -1..1 範圍內)轉換為 8 位,並將它們打包為 32 位無符號整數,反之亦然。

ivec_type bitfieldExtract (ivec_type value, int offset, int bits)

uvec_type bitfieldExtract (uvec_type value, int offset, int bits)

從整數中提取一系列位元。

ivec_type bitfieldInsert (ivec_type base, ivec_type insert, int offset, int bits)

uvec_type bitfieldInsert (uvec_type base, uvec_type insert, int offset, int bits)

將一系列位元插入整數中。

ivec_type bitfieldReverse (ivec_type value)

uvec_type bitfieldReverse (uvec_type value)

返回整數除法的餘數。

ivec_type bitCount (ivec_type value)

uvec_type bitCount (uvec_type value)

計算整數中 1 位的數量。

ivec_type findLSB (ivec_type value)

uvec_type findLSB (uvec_type value)

找出整數中設定為 1 的最低有效位元的索引。

ivec_type findMSB (ivec_type value)

uvec_type findMSB (uvec_type value)

找出整數中設定為 1 的最高有效位元的索引。

void imulExtended (ivec_type x, ivec_type y, out ivec_type msb, out ivec_type lsb)

void umulExtended (uvec_type x, uvec_type y, out uvec_type msb, out uvec_type lsb)

將兩個 32 位數字相乘並產生 64 位結果。 x - 第一個數字。 y - 第二個數字。 msb - 將包含最高有效位元。 lsb - 將包含最低有效位元。

uvec_type uaddCarry (uvec_type x, uvec_type y, out uvec_type carry)

將兩個無符號整數相加並產生進位。

uvec_type usubBorrow (uvec_type x, uvec_type y, out uvec_type borrow)

兩個無符號整數相減並產生借位。

vec_type ldexp (vec_type x, out ivec_type exp)

從數值和指陣列合浮點數。

如果該乘積太大而無法以浮點型別表示,則結果是未定義的。

vec_type frexp (vec_type x, out ivec_type exp)

將浮點數(x)拆分為有效數字(在 [0.5, 1.0] 範圍內)和整數指數。

對於“x”等於零,有效數和指數都為零。對於無窮大或 NaN 的“x”,結果是未定義的。