Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
天空著色器
天空著色器是一種特殊類型的著色器,用於繪製天空背景及更新用於基於影像照明(IBL)的輻射立方體貼圖。天空著色器僅有一個處理函式,即 sky() 函式。
天空著色器會在三個地方被使用。
首先,當你在場景中選擇使用天空作為背景時,天空著色器會用來繪製天空。
其次,當使用天空作為環境光或反射來源時,天空著色器會用於更新輻射立方體貼圖。
第三,天空著色器會用於算繪較低解析度的子通道,這些結果可用於高解析度背景或立方體貼圖通道。
總結來說,天空著色器每幀最多可執行六次。但實際上通常會少很多,因為輻射立方體貼圖不需每幀更新,而且不是所有子通道都會被用到。你可以透過檢查 AT_*_PASS 布林值來根據呼叫位置調整著色器行為。例如:
shader_type sky;
void sky() {
if (AT_CUBEMAP_PASS) {
// Sets the radiance cubemap to a nice shade of blue instead of doing
// expensive sky calculations
COLOR = vec3(0.2, 0.6, 1.0);
} else {
// Do expensive sky calculations for background sky only
COLOR = get_sky_color(EYEDIR);
}
}
當用天空著色器繪製背景時,會對螢幕上所有未被遮蔽的片段呼叫著色器。但對於背景的子通道,會對該子通道每個像素呼叫一次著色器。
當使用天空著色器來更新輻射立方體貼圖時,會針對立方體貼圖內每個像素執行一次著色器。但只有當輻射立方體貼圖需要更新時才會呼叫著色器。只要著色器的任何參數有更新時,立方體貼圖就需要重新計算。例如,如果著色器中有使用 TIME,那麼輻射立方體貼圖將每幀都重新計算。以下情況會強制觸發輻射立方體貼圖更新:
使用了
TIME。使用了
POSITION並且相機位置發生變化。如果有使用任何
LIGHTX_*屬性,且任何 DirectionalLight3D 發生變化。如果著色器中的任何 uniform 參數有更動。
若螢幕尺寸被調整,且有使用到任何子通道。
盡量避免不必要地更新輻射立方體貼圖。如果確實需要每幀更新輻射立方體貼圖,請確認你的 Sky 處理模式 已設為 PROCESS_MODE_REALTIME。
請注意,處理模式 僅影響輻射立方體貼圖的算繪。可見的天空仍會針對每個像素呼叫片段著色器。如果你的片段著色器很複雜,這會造成顯著的算繪負擔。如果天空是靜態的(如前述條件),或變化速度很慢,其實無需每幀都執行完整片段著色器。你可以將完整天空算繪到輻射立方體貼圖,再在顯示可見天空時直接讀取此貼圖。若天空完全靜態,只需要算繪一次即可。
以下程式碼會將完整天空算繪到輻射立方體貼圖,並在顯示可見天空時從該貼圖讀取:
shader_type sky;
void sky() {
if (AT_CUBEMAP_PASS) {
vec3 dir = EYEDIR;
vec4 col = vec4(0.0);
// Complex color calculation
COLOR = col.xyz;
ALPHA = 1.0;
} else {
COLOR = texture(RADIANCE, EYEDIR).rgb;
}
}
這樣一來,複雜的計算只會發生在立方體貼圖階段。你可以調整 天空處理模式 和 輻射貼圖尺寸,在效能與視覺品質間取得理想平衡。
算繪模式
子通道可讓你以較低解析度進行較昂貴的計算,加速著色器運算。例如,以下程式碼會以比天空其餘部分更低的解析度算繪雲層:
shader_type sky;
render_mode use_half_res_pass;
void sky() {
if (AT_HALF_RES_PASS) {
// Run cloud calculation for 1/4 of the pixels
vec4 color = generate_clouds(EYEDIR);
COLOR = color.rgb;
ALPHA = color.a;
} else {
// At full resolution pass, blend sky and clouds together
vec3 color = generate_sky(EYEDIR);
COLOR = color + HALF_RES_COLOR.rgb * HALF_RES_COLOR.a;
}
}
算繪模式 |
說明 |
|---|---|
use_half_res_pass |
允許著色器寫入及存取半解析度通道。 |
use_quarter_res_pass |
允許著色器寫入及存取四分之一解析度通道。 |
disable_fog |
啟用後,霧效將不會影響天空。 |
內建變數
標記為 in 的值為唯讀。標記為 out 的值可寫入,但不一定有合理初始值。取樣器(sampler)無法寫入,因此未標記。
全域內建變數
全域內建變數可於任何地方使用,包括自訂函式中。
有 4 個 LIGHTX 燈光,可分別以 LIGHT0、LIGHT1、LIGHT2、LIGHT3 存取。
內建變數 |
說明 |
|---|---|
in float TIME |
Global time since the engine has started, in seconds. It repeats after every |
in vec3 POSITION |
相機在世界座標中的位置。 |
samplerCube RADIANCE |
Radiance cubemap. Can only be read from during the background pass. Check |
in bool AT_HALF_RES_PASS |
|
in bool AT_QUARTER_RES_PASS |
|
in bool AT_CUBEMAP_PASS |
|
in bool LIGHTX_ENABLED |
若 |
in float LIGHTX_ENERGY |
|
in vec3 LIGHTX_DIRECTION |
|
in vec3 LIGHTX_COLOR |
|
in float LIGHTX_SIZE |
天空中 |
in float PI |
A |
in float TAU |
A |
in float E |
An |
天空內建變數
內建變數 |
說明 |
|---|---|
in vec3 EYEDIR |
Normalized direction of the current pixel. Use this as your basic direction for procedural effects. |
in vec2 SCREEN_UV |
Screen UV coordinate for the current pixel. Used to map a texture to the full screen. |
in vec2 SKY_COORDS |
球面 UV。用於將全景紋理貼圖到天空。 |
in vec4 HALF_RES_COLOR |
Color value of the corresponding pixel from the half resolution pass. Uses linear filter. |
in vec4 QUARTER_RES_COLOR |
Color value of the corresponding pixel from the quarter resolution pass. Uses linear filter. |
out vec3 COLOR |
輸出顏色。 |
out float ALPHA |
輸出的 alpha 值,只能在子通道中使用。 |
out vec4 FOG |