空間著色器

空間著色器用於三維物件的著色,是 Godot 提供中最複雜的著色器類型。空間著色器支援高度自訂,擁有多種算繪模式與不同的算繪選項(如:次表面散射、透射、環境遮蔽、邊緣光等)。開發者可以選擇撰寫頂點、片段、光照處理函式,以自訂物件的繪製方式。

算繪模式

這些算繪模式的視覺範例,請參見 Standard Material 3D 與 ORM Material 3D

算繪模式

說明

blend_mix

混合混合模式(Alpha 為透明度),預設。

blend_add

加法混合模式。

blend_sub

減法混合模式。

blend_mul

乘法混合模式。

blend_premul_alpha

預乘 Alpha 混合模式(完全透明時為加法,完全不透明時為混合模式)。

depth_draw_opaque

僅繪製不透明幾何體的深度(不含透明部分)。

depth_draw_always

始終繪製深度(不透明與透明物件均包含)。

depth_draw_never

不繪製深度。

depth_prepass_alpha

對透明幾何體進行不透明的深度預處理。

depth_test_disabled

停用深度測試。

sss_mode_skin

皮膚用的次表面散射模式(最佳化人類皮膚的視覺效果,例如加強紅色通道)。

cull_back

剔除背面(預設)。

cull_front

剔除正面。

cull_disabled

停用剔除(雙面渲染)。

unshaded

僅顯示反照率,不進行任何燈光或陰影計算,提升渲染效能。

wireframe

以線條方式繪製幾何體(適合除錯用)。

debug_shadow_splits

方向性陰影的每個分割區會以不同顏色繪製(方便除錯)。

diffuse_burley

漫反射使用 Burley(迪士尼 PBS,預設)。

diffuse_lambert

漫反射使用 Lambert 著色。

diffuse_lambert_wrap

漫反射使用 Lambert Wrap 著色(依粗糙度變化)。

diffuse_toon

漫反射使用卡通著色。

specular_schlick_ggx

直接光鏡面反射使用 Schlick-GGX(預設)。

specular_toon

直接光鏡面反射使用卡通著色。

specular_disabled

停用直接光的鏡面高光,不影響反射光(如需完全停用請使用 SPECULAR = 0.0)。

skip_vertex_transform

VERTEXNORMALTANGENTBITANGENT 需要在 vertex() 函式中手動進行轉換。

world_vertex_coords

VERTEXNORMALTANGENTBITANGENT 會在世界空間(而非模型空間)下被修改。

ensure_correct_normals

當網格有非均勻縮放時使用(註:目前尚未實作)。

shadows_disabled

Disable computing shadows in shader. The shader will not receive shadows, but can still cast them.

ambient_light_disabled

停用環境光與輻射圖的影響。

shadow_to_opacity

光照會調整 Alpha,使陰影區域不透明、無陰影區域透明。適合用於 AR 場景將陰影融合在相機畫面上。

vertex_lighting

使用頂點光照(取代逐像素光照)。

particle_trails

用於粒子幾何時啟用軌跡效果。

alpha_to_coverage

Alpha 抗鋸齒模式,詳見 此連結

alpha_to_coverage_and_one

Alpha 抗鋸齒模式,詳見 此連結

fog_disabled

停用基於深度或體積的霧氣接收。對於如粒子的 blend_add 材質很有用。

內建變數

標記為 in 的值為唯讀。標記為 out 的值可以選擇寫入,且不一定包含合理的預設值。標記為 inout 的值則有預設值,可以選擇寫入。取樣器(sampler)無法寫入,因此未標註。

並非所有內建變數都能在所有處理函式中使用。若要在 fragment() 函式中存取頂點階段內建變數,可以利用 varying。同理,若需在 light() 函式中存取片段階段的內建變數,也請使用 varying。

全域內建變數

全域內建變數可於任何地方使用,包括自訂函式。

內建變數

說明

in float TIME

自引擎啟動以來的全域時間(秒)。每 3,600 秒會重設(可透過 rollover 設定變更)。該值會受到 time_scale 影響,但不受暫停影響。如果你需要不受 time_scale 影響的 TIME,請自訂 全域著色器 uniform 並於每幀更新。

in float PI

常數 PI(3.141592),為圓周長與直徑的比值,也是一半圈的弧度數。

in float TAU

常數 TAU(6.283185),等於 PI * 2,也是一整圈的弧度數。

in float E

常數 E(2.718281),歐拉數,也是自然對數的底數。

in bool OUTPUT_IS_SRGB

當輸出處於 sRGB 色彩空間時為 true``(相容性算繪器為 ``true,Forward+ 與行動端為 false)。

in float CLIP_SPACE_FAR

裁剪空間的遠端 z 值。在 Forward+ 或行動算繪器中為 0.0,在相容性算繪器中為 -1.0。

頂點階段內建變數

頂點資料(VERTEXNORMALTANGENTBITANGENT)預設以模型(本地)空間表示。若未對這些變數寫入,將直接傳遞並在之後自動轉換為視圖空間給 fragment() 使用。

啟用 world_vertex_coords 算繪模式時,這些值可選擇以世界空間表示。

使用者可停用內建的 modelview 變換(投影仍會在後續進行),並自行於 shader 內進行如下轉換:

shader_type spatial;
render_mode skip_vertex_transform;

void vertex() {
    VERTEX = (MODELVIEW_MATRIX * vec4(VERTEX, 1.0)).xyz;
    NORMAL = normalize((MODELVIEW_MATRIX * vec4(NORMAL, 0.0)).xyz);
    BINORMAL = normalize((MODELVIEW_MATRIX * vec4(BINORMAL, 0.0)).xyz);
    TANGENT = normalize((MODELVIEW_MATRIX * vec4(TANGENT, 0.0)).xyz);
}

其他內建變數如 UVUV2COLOR,若未於頂點階段修改,亦會自動傳遞至 fragment() 階段。

使用者可透過寫入 POSITION 內建變數來覆蓋模型視圖與投影轉換。只要 shader 任何地方有寫入 POSITION,就會以該值為主,使用者需確保它始終有效。當 POSITION 被使用時,VERTEX 的值會被忽略且不進行投影,但傳遞至 fragment shader 的插值仍來自 VERTEX

在產生實體(instancing)時,INSTANCE_CUSTOM 變數包含自訂實例資料。用於粒子時內容通常如下:

  • x:旋轉角度,單位為弧度。

  • y:生命週期進度階段(0.0 ~ 1.0)。

  • z:動畫影格索引。

如此可讓你輕鬆將著色器調整至採用預設粒子材質的粒子系統。若撰寫自訂粒子 shader,也可依需求使用這些值。

內建變數

說明

in vec2 VIEWPORT_SIZE

視窗大小(像素)。

in mat4 VIEW_MATRIX

世界空間到視圖空間的轉換。

in mat4 INV_VIEW_MATRIX

視圖空間到世界空間的轉換。

in mat4 MAIN_CAM_INV_VIEW_MATRIX

用於繪製目前視窗的相機,其視圖空間到世界空間的轉換。

in mat4 INV_PROJECTION_MATRIX

裁剪空間到視圖空間的轉換。

in vec3 NODE_POSITION_WORLD

節點位置(世界空間)。

in vec3 NODE_POSITION_VIEW

節點位置(視圖空間)。

in vec3 CAMERA_POSITION_WORLD

相機在世界座標中的位置。

in vec3 CAMERA_DIRECTION_WORLD

相機方向(世界空間)。

in uint CAMERA_VISIBLE_LAYERS

目前算繪通道的相機可見圖層遮罩。

in int INSTANCE_ID

產生實體(instancing)時的實例 ID。

in vec4 INSTANCE_CUSTOM

自訂實體資料(主要用於粒子)。

in int VIEW_INDEX

目前算繪的視圖。 VIEW_MONO_LEFT0 )用於單視圖或左眼, VIEW_RIGHT1 )用於右眼。

in int VIEW_MONO_LEFT

單視圖或左眼用常數,值永遠為 0。

in int VIEW_RIGHT

右眼用常數,值永遠為 1。

in vec3 EYE_OFFSET

目前算繪眼睛的座標偏移量。僅適用於多視圖算繪。

inout vec3 VERTEX

頂點位置(模型空間)。如啟用 world_vertex_coords 則為世界空間。

in int VERTEX_ID

目前頂點在頂點緩衝區中的索引。

inout vec3 NORMAL

法線向量(模型空間),若啟用 world_vertex_coords 則為世界空間。

inout vec3 TANGENT

切線向量(模型空間),如啟用 world_vertex_coords 則為世界空間。

inout vec3 BINORMAL

副法線向量(模型空間),如啟用 world_vertex_coords 則為世界空間。

out vec4 POSITION

如有寫入,將覆蓋最終裁剪空間的頂點位置。

inout vec2 UV

UV 主通道。

inout vec2 UV2

UV2 次通道。

inout vec4 COLOR

頂點顏色。

out float ROUGHNESS

頂點光照用的粗糙度。

inout float POINT_SIZE

點算繪時的點大小。

inout mat4 MODELVIEW_MATRIX

模型(本地)空間到視圖空間的轉換(建議使用)。

inout mat3 MODELVIEW_NORMAL_MATRIX

in mat4 MODEL_MATRIX

模型(本地)空間到世界空間的轉換。

in mat3 MODEL_NORMAL_MATRIX

inout mat4 PROJECTION_MATRIX

視圖空間到裁剪空間的轉換。

in uvec4 BONE_INDICES

in vec4 BONE_WEIGHTS

in vec4 CUSTOM0

來自頂點原始資料的自訂值。若使用額外 UV,xy 對應 UV3,zw 對應 UV4。

in vec4 CUSTOM1

來自頂點原始資料的自訂值。若使用額外 UV,xy 對應 UV5,zw 對應 UV6。

in vec4 CUSTOM2

來自頂點原始資料的自訂值。若使用額外 UV,xy 對應 UV7,zw 對應 UV8。

in vec4 CUSTOM3

來自頂點原始資料的自訂值。

備註

MODELVIEW_MATRIX 結合了 WORLD_MATRIXINV_CAMERA_MATRIX,更適合可能會造成浮點數問題的場合。例如,如果物件距離世界原點非常遠,那麼使用單獨的 WORLD_MATRIXINV_CAMERA_MATRIX 可能就會遇到浮點數問題。

備註

INV_VIEW_MATRIX 是本次算繪通道用來轉換物件的矩陣,與 MAIN_CAM_INV_VIEW_MATRIX``(場景中主相機的矩陣)不同。在陰影通道時,``INV_VIEW_MATRIX 會以燈光所處位置的相機視圖為基準。

片段階段內建變數

Godot 片段處理函式的預設用途是設定物件的材質屬性,並交由內建算繪器處理最終著色。不必對所有這些屬性都寫入,未使用的部份 Godot 會自動優化移除相關運算。

內建變數

說明

in vec2 VIEWPORT_SIZE

視窗大小(像素)。

in vec4 FRAGCOORD

像素中心在螢幕空間中的座標。xy 表示在視窗中的位置,原點為左下角。z 表示片段深度,若未寫入 DEPTH,此值即作為片段深度輸出。

in bool FRONT_FACING

若當前面朝向正面則為 true,否則為 false

in vec3 VIEW

從片段位置指向相機的單位向量(視圖空間)。無論透視或正交攝影機,皆相同。

in vec2 UV

vertex() 傳來的 UV。

in vec2 UV2

vertex() 傳來的 UV2。

in vec4 COLOR

vertex() 函式傳遞來的顏色。

in vec2 POINT_COORD

使用 POINT_SIZE 算繪點時的點座標。

in mat4 MODEL_MATRIX

模型(本地)空間到世界空間的轉換。

in mat3 MODEL_NORMAL_MATRIX

模型(本地)空間至世界空間的法線轉換矩陣。預設與 MODEL_MATRIX 相同,若物件有非均勻縮放則設為 transpose(inverse(mat3(MODEL_MATRIX)))

in mat4 VIEW_MATRIX

世界空間到視圖空間的轉換。

in mat4 INV_VIEW_MATRIX

視圖空間到世界空間的轉換。

in mat4 PROJECTION_MATRIX

視圖空間到裁剪空間的轉換。

in mat4 INV_PROJECTION_MATRIX

裁剪空間到視圖空間的轉換。

in vec3 NODE_POSITION_WORLD

節點位置(世界空間)。

in vec3 NODE_POSITION_VIEW

節點位置(視圖空間)。

in vec3 CAMERA_POSITION_WORLD

相機在世界座標中的位置。

in vec3 CAMERA_DIRECTION_WORLD

相機方向(世界空間)。

in uint CAMERA_VISIBLE_LAYERS

目前算繪通道的相機可見圖層遮罩。

in vec3 VERTEX

片段(像素)的位置(視圖空間)。為 vertex() 傳來的 VERTEX 插值轉換至視圖空間的結果。若啟用 skip_vertex_transform,則可能不是視圖空間。

inout vec3 LIGHT_VERTEX

可寫入的 VERTEX 版本,用於更改光照與陰影。寫入本變數不會改變片段的位置。

in int VIEW_INDEX

目前算繪的視圖。用於多視角/立體算繪時區分視角。 VIEW_MONO_LEFT0 )代表單視角(非多視角)或左眼, VIEW_RIGHT1 )代表右眼。

in int VIEW_MONO_LEFT

單視圖或左眼用常數,值永遠為 0。

in int VIEW_RIGHT

右眼用常數,值永遠為 1。

in vec3 EYE_OFFSET

目前算繪眼睛的座標偏移量。僅適用於多視圖算繪。

sampler2D SCREEN_TEXTURE

已於 Godot 4 移除。請改用帶有 hint_screen_texturesampler2D

in vec2 SCREEN_UV

當前像素的螢幕 UV 座標。

sampler2D DEPTH_TEXTURE

已於 Godot 4 移除。請改用帶有 hint_depth_texturesampler2D

out float DEPTH

自訂深度值(範圍 0.0 ~ 1.0)。若任一 shader 分支寫入 DEPTH,則所有分支都必須明確設定 DEPTH,否則圖形 API 會將其視為未初始化。

inout vec3 NORMAL

vertex() 函式傳來的法線(視圖空間)。若啟用 skip_vertex_transform,則可能不是視圖空間。

inout vec3 TANGENT

vertex() 傳來的切線(視圖空間)。若啟用 skip_vertex_transform,則可能不是視圖空間。

inout vec3 BINORMAL

vertex() 傳來的副法線(視圖空間)。若啟用 skip_vertex_transform,則可能不是視圖空間。

out vec3 NORMAL_MAP

若需從材質貼圖(而非 NORMAL)讀取法線,請在此設定法線值。

out float NORMAL_MAP_DEPTH

NORMAL_MAP 的深度值,預設為 1.0。

out vec3 ALBEDO

反照率(預設白色)。基底色。

out float ALPHA

Alpha(0.0 ~ 1.0)。若有讀寫,材質將進入透明管線。

out float ALPHA_SCISSOR_THRESHOLD

如有寫入,Alpha 值低於此閾值的像素會被丟棄。

out float ALPHA_HASH_SCALE

使用 alpha hash 透明模式時的雜湊縮放。預設為 1.0,值越高,抖動圖樣中可見像素越多。

out float ALPHA_ANTIALIASING_EDGE

設定啟用 alpha to coverage 抗鋸齒的 alpha 閾值。預設 0.0。需搭配 alpha_to_coverage 模式,且此值應小於 ALPHA_SCISSOR_THRESHOLD 才有效。

out vec2 ALPHA_TEXTURE_COORDINATE

用於 alpha-to-coverage 抗鋸齒的材質座標。需啟用 alpha_to_coverage 模式。通常設為 UV * vec2(albedo_texture_size),其中 albedo_texture_size 為反照率貼圖的像素大小。

out float PREMUL_ALPHA_FACTOR

預乘 Alpha 因子。僅於啟用 render_mode blend_premul_alpha; 時生效。若使用有光照的預乘 Alpha 混合材質,請寫入此值。無光照(unshaded)材質則不需處理。

out float METALLIC

金屬度(0.0 ~ 1.0)。

out float SPECULAR

鏡面反射強度(非物理準確)。預設 0.5,設為 0.0 可停用反射。

out float ROUGHNESS

粗糙度(0.0 ~ 1.0)。

out float RIM

邊緣光(0.0 ~ 1.0)。如有使用 Godot 會自動計算邊緣光照,大小取決於 ROUGHNESS

out float RIM_TINT

邊緣色調,範圍從 0.0(白)到 1.0(反照率顏色)。如有使用,Godot 會計算邊緣光照。

out float CLEARCOAT

在現有鏡面反射上新增小範圍的高光。如有使用,Godot 會自動計算 Clearcoat(透明漆層)。

out float CLEARCOAT_GLOSS

Clearcoat 光澤度。如有使用,Godot 會自動計算 Clearcoat。

out float ANISOTROPY

依切線空間變形鏡面反射高光。

out vec2 ANISOTROPY_FLOW

失真方向,搭配 flowmap 使用。

out float SSS_STRENGTH

次表面散射強度。如有設定物件會啟用 SSS 效果。

out vec4 SSS_TRANSMITTANCE_COLOR

次表面散射穿透顏色。如有設定物件會啟用 SSS 穿透效果。

out float SSS_TRANSMITTANCE_DEPTH

次表面散射穿透深度,值越高效果越深入物件內部。

out float SSS_TRANSMITTANCE_BOOST

如設為大於 0.0 ,會加強次表面散射穿透,讓效果即使在直射光下也可見

inout vec3 BACKLIGHT

背光顏色(類似直接光照,但就算法線未完全朝向光源也會接收)。如有設定,物件會有背光效果,可作為次表面散射的較省效能近似法。

out float AO

環境遮蔽強度。用於搭配預先烘焙的 AO。

out float AO_LIGHT_AFFECT

環境遮蔽對直接光影響程度(0.0 ~ 1.0,預設 0.0)。

out vec3 EMISSION

自發光顏色(HDR 可超過 (1.0, 1.0, 1.0) )。

out vec4 FOG

如有寫入,最終像素顏色將依 FOG.aFOG.rgb 混合。

out vec4 RADIANCE

如有寫入,環境貼圖的輻射度將依 RADIANCE.aRADIANCE.rgb 混合。

out vec4 IRRADIANCE

如有寫入,環境貼圖的照度會依 IRRADIANCE.aIRRADIANCE.rgb 混合。

備註

寫入 ALPHA 並進入透明管線的 shader 可能會遇到透明排序問題。詳情與解法請參閱 3D 算繪限制頁之透明排序章節

燈光階段內建變數

撰寫光照處理函式(light processor function)是完全可選的。若使用 unshaded 算繪模式則可直接省略 light()。如果未撰寫 light 函式,Godot 會根據 fragment() 中的材質屬性自動計算燈光效果(依算繪模式而定)。

每一盞燈、每一個像素都會呼叫一次 light() 函式。此函式會針對每種燈光型別在迴圈中被呼叫。

以下是一個採用 Lambert 漫反射模型的自訂 light() 函式範例:

void light() {
    DIFFUSE_LIGHT += clamp(dot(NORMAL, LIGHT), 0.0, 1.0) * ATTENUATION * LIGHT_COLOR / PI;
}

若要讓多盞燈光疊加,請使用 += 將光照貢獻加到 DIFFUSE_LIGHT,而非直接覆蓋。

警告

若啟用 vertex_lighting 算繪模式,或在專案設定啟用 Rendering > Quality > Shading > Force Vertex Shading 時,light() 函式將不會執行。(在行動裝置預設啟用。)

內建變數

說明

in vec2 VIEWPORT_SIZE

視窗大小(像素)。

in vec4 FRAGCOORD

像素中心在螢幕空間中的座標。xy 表示視窗中的位置,若未使用 DEPTH,則 z 為片段深度。原點為左下角。

in mat4 MODEL_MATRIX

模型(本地)空間到世界空間的轉換。

in mat4 INV_VIEW_MATRIX

視圖空間到世界空間的轉換。

in mat4 VIEW_MATRIX

世界空間到視圖空間的轉換。

in mat4 PROJECTION_MATRIX

視圖空間到裁剪空間的轉換。

in mat4 INV_PROJECTION_MATRIX

裁剪空間到視圖空間的轉換。

in vec3 NORMAL

法線向量(視圖空間)。

in vec2 SCREEN_UV

當前像素的螢幕 UV 座標。

in vec2 UV

vertex() 傳來的 UV。

in vec2 UV2

vertex() 傳來的 UV2。

in vec3 VIEW

視線向量(視圖空間)。

in vec3 LIGHT

燈光向量(視圖空間)。

in vec3 LIGHT_COLOR

光源顏色 乘以 光源能量 再乘以 PI。乘上 PI 是因物理式光照模型會對光能量除以 PI

in float SPECULAR_AMOUNT

若為 OmniLight3DSpotLight3D,為 2.0 乘以 light_specular;若為 DirectionalLight3D,則為 1.0

in bool LIGHT_IS_DIRECTIONAL

若本通道為 DirectionalLight3D 則為 true

in float ATTENUATION

距離或陰影造成的光照衰減。

in vec3 ALBEDO

基底反照率。

in vec3 BACKLIGHT

in float METALLIC

金屬度。

in float ROUGHNESS

粗糙度。

out vec3 DIFFUSE_LIGHT

漫反射光輸出。

out vec3 SPECULAR_LIGHT

鏡面反射光輸出。

out float ALPHA

Alpha(0.0 ~ 1.0)。如有寫入,材質將進入透明管線。

備註

寫入 ALPHA 並進入透明管線的 shader 可能會遇到透明排序問題。詳情與解法請參閱 3D 算繪限制頁之透明排序章節

透明材質無法投射陰影,也無法出現在 hint_screen_texturehint_depth_texture uniform 內。因此這些材質不會出現在螢幕空間反射或折射效果中。SDFGI 的銳利反射不會顯示於透明材質(僅粗糙反射可見)。