Up to date

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

著色器

天空著色器是一種特殊型別的著色器,用於繪製天空背景和更新用於基於影像的照明 (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_*」屬性且任何:ref:`DirectionalLight3D <class_DirectionalLight3D>`發生變化。

  • 如果著色器中更改了任何制服。

  • 如果調整螢幕大小並且使用任一子頻道。

盡量避免不必要地更新輻射立方體貼圖。如果您確實需要每影格更新輻射立方體貼圖,請確保您的 Sky 處理模式 <class_Sky_property_process_mode>` 設定為 REALTIME

Note that the process mode only affects the rendering of the radiance cubemap. The visible sky is always rendered by calling the fragment shader for every pixel. With complex fragment shaders, this can result in a high rendering overhead. If the sky is static (the conditions listed above are met) or changes slowly, running the full fragment shader every frame is not needed. This can be avoided by rendering the full sky into the radiance cubemap, and reading from this cubemap when rendering the visible sky. With a completely static sky, this means that it needs to be rendered only once.

The following code renders the full sky into the radiance cubemap and reads from that cubemap for displaying the visible sky:

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;
    }
}

This way, the complex calculations happen only in the cubemap pass, which can be optimized by setting the sky's process mode and the radiance size to get the desired balance between performance and visual fidelity.

渲染模式

子通道可讓您以較低的解析度進行更昂貴的計算,以加快著色器的速度。例如,以下程式碼以低於天空其餘部分的解析度渲染雲:

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" 的值是可以選擇寫入的, 不一定包含合理的值. 標記為 "inout" 的值提供一個合理的預設值, 並且可以選擇寫入. 取樣器不是寫入的物件, 它們沒有被標記.

定數

全域內建的功能隨處可見, 包括自訂功能.

LIGHTX 燈光有 4 個,可以通過 LIGHT0LIGHT1LIGHT2LIGHT3 存取。

內建

說明

in float TIME

全球時間, 以秒為單位.

in vec3 POSITION

相機位置,使用世界空間

samplerCube RADIANCE

輻射度立方體貼圖。只能在背景階段讀取。使用前請檢查 !AT_CUBEMAP_PASS

in bool AT_HALF_RES_PASS

目前正在渲染半解析度階段。

in bool AT_QUARTER_RES_PASS

目前正在渲染四分之一解析度階段。

in bool AT_CUBEMAP_PASS

目前正在渲染輻射度立方體貼圖。

in bool LIGHTX_ENABLED

場景中存在 LightX 並且可見。如果為 false,則其他燈光屬性可能為垃圾值。

in float LIGHTX_ENERGY

LIGHTX 的能量乘數。

in vec3 LIGHTX_DIRECTION

LIGHTX 面朝的方向。

in vec3 LIGHTX_COLOR

LIGHTX 的顏色。

in float LIGHTX_SIZE

天空中“LIGHTX”的角直徑。以度數表示。作為參考,太陽與地球的夾角約為0.5度。

in float PI

一個“PI”常數(“3.141592”)。圓的周長與其直徑的比率以及半圈的弧度數。

in float TAU

一個“TAU”常數(“6.283185”)。相當於“PI * 2”和完整的弧度數。

in float E

一個“E”常數(“2.718281”)。歐拉數和自然對數的底數。

定數

內建

說明

in vec3 EYEDIR

目前像素的標準化方向。將此作為程式效果的基本方向。

in vec2 SCREEN_UV

螢幕目前像素的UV座標.

in vec2 SKY_COORDS

球體紫外線。用於將全景紋理對應到天空。

in vec4 HALF_RES_COLOR

來自半解析度通道的相應像素的顏色值。使用線性濾波器。

in vec4 QUARTER_RES_COLOR

來自四分之一解析度通道的相應像素的顏色值。使用線性濾波器。

out vec3 COLOR

輸出顏色。

out float ALPHA

輸出 alpha 值,只能在子通道中使用。

out vec4 FOG