|
@@ -6,63 +6,73 @@ Viewports
|
|
Introduction
|
|
Introduction
|
|
------------
|
|
------------
|
|
|
|
|
|
-Godot has a small but useful feature called viewports. Viewports
|
|
|
|
-are, as the name implies, rectangles where the world is drawn. They
|
|
|
|
-have three main uses, but can flexibly adapted to a lot more. All this
|
|
|
|
-is done via the :ref:`Viewport <class_Viewport>` node.
|
|
|
|
|
|
+Think of :ref:`Viewports <class_Viewport>` as a screen that the game is projected onto. In order
|
|
|
|
+to see the game we need to have a surface to draw it on, this surface is
|
|
|
|
+the Root :ref:`Viewport <class_Viewport>`.
|
|
|
|
|
|
.. image:: img/viewportnode.png
|
|
.. image:: img/viewportnode.png
|
|
|
|
|
|
-The main uses in question are:
|
|
|
|
|
|
|
|
-- **Scene Root**: The root of the active scene is always a Viewport.
|
|
|
|
- This is what displays the scenes created by the user. (You should
|
|
|
|
- know this by having read previous tutorials!)
|
|
|
|
-- **Sub-Viewports**: These can be created when a Viewport is a child of
|
|
|
|
- a :ref:`Control <class_Control>`.
|
|
|
|
-- **Render Targets**: Viewports can be set to "RenderTarget" mode. This
|
|
|
|
- means that the viewport is not directly visible, but its contents
|
|
|
|
- can be accessed via a :ref:`Texture <class_Texture>`.
|
|
|
|
|
|
+:ref:`Viewports <class_Viewport>` can also be added to the scene so that there
|
|
|
|
+are multiple surfaces to draw on. When we are drawing to a :ref:`Viewport <class_Viewport>`
|
|
|
|
+that is not the Root we call it a render target. We can access the contents
|
|
|
|
+of a render target by accessing its corresponding :ref:`texture <class_ViewportTexture>`.
|
|
|
|
+By using a :ref:`Viewport <class_Viewport>` as a render target
|
|
|
|
+we can either render multiple scenes simultaneously or we can render to
|
|
|
|
+a :ref:`texture <class_ViewportTexture>` which is applied to an object in the scene, for example a dynamic
|
|
|
|
+skybox.
|
|
|
|
+
|
|
|
|
+:ref:`Viewports <class_Viewport>` have a variety of use cases including:
|
|
|
|
+
|
|
|
|
+- Rendering 3d objects within a 2d game
|
|
|
|
+- Rendering 2d elements in a 3d game
|
|
|
|
+- Rendering dynamic textures
|
|
|
|
+- Generating procedural textures at runtime
|
|
|
|
+- Rendering multiple cameras in the same scene
|
|
|
|
+
|
|
|
|
+What all these use cases have in common is that you are given the ability to
|
|
|
|
+draw objects to a texture as if it were another screen and then you can choose
|
|
|
|
+what to do with the resulting texture.
|
|
|
|
|
|
Input
|
|
Input
|
|
-----
|
|
-----
|
|
|
|
|
|
-Viewports are also responsible of delivering properly adjusted and
|
|
|
|
-scaled input events to all its children nodes. Both the root viewport
|
|
|
|
-and sub-viewports do this automatically, but render targets do not.
|
|
|
|
-Because of this, the user must do it manually via the
|
|
|
|
-:ref:`Viewport.input() <class_Viewport_input>` function if needed.
|
|
|
|
|
|
+:ref:`Viewports <class_Viewport>` are also responsible for delivering properly adjusted and
|
|
|
|
+scaled input events to all their children nodes. Typically input is received by the
|
|
|
|
+nearest :ref:`Viewport <class_Viewport>` in the tree, but you can set :ref:`Viewports <class_Viewport>` to not recieve input by checking
|
|
|
|
+'Disable Input' to 'on', this will allow the next nearest :ref:`Viewport <class_Viewport>` in the tree to capture
|
|
|
|
+the input.
|
|
|
|
+
|
|
|
|
+.. image:: img/input.png
|
|
|
|
+
|
|
|
|
+For more information on how Godot handles input please read the :ref:`Input Event Tutorial<doc_inputevent>`.
|
|
|
|
|
|
Listener
|
|
Listener
|
|
--------
|
|
--------
|
|
|
|
|
|
Godot supports 3D sound (in both 2D and 3D nodes), more on this can be
|
|
Godot supports 3D sound (in both 2D and 3D nodes), more on this can be
|
|
-found in another tutorial (one day..). For this type of sound to be
|
|
|
|
-audible, the viewport needs to be enabled as a listener (for 2D or 3D).
|
|
|
|
-If you are using a custom viewport to display your world, don't forget
|
|
|
|
|
|
+found in the :ref:`Audio Streams Tutorial<doc_audio-streams>`. For this type of sound to be
|
|
|
|
+audible, the :ref:`Viewport <class_Viewport>` needs to be enabled as a listener (for 2D or 3D).
|
|
|
|
+If you are using a custom :ref:`Viewport <class_Viewport>` to display your :ref:`World <class_World>`, don't forget
|
|
to enable this!
|
|
to enable this!
|
|
|
|
|
|
Cameras (2D & 3D)
|
|
Cameras (2D & 3D)
|
|
-----------------
|
|
-----------------
|
|
|
|
|
|
-When using a 2D or 3D :ref:`Camera <class_Camera>` /
|
|
|
|
|
|
+When using a :ref:`Camera <class_Camera>` /
|
|
:ref:`Camera2D <class_Camera2D>`, cameras will always display on the
|
|
:ref:`Camera2D <class_Camera2D>`, cameras will always display on the
|
|
-closest parent viewport (going towards the root). For example, in the
|
|
|
|
|
|
+closest parent :ref:`Viewport <class_Viewport>` (going towards the root). For example, in the
|
|
following hierarchy:
|
|
following hierarchy:
|
|
|
|
|
|
-- Viewport
|
|
|
|
-
|
|
|
|
- - Camera
|
|
|
|
-
|
|
|
|
-Camera will display on the parent viewport, but in the following one:
|
|
|
|
-
|
|
|
|
-- Camera
|
|
|
|
|
|
+.. image:: img/cameras.png
|
|
|
|
|
|
- - Viewport
|
|
|
|
|
|
+CameraA will display on the Root :ref:`Viewport <class_Viewport>` and it will draw MeshA. CameraB
|
|
|
|
+will be captured by the :ref:`Viewport <class_Viewport>` Node along with MeshB. Even though MeshB is in the scene
|
|
|
|
+heirarchy, it will still not be drawn to the Root :ref:`Viewport <class_Viewport>`. Similarly MeshA will not
|
|
|
|
+be visible from the :ref:`Viewport <class_Viewport>` node becuase :ref:`Viewport <class_Viewport>` nodes only capture nodes below them
|
|
|
|
+in the heirarchy.
|
|
|
|
|
|
-It will not (or may display in the root viewport if this is a subscene).
|
|
|
|
-
|
|
|
|
-There can be only one active camera per viewport, so if there is more
|
|
|
|
|
|
+There can only be one active camera per :ref:`Viewport <class_Viewport>`, so if there is more
|
|
than one, make sure that the desired one has the "current" property set,
|
|
than one, make sure that the desired one has the "current" property set,
|
|
or make it the current camera by calling:
|
|
or make it the current camera by calling:
|
|
|
|
|
|
@@ -73,60 +83,60 @@ or make it the current camera by calling:
|
|
Scale & stretching
|
|
Scale & stretching
|
|
------------------
|
|
------------------
|
|
|
|
|
|
-Viewports have a "rect" property. X and Y are often not used (only the
|
|
|
|
-root viewport uses them), while WIDTH AND HEIGHT represent the
|
|
|
|
-size of the viewport in pixels. For Sub-Viewports, these values are
|
|
|
|
-overridden by the ones from the parent control, but for render targets
|
|
|
|
-this sets their resolution.
|
|
|
|
|
|
+:ref:`Viewports <class_Viewport>` have a "size" property which represents the size of the :ref:`Viewport <class_Viewport>`
|
|
|
|
+in pixels. For :ref:`Viewports <class_Viewport>` which are children of :ref:`ViewportContainers <class_viewportcontainer>`,
|
|
|
|
+these values are overridden, but for all others this sets their resolution.
|
|
|
|
|
|
-It is also possible to scale the 2D content and make it believe the
|
|
|
|
-viewport resolution is other than the one specified in the rect, by
|
|
|
|
-calling:
|
|
|
|
|
|
+It is also possible to scale the 2D content and make the :ref:`Viewport <class_Viewport>` resolution
|
|
|
|
+different than the one specified in size, by calling:
|
|
|
|
|
|
::
|
|
::
|
|
|
|
|
|
viewport.set_size_override(w, h) # custom size for 2D
|
|
viewport.set_size_override(w, h) # custom size for 2D
|
|
viewport.set_size_override_stretch(true) # enable stretch for custom size
|
|
viewport.set_size_override_stretch(true) # enable stretch for custom size
|
|
|
|
|
|
-The root viewport uses this for the stretch options in the project
|
|
|
|
-settings.
|
|
|
|
|
|
+The root :ref:`Viewport <class_Viewport>` uses this for the stretch options in the project
|
|
|
|
+settings. For more information on scaling and stretching visit the :ref:`Multiple Resolutions Tutorial <doc_multiple_resolutions>`
|
|
|
|
|
|
Worlds
|
|
Worlds
|
|
------
|
|
------
|
|
|
|
|
|
-For 3D, a Viewport will contain a :ref:`World <class_World>`. This
|
|
|
|
|
|
+For 3D, a :ref:`Viewport <class_Viewport>` will contain a :ref:`World <class_World>`. This
|
|
is basically the universe that links physics and rendering together.
|
|
is basically the universe that links physics and rendering together.
|
|
-Spatial-base nodes will register using the World of the closest
|
|
|
|
-viewport. By default, newly created viewports do not contain a World but
|
|
|
|
-use the same as a parent viewport (root viewport does contain one
|
|
|
|
-though, which is the one objects are rendered to by default). A world can
|
|
|
|
-be set in a viewport using the "world" property, and that will separate
|
|
|
|
-all children nodes of that viewport from interacting with the parent
|
|
|
|
-viewport world. This is especially useful in scenarios where, for
|
|
|
|
|
|
+Spatial-base nodes will register using the :ref:`World <class_World>` of the closest
|
|
|
|
+:ref:`Viewport <class_Viewport>`. By default, newly created :ref:`Viewports <class_Viewport>` do not contain a :ref:`World <class_World>` but
|
|
|
|
+use the same as their parent :ref:`Viewport <class_Viewport>` (root :ref:`Viewport <class_Viewport>` always contains a
|
|
|
|
+:ref:`World <class_World>`, which is the one objects are rendered to by default). A :ref:`World <class_World>` can
|
|
|
|
+be set in a :ref:`Viewport <class_Viewport>` using the "world" property, and that will separate
|
|
|
|
+all children nodes of that :ref:`Viewport <class_Viewport>` from interacting with the parent
|
|
|
|
+:ref:`Viewport's <class_Viewport>` :ref:`World <class_World>`. This is especially useful in scenarios where, for
|
|
example, you might want to show a separate character in 3D imposed over
|
|
example, you might want to show a separate character in 3D imposed over
|
|
the game (like in Starcraft).
|
|
the game (like in Starcraft).
|
|
|
|
|
|
-As a helper for situations where you want to create viewports that
|
|
|
|
-display single objects and don't want to create a world, viewport has
|
|
|
|
-the option to use its own World. This is useful when you want to
|
|
|
|
-instance 3D characters or objects in the 2D world.
|
|
|
|
|
|
+As a helper for situations where you want to create :ref:`Viewports <class_Viewport>` that
|
|
|
|
+display single objects and don't want to create a :ref:`World <class_World>`, :ref:`Viewport <class_Viewport>` has
|
|
|
|
+the option to use its own :ref:`World <class_World>`. This is useful when you want to
|
|
|
|
+instance 3D characters or objects in a 2D :ref:`World <class_World2D>`.
|
|
|
|
|
|
-For 2D, each Viewport always contains its own :ref:`World2D <class_World2D>`.
|
|
|
|
|
|
+For 2D, each :ref:`Viewport <class_Viewport>` always contains its own :ref:`World2D <class_World2D>`.
|
|
This suffices in most cases, but in case sharing them may be desired, it
|
|
This suffices in most cases, but in case sharing them may be desired, it
|
|
-is possible to do so by calling the viewport API manually.
|
|
|
|
|
|
+is possible to do so by setting the :ref:`Viewport's <class_Viewport>` :ref:`World2D <class_World2D>` manually.
|
|
|
|
+
|
|
|
|
+For an example of how this works see the demo projects `3D in 2D <https://github.com/godotengine/godot-demo-projects/tree/master/viewport/3d_in_2d>`_ and `2D in 3D <https://github.com/godotengine/godot-demo-projects/tree/master/viewport/2d_in_3d>`_ respectively.
|
|
|
|
|
|
Capture
|
|
Capture
|
|
-------
|
|
-------
|
|
|
|
|
|
-It is possible to query a capture of the viewport contents. For the root
|
|
|
|
-viewport this is effectively a screen capture. This is done with the
|
|
|
|
-following API:
|
|
|
|
|
|
+It is possible to query a capture of the :ref:`Viewport <class_Viewport>` contents. For the root
|
|
|
|
+:ref:`Viewport <class_Viewport>` this is effectively a screen capture. This is done with the
|
|
|
|
+following code:
|
|
|
|
|
|
::
|
|
::
|
|
|
|
|
|
# Retrieve the captured Image using get_data()
|
|
# Retrieve the captured Image using get_data()
|
|
var img = get_viewport().get_texture().get_data()
|
|
var img = get_viewport().get_texture().get_data()
|
|
- # Also remember to flip the texture (because it's flipped)
|
|
|
|
|
|
+ # Flip on the y axis
|
|
|
|
+ # You can also set "V Flip" to true if not on the Root Viewport
|
|
img.flip_y()
|
|
img.flip_y()
|
|
# Convert Image to ImageTexture
|
|
# Convert Image to ImageTexture
|
|
var tex = ImageTexture.new()
|
|
var tex = ImageTexture.new()
|
|
@@ -134,7 +144,7 @@ following API:
|
|
# Set Sprite Texture
|
|
# Set Sprite Texture
|
|
$sprite.texture = tex
|
|
$sprite.texture = tex
|
|
|
|
|
|
-But if you use this in _ready() or from the first frame of the viewport's initialization
|
|
|
|
|
|
+But if you use this in _ready() or from the first frame of the :ref:`Viewport's <class_Viewport>` initialization
|
|
you will get an empty texture cause there is nothing to get as texture. You can deal with
|
|
you will get an empty texture cause there is nothing to get as texture. You can deal with
|
|
it using (for example):
|
|
it using (for example):
|
|
|
|
|
|
@@ -146,45 +156,92 @@ it using (for example):
|
|
# You can get the image after this
|
|
# You can get the image after this
|
|
|
|
|
|
If the returned image is empty, capture still didn't happen, wait a
|
|
If the returned image is empty, capture still didn't happen, wait a
|
|
-little more, as this API is asynchronous.
|
|
|
|
|
|
+little more, as Godot's rendering API is asynchronous. For a working example of this
|
|
|
|
+check out the `Screen Capture example <https://github.com/godotengine/godot-demo-projects/tree/master/viewport/screen_capture>`_ in the demo projects
|
|
|
|
|
|
-Sub-viewport
|
|
|
|
-------------
|
|
|
|
|
|
+Viewport Container
|
|
|
|
+------------------
|
|
|
|
+
|
|
|
|
+If the :ref:`Viewport <class_Viewport>` is a child of a :ref:`ViewportContainer <class_viewportcontainer>`, it will become active and
|
|
|
|
+display anything it has inside. The layout looks like this:
|
|
|
|
+
|
|
|
|
+.. image:: img/container.png
|
|
|
|
+
|
|
|
|
+The :ref:`Viewport <class_Viewport>` will cover the area of its parent :ref:`ViewportContainer <class_viewportcontainer>` completely
|
|
|
|
+if stretch is set to true in :ref:`ViewportContainer <class_viewportcontainer>`.
|
|
|
|
+Note: The size of the :ref:`ViewportContainer <class_viewportcontainer>` cannot be smaller than the size of the :ref:`Viewport <class_Viewport>`.
|
|
|
|
|
|
-If the viewport is a child of a :ref:`ViewportContainer <class_viewportcontainer>`, it will become active and
|
|
|
|
-display anything it has inside. The layout is something like this:
|
|
|
|
|
|
+Rendering
|
|
|
|
+---------
|
|
|
|
|
|
-- ViewportContainer
|
|
|
|
-
|
|
|
|
- - Viewport
|
|
|
|
|
|
+Due to the fact that the :ref:`Viewport <class_Viewport>` is an entryway into another rendering surface, it exposes a few
|
|
|
|
+rendering properties that can be different from the project settings. The first is MSAA, you can
|
|
|
|
+choose to use a different level of MSAA for each :ref:`Viewport <class_Viewport>`, the default behavior is DISABLED.
|
|
|
|
+You can also set the :ref:`Viewport <class_Viewport>` to use HDR, HDR is very useful for when you want to store values in the
|
|
|
|
+texture that are outside the range 0.0 - 1.0.
|
|
|
|
|
|
-The viewport will cover the area of its parent control completely, if stretch is set to true in Viewport Container.
|
|
|
|
-But you will have to setup the Viewport Size to get the the appropriate part of the Viewport.
|
|
|
|
-And Viewport Container can not be smaller than the size of the Viewport.
|
|
|
|
|
|
+If you know how the :ref:`Viewport <class_Viewport>` is going to be used, you can set its Usage to either 3D or 2D. Godot will then
|
|
|
|
+restrict how the :ref:`Viewport <class_Viewport>` is drawn to in accordance with your choice, default is 3D.
|
|
|
|
|
|
-.. image:: img/subviewport.png
|
|
|
|
|
|
+Godot also provides a way of customizing how everything is drawn inside :ref:`Viewports <class_Viewport>` using “Debug Draw”.
|
|
|
|
+Debug Draw allows you to specify one of four options for how the :ref:`Viewport <class_Viewport>` will display things drawn
|
|
|
|
+inside it. Debug Draw is disabled by default.
|
|
|
|
+
|
|
|
|
+.. image:: img/default_scene.png
|
|
|
|
+
|
|
|
|
+*A scene drawn with Debug Draw disabled*
|
|
|
|
+
|
|
|
|
+The other three options are Unshaded, Overdraw, and Wireframe. Unshaded draws the scene
|
|
|
|
+without using lighting information so all the objects appear flatly colored the color of
|
|
|
|
+their albedo.
|
|
|
|
+
|
|
|
|
+.. image:: img/unshaded.png
|
|
|
|
+
|
|
|
|
+*The same scene with Debug Draw set to Unshaded*
|
|
|
|
+
|
|
|
|
+Overdraw draws the meshes semi-transparent with an additive blend so you can see how the meshes overlap.
|
|
|
|
+
|
|
|
|
+.. image:: img/overdraw.png
|
|
|
|
+
|
|
|
|
+*The same scene with Debug Draw set to Overdraw*
|
|
|
|
+
|
|
|
|
+Lastly, Wireframe draws the scene using only the edges of triangles in the meshes. NOTE: as of the
|
|
|
|
+writting of this (v3.0.2) wireframe is broken and currently just renders the scene normally.
|
|
|
|
|
|
Render target
|
|
Render target
|
|
-------------
|
|
-------------
|
|
|
|
|
|
-To set as a render target, toggle the "render target" property of
|
|
|
|
-the viewport to enabled. Note that whatever is inside will not be
|
|
|
|
-visible in the scene editor. To display the contents, the method remains the same.
|
|
|
|
|
|
+When rendering to a :ref:`Viewport <class_Viewport>` whatever is inside will not be
|
|
|
|
+visible in the scene editor. To display the contents, you have to draw the :ref:`Viewport's <class_Viewport>` :ref:`ViewportTexture <class_ViewportTexture>` somewhere.
|
|
This can be requested via code using (for example):
|
|
This can be requested via code using (for example):
|
|
|
|
|
|
::
|
|
::
|
|
|
|
|
|
- #This gets us the render_target texture
|
|
|
|
|
|
+ #This gets us the ViewportTexture
|
|
var rtt = viewport.get_texture()
|
|
var rtt = viewport.get_texture()
|
|
sprite.texture = rtt
|
|
sprite.texture = rtt
|
|
|
|
|
|
-By default, re-rendering of the render target happens when the render
|
|
|
|
-target texture has been drawn in a frame. If visible, it will be
|
|
|
|
|
|
+Or it can be assigned in the editor by selecting "New ViewportTexture"
|
|
|
|
+
|
|
|
|
+.. image:: img/texturemenu.png
|
|
|
|
+
|
|
|
|
+and then selecting the :ref:`Viewport <class_Viewport>` you want to use.
|
|
|
|
+
|
|
|
|
+.. image:: img/texturepath.png
|
|
|
|
+
|
|
|
|
+Every frame the :ref:`Viewport <class_Viewport>`'s texture is cleared away with the default clear color (or a transparent
|
|
|
|
+color if Transparent BG is set to true). This can be changed by setting Clear Mode to Never or Next Frame.
|
|
|
|
+As the name implies, Never means the texture will never be cleared while next frame will
|
|
|
|
+clear the texture on the next frame and then set itself to Never.
|
|
|
|
+
|
|
|
|
+By default, re-rendering of the :ref:`Viewport <class_Viewport>` happens when the
|
|
|
|
+:ref:`Viewport <class_Viewport>`'s :ref:`ViewportTexture <class_ViewportTexture>` has been drawn in a frame. If visible, it will be
|
|
rendered, otherwise it will not. This behavior can be changed to manual
|
|
rendered, otherwise it will not. This behavior can be changed to manual
|
|
-rendering (once), or always render, no matter if visible or not.
|
|
|
|
|
|
+rendering (once), or always render, no matter if visible or not. This flexibility
|
|
|
|
+allows users to render an image once and then use the texture without
|
|
|
|
+incurring the cost of rendering every frame.
|
|
|
|
|
|
-``TODO: Review the doc, change outdated and add more images.``
|
|
|
|
|
|
|
|
-Make sure to check the viewport demos! Viewport folder in the demos
|
|
|
|
|
|
+Make sure to check the Viewport demos! Viewport folder in the demos
|
|
archive available to download, or
|
|
archive available to download, or
|
|
https://github.com/godotengine/godot-demo-projects/tree/master/viewport
|
|
https://github.com/godotengine/godot-demo-projects/tree/master/viewport
|