空間著色器
空間著色器用於三維物件的著色,是 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 |
停用直接光的鏡面高光,不影響反射光(如需完全停用請使用 |
skip_vertex_transform |
|
world_vertex_coords |
|
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 |
停用基於深度或體積的霧氣接收。對於如粒子的 |
內建變數
標記為 in 的值為唯讀。標記為 out 的值可以選擇寫入,且不一定包含合理的預設值。標記為 inout 的值則有預設值,可以選擇寫入。取樣器(sampler)無法寫入,因此未標註。
並非所有內建變數都能在所有處理函式中使用。若要在 fragment() 函式中存取頂點階段內建變數,可以利用 varying。同理,若需在 light() 函式中存取片段階段的內建變數,也請使用 varying。
全域內建變數
全域內建變數可於任何地方使用,包括自訂函式。
內建變數 |
說明 |
|---|---|
in float TIME |
自引擎啟動以來的全域時間(秒)。每 3,600 秒會重設(可透過 rollover 設定變更)。該值會受到 time_scale 影響,但不受暫停影響。如果你需要不受 time_scale 影響的 |
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 色彩空間時為 |
in float CLIP_SPACE_FAR |
裁剪空間的遠端 z 值。在 Forward+ 或行動算繪器中為 0.0,在相容性算繪器中為 -1.0。 |
頂點階段內建變數
頂點資料(VERTEX、NORMAL、TANGENT、BITANGENT)預設以模型(本地)空間表示。若未對這些變數寫入,將直接傳遞並在之後自動轉換為視圖空間給 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);
}
其他內建變數如 UV、UV2、COLOR,若未於頂點階段修改,亦會自動傳遞至 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 |
目前算繪的視圖。 |
in int VIEW_MONO_LEFT |
單視圖或左眼用常數,值永遠為 0。 |
in int VIEW_RIGHT |
右眼用常數,值永遠為 1。 |
in vec3 EYE_OFFSET |
目前算繪眼睛的座標偏移量。僅適用於多視圖算繪。 |
inout vec3 VERTEX |
頂點位置(模型空間)。如啟用 |
in int VERTEX_ID |
目前頂點在頂點緩衝區中的索引。 |
inout vec3 NORMAL |
法線向量(模型空間),若啟用 |
inout vec3 TANGENT |
切線向量(模型空間),如啟用 |
inout vec3 BINORMAL |
副法線向量(模型空間),如啟用 |
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, |
in vec4 CUSTOM1 |
來自頂點原始資料的自訂值。若使用額外 UV, |
in vec4 CUSTOM2 |
來自頂點原始資料的自訂值。若使用額外 UV, |
in vec4 CUSTOM3 |
來自頂點原始資料的自訂值。 |
備註
MODELVIEW_MATRIX 結合了 WORLD_MATRIX 和 INV_CAMERA_MATRIX,更適合可能會造成浮點數問題的場合。例如,如果物件距離世界原點非常遠,那麼使用單獨的 WORLD_MATRIX 和 INV_CAMERA_MATRIX 可能就會遇到浮點數問題。
備註
INV_VIEW_MATRIX 是本次算繪通道用來轉換物件的矩陣,與 MAIN_CAM_INV_VIEW_MATRIX``(場景中主相機的矩陣)不同。在陰影通道時,``INV_VIEW_MATRIX 會以燈光所處位置的相機視圖為基準。
片段階段內建變數
Godot 片段處理函式的預設用途是設定物件的材質屬性,並交由內建算繪器處理最終著色。不必對所有這些屬性都寫入,未使用的部份 Godot 會自動優化移除相關運算。
內建變數 |
說明 |
|---|---|
in vec2 VIEWPORT_SIZE |
視窗大小(像素)。 |
in vec4 FRAGCOORD |
像素中心在螢幕空間中的座標。 |
in bool FRONT_FACING |
若當前面朝向正面則為 |
in vec3 VIEW |
從片段位置指向相機的單位向量(視圖空間)。無論透視或正交攝影機,皆相同。 |
in vec2 UV |
由 |
in vec2 UV2 |
由 |
in vec4 COLOR |
由 |
in vec2 POINT_COORD |
使用 |
in mat4 MODEL_MATRIX |
模型(本地)空間到世界空間的轉換。 |
in mat3 MODEL_NORMAL_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 |
片段(像素)的位置(視圖空間)。為 |
inout vec3 LIGHT_VERTEX |
可寫入的 |
in int VIEW_INDEX |
目前算繪的視圖。用於多視角/立體算繪時區分視角。 |
in int VIEW_MONO_LEFT |
單視圖或左眼用常數,值永遠為 0。 |
in int VIEW_RIGHT |
右眼用常數,值永遠為 1。 |
in vec3 EYE_OFFSET |
目前算繪眼睛的座標偏移量。僅適用於多視圖算繪。 |
sampler2D SCREEN_TEXTURE |
已於 Godot 4 移除。請改用帶有 |
in vec2 SCREEN_UV |
當前像素的螢幕 UV 座標。 |
sampler2D DEPTH_TEXTURE |
已於 Godot 4 移除。請改用帶有 |
out float DEPTH |
自訂深度值(範圍 0.0 ~ 1.0)。若任一 shader 分支寫入 |
inout vec3 NORMAL |
由 |
inout vec3 TANGENT |
由 |
inout vec3 BINORMAL |
由 |
out vec3 NORMAL_MAP |
若需從材質貼圖(而非 |
out float NORMAL_MAP_DEPTH |
|
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。需搭配 |
out vec2 ALPHA_TEXTURE_COORDINATE |
用於 alpha-to-coverage 抗鋸齒的材質座標。需啟用 |
out float PREMUL_ALPHA_FACTOR |
預乘 Alpha 因子。僅於啟用 |
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 會自動計算邊緣光照,大小取決於 |
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 |
如設為大於 |
inout vec3 BACKLIGHT |
背光顏色(類似直接光照,但就算法線未完全朝向光源也會接收)。如有設定,物件會有背光效果,可作為次表面散射的較省效能近似法。 |
out float AO |
環境遮蔽強度。用於搭配預先烘焙的 AO。 |
out float AO_LIGHT_AFFECT |
環境遮蔽對直接光影響程度(0.0 ~ 1.0,預設 0.0)。 |
out vec3 EMISSION |
自發光顏色(HDR 可超過 |
out vec4 FOG |
如有寫入,最終像素顏色將依 |
out vec4 RADIANCE |
如有寫入,環境貼圖的輻射度將依 |
out vec4 IRRADIANCE |
如有寫入,環境貼圖的照度會依 |
備註
寫入 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 |
像素中心在螢幕空間中的座標。 |
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 |
由 |
in vec2 UV2 |
由 |
in vec3 VIEW |
視線向量(視圖空間)。 |
in vec3 LIGHT |
燈光向量(視圖空間)。 |
in vec3 LIGHT_COLOR |
|
in float SPECULAR_AMOUNT |
若為 OmniLight3D 或 SpotLight3D,為 |
in bool LIGHT_IS_DIRECTIONAL |
若本通道為 DirectionalLight3D 則為 |
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_texture 與 hint_depth_texture uniform 內。因此這些材質不會出現在螢幕空間反射或折射效果中。SDFGI 的銳利反射不會顯示於透明材質(僅粗糙反射可見)。