diff --git a/tutorials/viewports/img/cameras.png b/tutorials/viewports/img/cameras.png new file mode 100644 index 000000000..969df4417 Binary files /dev/null and b/tutorials/viewports/img/cameras.png differ diff --git a/tutorials/viewports/img/container.png b/tutorials/viewports/img/container.png new file mode 100644 index 000000000..c98df2dc2 Binary files /dev/null and b/tutorials/viewports/img/container.png differ diff --git a/tutorials/viewports/img/default_scene.png b/tutorials/viewports/img/default_scene.png new file mode 100644 index 000000000..23f5905ea Binary files /dev/null and b/tutorials/viewports/img/default_scene.png differ diff --git a/tutorials/viewports/img/input.png b/tutorials/viewports/img/input.png new file mode 100644 index 000000000..9acae21e3 Binary files /dev/null and b/tutorials/viewports/img/input.png differ diff --git a/tutorials/viewports/img/overdraw.png b/tutorials/viewports/img/overdraw.png new file mode 100644 index 000000000..16b834344 Binary files /dev/null and b/tutorials/viewports/img/overdraw.png differ diff --git a/tutorials/viewports/img/subviewport.png b/tutorials/viewports/img/subviewport.png deleted file mode 100644 index de26e0601..000000000 Binary files a/tutorials/viewports/img/subviewport.png and /dev/null differ diff --git a/tutorials/viewports/img/texturemenu.png b/tutorials/viewports/img/texturemenu.png new file mode 100644 index 000000000..059b3356e Binary files /dev/null and b/tutorials/viewports/img/texturemenu.png differ diff --git a/tutorials/viewports/img/texturepath.png b/tutorials/viewports/img/texturepath.png new file mode 100644 index 000000000..8dd5209ab Binary files /dev/null and b/tutorials/viewports/img/texturepath.png differ diff --git a/tutorials/viewports/img/unshaded.png b/tutorials/viewports/img/unshaded.png new file mode 100644 index 000000000..8da033502 Binary files /dev/null and b/tutorials/viewports/img/unshaded.png differ diff --git a/tutorials/viewports/viewports.rst b/tutorials/viewports/viewports.rst index a21b31877..ec5eb5b13 100644 --- a/tutorials/viewports/viewports.rst +++ b/tutorials/viewports/viewports.rst @@ -6,63 +6,73 @@ Viewports 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 ` node. +Think of :ref:`Viewports ` 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 `. .. 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 `. -- **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 `. +:ref:`Viewports ` can also be added to the scene so that there +are multiple surfaces to draw on. When we are drawing to a :ref:`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 `. +By using a :ref:`Viewport ` as a render target +we can either render multiple scenes simultaneously or we can render to +a :ref:`texture ` which is applied to an object in the scene, for example a dynamic +skybox. + +:ref:`Viewports ` 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 ----- -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() ` function if needed. +:ref:`Viewports ` 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 ` in the tree, but you can set :ref:`Viewports ` to not recieve input by checking +'Disable Input' to 'on', this will allow the next nearest :ref:`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`. Listener -------- 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`. For this type of sound to be +audible, the :ref:`Viewport ` needs to be enabled as a listener (for 2D or 3D). +If you are using a custom :ref:`Viewport ` to display your :ref:`World `, don't forget to enable this! Cameras (2D & 3D) ----------------- -When using a 2D or 3D :ref:`Camera ` / +When using a :ref:`Camera ` / :ref:`Camera2D `, cameras will always display on the -closest parent viewport (going towards the root). For example, in the +closest parent :ref:`Viewport ` (going towards the root). For example, in the following hierarchy: -- Viewport +.. image:: img/cameras.png - - Camera +CameraA will display on the Root :ref:`Viewport ` and it will draw MeshA. CameraB +will be captured by the :ref:`Viewport ` Node along with MeshB. Even though MeshB is in the scene +heirarchy, it will still not be drawn to the Root :ref:`Viewport `. Similarly MeshA will not +be visible from the :ref:`Viewport ` node becuase :ref:`Viewport ` nodes only capture nodes below them +in the heirarchy. -Camera will display on the parent viewport, but in the following one: - -- Camera - - - Viewport - -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 `, so if there is more than one, make sure that the desired one has the "current" property set, or make it the current camera by calling: @@ -73,60 +83,60 @@ or make it the current camera by calling: 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 ` have a "size" property which represents the size of the :ref:`Viewport ` +in pixels. For :ref:`Viewports ` which are children of :ref:`ViewportContainers `, +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 ` resolution +different than the one specified in size, by calling: :: viewport.set_size_override(w, h) # custom size for 2D 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 ` uses this for the stretch options in the project +settings. For more information on scaling and stretching visit the :ref:`Multiple Resolutions Tutorial ` Worlds ------ -For 3D, a Viewport will contain a :ref:`World `. This +For 3D, a :ref:`Viewport ` will contain a :ref:`World `. This 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 ` of the closest +:ref:`Viewport `. By default, newly created :ref:`Viewports ` do not contain a :ref:`World ` but +use the same as their parent :ref:`Viewport ` (root :ref:`Viewport ` always contains a +:ref:`World `, which is the one objects are rendered to by default). A :ref:`World ` can +be set in a :ref:`Viewport ` using the "world" property, and that will separate +all children nodes of that :ref:`Viewport ` from interacting with the parent +:ref:`Viewport's ` :ref:`World `. This is especially useful in scenarios where, for example, you might want to show a separate character in 3D imposed over 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 ` that +display single objects and don't want to create a :ref:`World `, :ref:`Viewport ` has +the option to use its own :ref:`World `. This is useful when you want to +instance 3D characters or objects in a 2D :ref:`World `. -For 2D, each Viewport always contains its own :ref:`World2D `. +For 2D, each :ref:`Viewport ` always contains its own :ref:`World2D `. 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 ` :ref:`World2D ` manually. + +For an example of how this works see the demo projects `3D in 2D `_ and `2D in 3D `_ respectively. 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 ` contents. For the root +:ref:`Viewport ` this is effectively a screen capture. This is done with the +following code: :: # Retrieve the captured Image using 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() # Convert Image to ImageTexture var tex = ImageTexture.new() @@ -134,7 +144,7 @@ following API: # Set Sprite Texture $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 ` initialization you will get an empty texture cause there is nothing to get as texture. You can deal with it using (for example): @@ -146,45 +156,92 @@ it using (for example): # You can get the image after this 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 `_ in the demo projects -Sub-viewport ------------- +Viewport Container +------------------ -If the viewport is a child of a :ref:`ViewportContainer `, it will become active and -display anything it has inside. The layout is something like this: +If the :ref:`Viewport ` is a child of a :ref:`ViewportContainer `, it will become active and +display anything it has inside. The layout looks like this: -- ViewportContainer - - - Viewport +.. image:: img/container.png -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. +The :ref:`Viewport ` will cover the area of its parent :ref:`ViewportContainer ` completely +if stretch is set to true in :ref:`ViewportContainer `. +Note: The size of the :ref:`ViewportContainer ` cannot be smaller than the size of the :ref:`Viewport `. -.. image:: img/subviewport.png +Rendering +--------- + +Due to the fact that the :ref:`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 `, the default behavior is DISABLED. +You can also set the :ref:`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. + +If you know how the :ref:`Viewport ` is going to be used, you can set its Usage to either 3D or 2D. Godot will then +restrict how the :ref:`Viewport ` is drawn to in accordance with your choice, default is 3D. + +Godot also provides a way of customizing how everything is drawn inside :ref:`Viewports ` using “Debug Draw”. +Debug Draw allows you to specify one of four options for how the :ref:`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 ------------- -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 ` whatever is inside will not be +visible in the scene editor. To display the contents, you have to draw the :ref:`Viewport's ` :ref:`ViewportTexture ` somewhere. 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() 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 ` you want to use. + +.. image:: img/texturepath.png + +Every frame the :ref:`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 ` happens when the +:ref:`Viewport `'s :ref:`ViewportTexture ` has been drawn in a frame. If visible, it will be 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 https://github.com/godotengine/godot-demo-projects/tree/master/viewport