Verwenden von Ansichtsfenstern (Viewports)

Einführung

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

../../_images/viewportnode.png

Viewports können der Szene auch hinzugefügt werden, sodass mehrere Oberflächen zum Zeichnen vorhanden sind. Wenn wir auf einem Viewport zeichnen das nicht die Wurzel ist, nennen wir es ein Renderziel. Wir können auf den Inhalt eines Renderziels zugreifen, indem wir hierauf texture zugreifen. Wenn Sie ein Viewport als Renderziel verwenden, können Sie entweder mehrere Szenen gleichzeitig rendern, oder wir können ein texture rendern, das auf ein Objekt in der Szene angewendet wird, zum Beispiel eine dynamische Skybox.

Viewports haben viele Nutzungsmöglichkeiten, inklusive:

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

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

  • Dynamische Texturen rendern

  • Prozedurale Texturen zur Laufzeit generieren

  • Rendern mehrerer Kameras in derselben Szene

Allen diesen Anwendungsfällen ist 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.

Eingabe

Viewports sind auch dafür verantwortlich, dass alle untergeordneten Nodes ordnungsgemäß angepasste und skalierte Eingabeereignisse erhalten. In der Regel wird die Eingabe vom nächsten Viewport im Baum empfangen, aber Sie können festlegen, dass Viewports keine Eingabe empfangen, indem Sie 'Disable Input' auf 'on' aktivieren; Dadurch kann der nächstgelegene Viewport im Baum die Eingabe erfassen.

../../_images/input.png

Für weitere Informationen dazu, wie Godot Eingaben verarbeitet, siehe InputEvent Tutorial.

Listener

Godot unterstützt 3D Sound (sowohl in 2D als auch in 3D Nodes). Weitere Informationen hierzu finden Sie im Audio Streams Anleitung. Damit diese Art von Sound zu hören ist, muss Viewport als Listener aktiviert sein (für 2D oder 3D). Wenn Sie ein benutzerdefiniertes Viewport verwenden, um Ihre Welt anzuzeigen, vergessen Sie nicht, dies zu aktivieren!

Kameras (2D & 3D)

Bei Verwendung von Camera / Camera2D werden Kameras immer auf dem nächstgelegenen übergeordneten Element angezeigt Viewport (in Richtung Wurzel). Zum Beispiel in der folgenden Hierarchie:

../../_images/cameras.png

CameraA wird im Wurzel Viewport angezeigt und zeichnet MeshA. CameraB wird vom Viewport-Node zusammen mit MeshB erfasst. Obwohl sich MeshB in der Szenenhierarchie befindet, wird es dennoch nicht im Wurzel :ref: Viewport <class_Viewport> gezeichnet. In ähnlicher Weise ist MeshA vom Viewport-Node nicht sichtbar, da Viewport-Nodes nur Nodes unter ihnen in der Hierarchie erfassen.

Es kann nur eine aktive Kamera pro Viewport geben. Wenn also mehr als eine vorhanden ist, stellen Sie sicher, dass für die gewünschte Kamera die Eigenschaft "current" festgelegt ist, oder machen Sie sie zur aktuellen Kamera, indem Sie Folgendes aufrufen:

camera.make_current()

Standardmäßig rendern Kameras alle Objekte in ihrer Welt. In 3D können Kameras ihre Eigenschaft cull_mask in Kombination mit der Eigenschaft VisualInstance layer verwenden, um zu beschränken, welche Objekte gerendert werden.

Skalieren & Dehnen

Viewports haben eine "size"-Eigenschaft, die die Größe des Viewport in Pixel darstellt. Für Viewports die untergeordnete Elemente von ViewportContainers sind, werden diese Werte überschrieben, für alle anderen wird jedoch ihre Auflösung festgelegt.

Es ist auch möglich den 2D Inhalt zu skalieren und die Viewport Auflösung von der in der Größe angegebenen Auflösung zu unterscheiden, indem Sie Folgendes aufrufen:

viewport.set_size_override(true, Vector2(width, height)) # Custom size for 2D.
viewport.set_size_override_stretch(true) # Enable stretch for custom size.

Der Wurzel Viewport verwendet dies für die Stretch-Optionen in den Projekteinstellungen. Weitere Informationen zum Skalieren und Dehnen finden Sie in der Anleitung für mehrere Auflösungen

Welten

Für 3D enthält ein Viewport eine World. Dies ist im Grunde das Universum, das Physik und Rendering miteinander verbindet. Raumbasierte Nodes registrieren sich mit World des nächstgelegenen Viewport. Standardmäßig enthält das neu erstellte Verzeichnis Viewports keine World, verwendet jedoch dasselbe wie das übergeordnete Viewport Element (der Wurzel :ref:` Viewport <class_Viewport> enthält immer eine :ref: World <class_World> , welches das Objekt ist, für das standardmäßig gerendert wird). Eine :ref:`World <class_World> kann in einem Viewport mithilfe der Eigenschaft "world" festgelegt werden. Dadurch werden alle untergeordneten Nodes dieses Viewport von Interaktionen mit dem übergeordneten Element Viewport World getrennt. Dies ist besonders nützlich in Szenarien, in denen Sie beispielsweise einen separaten Charakter in 3D anzeigen möchten, der über das Spiel festgelegt wurde (wie in StarCraft).

Als Hilfsmittel für Situationen, in denen Sie ein Viewport, der einzelne Objekte anzeigen und keine World erstellen möchten, hat Viewport die Möglichkeit eine eigene World zu verwenden. Dies ist nützlich, wenn Sie 3D Zeichen oder Objekte in einer 2D World Instanz instanziieren möchten.

Für 2D enthält jeder Viewport immer ein eigenes World2D. Dies reicht in den meisten Fällen aus, aber falls eine gemeinsame Nutzung gewünscht wird, können Sie dies manuell durch Viewport World2D festlegen.

Ein Beispiel dafür finden Sie in den Demo-Projekten 3D in 2D und `2D in 3D <https : //github.com/godotengine/godot-demo-projects/tree/master/viewport/2d_in_3d> `_.

Aufnahme

Es ist möglich, eine Erfassung des Inhalts von Viewport abzufragen. Für den Wurzel Viewport ist dies effektiv eine Bildschirmaufnahme. Dies geschieht mit folgendem Code:

# Retrieve the captured Image using get_data().
var img = get_viewport().get_texture().get_data()
# Flip on the Y axis.
# You can also set "V Flip" to true if not on the root Viewport.
img.flip_y()
# Convert Image to ImageTexture.
var tex = ImageTexture.new()
tex.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 für eine Textur da ist. Sie können dies beispielsweise so handhaben:

# Wait until the frame has finished before getting the texture.
yield(VisualServer, "frame_post_draw")
# You can get the image after this.

Viewport Container

Wenn der Viewport ein untergeordnetes Element eines ViewportContainer ist, wird es aktiv und zeigt seinen gesamten Inhalt an. Das Layout sieht folgendermaßen aus:

../../_images/container.png

Der Viewport deckt den Bereich seines übergeordneten ViewportContainer vollständig ab, wenn Stretch in ViewportContainer auf ` true` gesetzt ist. Hinweis: Die Größe des ViewportContainer darf nicht kleiner sein als die Größe des Viewport.

Rendering

Aufgrund der Tatsache, dass das Viewport in eine andere Rendering-Oberfläche übergehen kann, werden einige Rendering-Eigenschaften verfügbar gemacht, die von den Projekteinstellungen abweichen können. Der erste ist MSAA; Sie können für jeden Viewport eine andere MSAA-Stufe verwenden; Das Standardverhalten ist DEAKTIVIERT. Sie können auch einen Viewport HDR verwenden lassen. HDR ist sehr nützlich, wenn Sie Werte in der Textur speichern möchten, die außerhalb des Bereichs von 0,0 bis 1,0 liegen.

Wenn Sie bereits wissen wie ein Viewport verwendet wird, können Sie einstellen ob es entweder für 3D oder 2D genutzt werden soll. Godot wird dann einschränken, wie der Viewport gemäß Ihrer Wahl gezeichnet wird; Standard ist 3D. Der 2D-Nutzungsmodus ist etwas schneller und benötigt weniger Speicher als der 3D-Modus. Es ist eine gute Idee, die Nutzungs-Eigenschaft von Viewport auf 2D zu setzen, wenn Ihr Ansichtsfenster nichts in 3D rendert.

Bemerkung

Wenn Sie 3D-Schatten im Ansichtsfenster rendern müssen, stellen Sie sicher, dass die Eigenschaft Schattenatlasgröße des Ansichtsfensters auf einen Wert über 0 festgelegt ist. Andernfalls werden Schatten nicht gerendert. Als Referenz definieren die Projekteinstellungen standardmäßig 4096.

Godot bietet auch eine Möglichkeit, das Zeichnen innerhalb eines Viewports mithilfe von "Debug Draw" anzupassen . Mit Debug Draw können Sie eine von vier Optionen angeben, wie Viewport darin gezeichnete Objekte anzeigt. Debug Draw ist standardmäßig deaktiviert.

../../_images/default_scene.png

Eine Szene mit deaktiviertem Debug Draw

Die anderen drei Optionen sind Unschattiert, Überzeichnet und Drahtgitter. Unschattiert zeichnet die Szene ohne Verwendung von Beleuchtungsinformationen, sodass alle Objekte einfach in der Albedo-Farbe erscheinen.

../../_images/unshaded.png

Dieselbe Szene mit Debug Draw auf Unschattiert eingestellt

Durch Überzeichnen werden die Meshes mit einer additiven Mischung halbtransparent gezeichnet, sodass die Meshes überlappt erscheinen.

../../_images/overdraw.png

Dieselbe Szene mit Debug Draw auf Überzeichnet eingestellt

Zuletzt zeichnet Drahtgitter die Szene nur mit den Dreieckskanten in den Meshes.

Bemerkung

Die Auswirkungen des Drahtgitter-Modus sind nur im Editor sichtbar, nicht während das Projekt ausgeführt wird.

Ziel rendern

Beim Rendern in einem Viewport wird nichts was sich im Szeneneditor befindet angezeigt. Um den Inhalt anzuzeigen, müssen Sie irgendwo die ViewportTexture im :ref:`Viewports <class_Viewport>`zeichnen. Dies kann per Code angefordert werden mit (zum Beispiel):

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

Oder es kann im Editor durch Auswahl von "Neue ViewportTextur" zugewiesen werden

../../_images/texturemenu.png

und wählen Sie dann den gewünschten Viewport aus.

../../_images/texturepath.png

In jedem Frame wird die Textur des Viewport mit der standardmäßigen Lösch-Farbe gelöscht (oder eine transparente Farbe, wenn Transparent Bg auf true gesetzt ist). Dies kann geändert werden, indem Clear Mode auf Niemals oder Nächster Frame gesetzt wird. Wie der Name schon sagt bedeutet Niemals, dass die Textur niemals gelöscht wird, während Nächster Frame die Textur im nächsten Frame löscht und sich dann auf Niemals setzt.

Standardmäßig erfolgt das erneute Rendern des Viewport wenn die ViewportTexture des Viewport in einem Frame gezeichnet wurde. Wenn sichtbar wird es gerendert, andernfalls eben nicht. Dieses Verhalten kann geändert werden in manuelles rendern (einmal) oder immer rendern, unabhängig ob es sichtbar ist oder nicht. Diese Flexibilität ermöglicht es Benutzern, ein Bild einmal zu rendern und dann die Textur zu verwenden, ohne die Kosten für das Rendern in jedem Frame zu verursachen.

Sehen Sie sich unbedingt die Viewport-Demos an! Der Viewport-Ordner im Demo-Archiv ist hier zum Herunterladen verfügbar: https://github.com/godotengine/godot-demo-projects/tree/master/viewport