Up to date

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

Verwenden von Viewports

Einführung

Stellen Sie sich ein Viewport als einen Bildschirm vor, auf den das Spiel projiziert wird. Um das Spiel sehen zu können, brauchen wir eine Oberfläche, auf der wir es zeichnen können. Diese Fläche ist der Root-Viewport.

../../_images/subviewportnode.webp

SubViewports sind eine Art von Viewport, die der Szene hinzugefügt werden können, so dass es mehrere Oberflächen gibt, auf die man zeichnen kann. Wenn wir auf ein SubViewport zeichnen, nennen wir es ein Render-Target. Wir können auf den Inhalt eines Render-Targets zugreifen, indem wir auf die entsprechende Textur zugreifen. Wenn wir ein SubViewport als Render-Target verwenden, können wir entweder mehrere Szenen gleichzeitig rendern oder wir können auf eine ViewportTexture rendern, die auf ein Objekt in der Szene angewendet wird, zum Beispiel eine dynamische Skybox.

SubViewports haben eine Vielzahl von Anwendungsfällen, einschließlich:

  • Rendern von 3D-Objekten in einem 2D-Spiel

  • Rendern von 2D-Elementen in einem 3D-Spiel

  • Rendern von dynamischen Texturen

  • Generieren von prozeduralen Texturen zur Laufzeit

  • Rendern mehrerer Kameras in derselben Szene

Allen diese Anwendungsfällen haben gemeinsam, dass Sie Objekte auf eine Textur zeichnen können als wäre es ein anderer Bildschirm und dann auswählen können, was mit der resultierenden Textur geschehen soll.

Eine andere Art von Viewports in Godot sind Fenster. Sie erlauben es, ihren Inhalt auf ein Fenster zu projizieren. Auch wenn der Root Viewport ein Fenster ist, sind sie doch weniger flexibel. Wenn Sie die Textur eines Viewports verwenden wollen, werden Sie die meiste Zeit mit SubViewports arbeiten.

Eingabe

Viewports sind auch dafür verantwortlich, ihren Child-Nodes korrekt angepasste und skalierte Eingabeereignisse zu liefern. Standardmäßig erhalten SubViewports nicht automatisch Eingaben, es sei denn, sie erhalten sie von ihrem direkten SubViewportContainer Parent-Node. In diesem Fall kann die Eingabe mit der Property Eingabe Deaktivieren deaktiviert werden.

../../_images/input.webp

Für weitere Informationen darüber, wie Godot mit Eingaben umgeht, lesen Sie bitte das Input Event Tutorial.

Listener

Godot unterstützt 3D-Audio (sowohl in 2D- als auch in 3D-Nodes). Mehr dazu finden Sie im Audio Streams-Tutorial. Damit diese Art von Audio hörbar ist, muss das Viewport als Listener (für 2D oder 3D) aktiviert sein. Wenn Sie einen SubViewport verwenden, um Ihre World3D oder World2D anzuzeigen, vergessen Sie nicht, dies zu aktivieren!

Kameras (2D & 3D)

Wenn eine Camera3D oder Camera2D verwendet wird, wird sie immer auf dem nächstgelegenen Parent-Viewport (in Richtung Root) angezeigt. Zum Beispiel, in der folgenden Hierarchie:

../../_images/cameras.webp

CameraA wird auf dem Root Viewport angezeigt und es wird MeshA gezeichnet. CameraB wird von dem SubViewport zusammen mit MeshB aufgezeichnet. Obwohl MeshB in der Szenenhierarchie ist, wird es trotzdem nicht in den Root-Viewport gezeichnet. Ebenso wird MeshA im SubViewport nicht sichtbar sein, da SubViewports nur Nodes unterhalb von ihnen in der Hierarchie erfassen.

Es kann nur eine aktive Kamera pro Viewport geben. Wenn es also mehr als eine gibt, stellen Sie sicher, dass die gewünschte Kamera die Property current gesetzt hat, oder machen Sie sie durch einen Aufruf zur aktuellen Kamera:

camera.make_current()

Standardmäßig rendern Kameras alle Objekte in ihrer Welt. In 3D können Kameras ihre cull_mask-Property in Kombination mit der VisualInstance3D's layer-Property verwenden, um einzuschränken, welche Objekte gerendert werden.

Skalieren & Dehnen

SubViewports haben eine size Property, zur Darstellung der Größe des SubViewports in Pixeln. Für SubViewports, die Child-Elemente von SubViewportContainers sind, werden diese Werte überschrieben, aber für alle anderen left dies ihre Auflösung fest.

Es ist auch möglich, den 2D-Inhalt zu skalieren und die Auflösung des SubViewport von der in der Größe angegebenen Auflösung zu unterscheiden, indem man folgendes aufruft:

sub_viewport.set_size_2d_override(Vector2i(width, height)) # Custom size for 2D.
sub_viewport.set_size_2d_override_stretch(true) # Enable stretch for custom size.

Für Informationen zum Skalieren und Dehnen mit dem Root-Viewport besuchen Sie das Mehrfache-Auflösungen-Tutorial

Welten

Für 3D wird ein Viewport ein World3D enthalten. Dies ist im Grunde das Universum, das Physik und Rendering miteinander verbindet. Node3D-basierte Nodes registrieren sich mit dem World3D des nächstgelegenen Viewports. Standardmäßig enthalten neu erstellte Viewports kein World3D, sondern verwenden das gleiche wie der Parent-Viewport. Der Root-Viewport enthält immer ein World3D, in dem Objekte standardmäßig gerendert werden.

Ein World3D kann in einem Viewport mit der World 3D-Property gesetzt werden, die alle untergeordneten Nodes dieses Viewports trennt und verhindert, dass sie mit dem World3D des übergeordneten Viewports interagieren. Dies ist besonders nützlich in Szenarien, in denen man z.B. einen separaten Charakter in 3D über dem Spiel zeigen möchte (wie in StarCraft).

Als Hilfe für Situationen, in denen man Viewports erstellen möchte, die einzelne Objekte anzeigen und keine World3D erstellen wollen, hat Viewport die Option, seine Eigene World3D zu verwenden. Dies ist nützlich, wenn Sie 3D-Charaktere oder Objekte in World2D instanziieren wollen.

Für 2D enthält jeder Viewport immer sein eigenes World2D. Dies reicht in den meisten Fällen aus, aber falls eine gemeinsame Nutzung erwünscht ist, ist es möglich, dies zu tun, indem world_2d auf dem Viewport durch Code gesetzt wird.

Ein Beispiel dafür finden Sie in den Demo-Projekten 3D in 2D und 2D in 3D.

Capture

Es ist möglich, eine Aufnahme des Inhalts des Viewport abzufragen. Für den Root-Viewport ist dies effektiv eine Bildschirmaufnahme. Dies wird mit folgendem Code erreicht:

# Retrieve the captured Image using get_image().
var img = get_viewport().get_texture().get_image()
# Convert Image to ImageTexture.
var tex = ImageTexture.create_from_image(img)
# Set sprite texture.
sprite.texture = tex

Wenn Sie dies jedoch in _ready() oder ab dem ersten Frame der Viewport's-Initialisierung verwenden, erhalten Sie eine leere Textur, da nichts als Textur definiert ist. Sie können dies beispielsweise so handhaben:

# Wait until the frame has finished before getting the texture.
await RenderingServer.frame_post_draw
# You can get the image after this.

Viewport-Container

Wenn der SubViewport ein Child eines SubViewportContainer ist, wird er aktiv und zeigt alles an, was er enthält. Das Layout sieht wie folgt aus:

../../_images/container.webp

Der SubViewport deckt den Bereich seines Parent-SubViewportContainer vollständig ab, wenn Stretch im SubViewportContainer auf true gesetzt ist.

Bemerkung

Die Größe des SubViewportContainer kann nicht kleiner sein als die Größe des SubViewport.

Rendern

Da der Viewport ein Zugang zu einer anderen Rendering-Oberfläche darstellt, legt er einige Rendering-Propertys offen, die sich von den Projekteinstellungen unterscheiden können. Sie können für jeden Viewport eine andere Stufe von MSAA verwenden. Das Default-Verhalten ist Deaktiviert.

Wenn Sie wissen, dass der Viewport nur für 2D verwendet werden soll, können Sie Disable 3D. Godot wird dann einschränken, wie der Viewport gezeichnet wird. Die Deaktivierung von 3D ist etwas schneller und verbraucht weniger Speicher im Vergleich zu aktiviertem 3D. Es ist eine gute Idee, 3D zu deaktivieren, wenn Ihr Viewport nichts in 3D rendert.

Bemerkung

Wenn Sie 3D-Schatten im Viewport rendern müssen, stellen Sie sicher, dass Sie die Property positional_shadow_atlas_size des Viewports auf einen Wert größer als 0 setzen. Andernfalls werden die Schatten nicht gerendert. Standardmäßig ist die entsprechende Projekteinstellung auf 4096 auf Desktop-Plattformen und 2048 auf mobilen Plattformen gesetzt.

Godot bietet auch eine Möglichkeit, die Art und Weise, wie alles in Viewports gezeichnet wird, mit Debug Draw anzupassen. Debug Draw erlaubt es, einen Modus zu spezifizieren, der bestimmt, wie das Viewport Dinge, die darin gezeichnet werden, anzeigt. Debug Draw ist standardmäßig Deactivated. Einige andere Optionen sind Unshaded, Overdraw, und Wireframe. Eine vollständige Liste finden Sie in der Viewport Dokumentation.

  • Debug Draw = Disabled (Default): Die Szene wird normal gezeichnet.

../../_images/default_scene.webp
  • Debug Draw = Unshaded: Unshaded zeichnet die Szene ohne Beleuchtungsinformationen, so dass alle Objekte flach in ihrer Albedo-Farbe erscheinen.

../../_images/unshaded.webp
  • Debug Draw = Overdraw: Overdraw zeichnet die Meshes halbtransparent mit additivem Blending, damit Sie sehen können, wie sich die Meshes überlappen.

../../_images/overdraw.webp
  • Debug Draw = Wireframe: Wireframe zeichnet die Szene nur mit den Kanten der Dreiecke in den Meshes.

../../_images/wireframe.webp

Bemerkung

Debug-Zeichenmodi werden derzeit nicht unterstützt, wenn die Kompatibilität-Rendermethode verwendet wird. Sie werden als normale Zeichenmodi angezeigt.

Render-Target

Wenn man in ein SubViewport rendert, ist der Inhalt im Szeneneditor nicht sichtbar. Um den Inhalt anzuzeigen, muss man irgendwo die ViewportTexture des SubViewports zeichnen. Dies kann per Code angefordert werden, indem man (zum Beispiel):

# This gives us the ViewportTexture.
var tex = viewport.get_texture()
sprite.texture = tex

Oder sie kann im Editor durch Auswahl von "Neu: ViewportTexture" zugewiesen werden

../../_images/texturemenu.webp

und dann durch Auswahl des Viewport, den Sie verwenden möchten.

../../_images/texturepath.webp

In jedem Frame wird die Textur des Viewport's mit der Standard-Clear-Farbe geleert (oder einer transparenten Farbe, wenn Transparent BG auf true gesetzt ist). Dies kann geändert werden, indem man Clear Mode auf Never oder Next Frame setzt. Wie der Name schon sagt, bedeutet "Never", dass die Textur nie gelöscht wird, während "Next Frame" die Textur im nächsten Frame löscht und sich dann auf "Never" setzt.

Standardmäßig wird das SubViewport neu gerendert, wenn seine ViewportTexture in einem Frame gezeichnet wurde. Wenn er sichtbar ist, wird er gerendert, andernfalls wird er nicht gerendert. Dieses Verhalten kann durch Setzen von Update Mode auf Never, Once, Always, oder When Parent Visible geändert werden. Never und Always werden nie bzw. immer neu gerendert. Once wird im nächsten Frame neu gerendert und wechselt danach zu Never. Dies kann verwendet werden, um das Ansichtsfenster manuell zu aktualisieren. Diese Flexibilität ermöglicht es dem Benutzer, ein Bild einmal zu rendern und dann die Textur zu verwenden, ohne dass die Kosten für das Rendern jedes Frames anfallen.

Bemerkung

Sehen Sie sich unbedingt die Viewport-Demos an. Sie sind im Viewport-Ordner des Demos-Archivs oder unter https://github.com/godotengine/godot-demo-projects/tree/master/viewport verfügbar.