Up to date

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

Sky-Shader

Sky-Shader sind eine spezielle Art von Shader, die zum Zeichnen von Himmelshintergründen und zum Aktualisieren von Strahlungs-Cubemaps verwendet werden, die für die bildbasierte Beleuchtung (IBL) eingesetzt werden. Himmels-Shader haben nur eine Verarbeitungsfunktion, die Funktion Sky().

Es gibt drei Stellen, an denen der Sky-Shader verwendet wird.

  • Zunächst wird der Sky-Shader verwendet, um den Himmel zu zeichnen, wenn Sie einen Himmel als Hintergrund in Ihrer Szene ausgewählt haben.

  • Zweitens wird der Sky-Shader verwendet, um die Radiance-Cubemap zu aktualisieren, wenn der Himmel für Umgebungsfarben oder Reflexionen verwendet wird.

  • Drittens wird der Sky-Shader verwendet, um die niedriger aufgelösten Subpasses zu zeichnen, die im hochauflösenden Hintergrund oder Cubemap-Pass verwendet werden können.

Insgesamt bedeutet dies, dass der Sky-Shader bis zu sechsmal pro Frame ausgeführt werden kann. In der Praxis wird es jedoch viel weniger sein, da die Radiance Cubemap nicht bei jedem Frame aktualisiert werden muss und nicht alle Subpasses verwendet werden. Man kann das Verhalten des Shaders ändern, je nachdem, wo er aufgerufen wird, indem man die AT_*_PASS Booleschen Werte überprüft. Zum Beispiel:

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

Wenn Sie den Sky-Shader verwenden, um einen Hintergrund zu zeichnen, wird der Shader für alle nicht verdeckten Fragmente auf dem Bildschirm aufgerufen. Bei den Unter-Durchläufen des Hintergrunds wird der Shader jedoch für jedes Pixel des Unter-Durchlaufs aufgerufen.

Wenn Sie den Sky-Shader zur Aktualisierung der Radiance Cubemap verwenden, wird der Sky-Shader für jedes Pixel in der Cubemap aufgerufen. Andererseits wird der Shader nur aufgerufen, wenn die Radiance Cubemap aktualisiert werden muss. Die Radiance Cubemap muss aktualisiert werden, wenn einer der Shader-Parameter aktualisiert wird. Wenn zum Beispiel TIME im Shader verwendet wird, dann wird die Radiance Cubemap bei jedem Frame aktualisiert. Die folgende Liste von Änderungen erzwingt eine Aktualisierung der Radiance Cubemap:

  • TIME wird verwendet.

  • POSITION wird verwendet und die Kameraposition ändert sich.

  • Wenn irgendwelche LIGHTX_* Propertys verwendet werden und sich irgendwelche DirectionalLight3D ändern.

  • Wenn ein Uniform im Shader geändert wird.

  • Wenn die Größe des Bildschirms geändert wird und einer der Unter-Durchläufe verwendet wird.

Versuchen Sie, eine unnötige Aktualisierung der Radiance Cubemap zu vermeiden. Wenn Sie die Radiance Cubemap bei jedem Frame aktualisieren müssen, stellen Sie sicher, dass Ihr Sky process mode auf REALTIME gesetzt ist.

Beachten Sie, dass der Prozessierungmodus nur das Rendering der Radiance Cubemap beeinflusst. Der sichtbare Himmel wird immer durch den Aufruf des Fragment-Shaders für jedes Pixel gerendert. Bei komplexen Fragment-Shadern kann dies zu einem hohen Rendering-Overhead führen. Wenn der Himmel statisch ist (die oben genannten Bedingungen sind erfüllt) oder sich nur langsam ändert, ist es nicht erforderlich, den vollständigen Fragment-Shader für jedes Bild aufzurufen. Dies kann vermieden werden, indem der gesamte Himmel in die Radiance Cubemap gerendert und beim Rendern des sichtbaren Himmels aus dieser Cubemap gelesen wird. Bei einem völlig statischen Himmel bedeutet dies, dass er nur einmal gerendert werden muss.

Der folgende Code rendert den gesamten Himmel in die Radiance Cubemap und liest aus dieser Cubemap den sichtbaren Himmel aus:

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

Auf diese Weise finden die komplexen Berechnungen nur im Cubemap-Durchlauf statt, der durch Einstellen des Prozessmodus und der Radianzgröße optimiert werden kann, um die gewünschte Balance zwischen Performance und visueller Wiedergabetreue zu erreichen.

Render-Modi

Mit Unter-Durchläufen können Sie aufwändigere Berechnungen mit einer niedrigeren Auflösung durchführen, um Ihre Shader zu beschleunigen. Der folgende Code rendert zum Beispiel die Wolken mit einer niedrigeren Auflösung als den Rest des Himmels:

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

Rendermodus

Beschreibung

use_half_res_pass

Ermöglicht dem Shader das Schreiben in und den Zugriff auf den Halbe-Auflösungs-Durchlauf.

use_quarter_res_pass

Ermöglicht dem Shader das Schreiben in und den Zugriff auf den Viertel-Auflösungs-Durchlauf.

disable_fog

Wenn er verwendet wird, hat der Nebel keine Auswirkungen auf den Himmel.

Built-ins

Die als "in" gekennzeichneten Werte sind schreibgeschützt. Mit "out" gekennzeichnete Werte sind zum optionalen Schreiben vorgesehen und enthalten nicht unbedingt sinnvolle Werte. Sampler können nicht beschrieben werden, daher sind sie nicht markiert.

Globale Built-ins

Globale Built-ins sind überall verfügbar, auch in benutzerdefinierten Funktionen.

Es gibt 4 LIGHTX-Lichter, die als LIGHT0, LIGHT1, LIGHT2 und LIGHT3 angesprochen werden.

Built-in

Beschreibung

in float TIME

Globale Zeit in Sekunden.

in vec3 POSITION

Kameraposition im World-Space

samplerCube RADIANCE

Radiance Cubemap. Kann nur während des Hintergrund-Durchlaufs gelesen werden. Prüfen Sie !AT_CUBEMAP_PASS vor der Verwendung.

in bool AT_HALF_RES_PASS

Derzeit wird der Halbe-Auflösungs-Durchlauf gerendert.

in bool AT_QUARTER_RES_PASS

Derzeit wird der Viertel-Auflösungs-Durchlauf gerendert.

in bool AT_CUBEMAP_PASS

Derzeit wird in die Radiance Cubemap gerendert.

in bool LIGHTX_ENABLED

LightX ist sichtbar und in der Szene. Wenn false, können andere Light Propertys Müll sein.

in float LIGHTX_ENERGY

Energiemultiplikator für LIGHTX.

in vec3 LIGHTX_DIRECTION

Richtung, in die LIGHTX gerichtet ist.

in vec3 LIGHTX_COLOR

Farbe von LIGHTX.

in float LIGHTX_SIZE

Winkeldurchmesser von LIGHTX am Himmel. Ausgedrückt in Grad. Zum Vergleich: Die Sonne ist von der Erde aus gesehen etwa 0,5 Grad groß.

in float PI

Eine PI-Konstante (3,141592). Das Verhältnis des Umfangs eines Kreises zu seinem Durchmesser und die Anzahl der Bogenmaßeinheiten in einer halben Umdrehung.

in float TAU

Eine TAU-Konstante (6.283185). Ein Äquivalent von PI * 2 und die Anzahl der Bogenmaßeinheiten in einer vollen Umdrehung.

in float E

Eine E-Konstante (2,718281). Eulersche Zahl und eine Basis des natürlichen Logarithmus.

Himmels-Built-ins

Built-in

Beschreibung

in vec3 EYEDIR

Normalisierte Richtung des aktuellen Pixels. Verwenden Sie dies als Grundrichtung für prozedurale Effekte.

in vec2 SCREEN_UV

Bildschirm-UV-Koordinate für das aktuelle Pixel. Wird verwendet, um eine Textur auf den gesamten Bildschirm abzubilden.

in vec2 SKY_COORDS

Kugel-UV. Wird verwendet, um eine Panoramatextur auf den Himmel abzubilden.

in vec4 HALF_RES_COLOR

Farbwert des entsprechenden Pixels aus dem Halbe-Auflösungs-Durchlauf. Verwendet einen linearen Filter.

in vec4 QUARTER_RES_COLOR

Farbwert des entsprechenden Pixels aus dem Viertel-Auflösungs-Durchlauf. Verwendet einen linearen Filter.

out vec3 COLOR

Farbe der Ausgabe.

out float ALPHA

Alphawert der Ausgabe, kann nur in Unterdurchläufen verwendet werden.

out vec4 FOG