Usando Viewports

Introducción

Piensa en las Viewports como una pantalla en la que se proyecta el juego. Para ver el juego necesitamos tener una superficie sobre la que dibujarlo, esta superficie es el Root :ref:`Viewport <class_Viewport>`(nodo raíz).

../../_images/viewportnode.png

Los Viewports también se puede añadir a la escena para que haya múltiples superficies sobre las que dibujar. Cuando estamos dibujando a un Viewport que no es el Root lo llamamos un render target(objetivo de renderizado). Podemos acceder al contenido de un render target accediendo a su correspondiente Texture. Usando un Viewport como objetivo de render podemos renderizar múltiples escenas simultáneamente o podemos renderizar a una Texture que se aplica a un objeto de la escena, por ejemplo un skybox dinámico.

Los Viewports tienen una variedad de casos de uso, incluyendo:

  • Renderización de objetos 3D dentro de un juego 2D

  • Renderizar elementos 2D en un juego 3D

  • Renderizado de texturas dinámicas

  • Generación de texturas de procedimiento en tiempo de ejecución

  • Renderizado de varias cámaras en la misma escena

Lo que todos estos casos de uso tienen en común es que se da la capacidad de dibujar objetos a una textura como si fuera otra pantalla y luego puedes elegir qué hacer con la textura resultante.

Entrada

Los Viewports son también responsables de entregar eventos de entrada correctamente ajustados y escalados a todos sus nodos hijos. Típicamente la entrada es recibida por el Viewport más cercano en el árbol, pero puedes establecer Viewports para que no reciba entradas al marcar 'Disable Input' en activado, esto permitirá que el siguiente Viewport más cercano en el árbol capture la entrada.

../../_images/input.png

Para más información sobre cómo maneja Godot las entradas, por favor lee el Tutorial de Eventos de Entrada.

Oyente

Godot soporta el sonido 3D (tanto en nodos 2D como 3D); más sobre esto se puede encontrar en el Audio Streams Tutorial. Para que este tipo de sonido sea audible, el Viewport debe estar habilitado como oyente (para 2D o 3D). Si estás usando un Viewport personalizado para mostrar tu World, ¡no te olvides de habilitarlo!

Cámaras (2D y 3D)

Cuando se usa una Camera / Camera2D, las cámaras siempre se mostrarán en el padre más cercano Viewport (yendo hacia la raíz). Por ejemplo, en la siguiente jerarquía:

../../_images/cameras.png

La cámaraA aparecerá en la raíz Viewport y dibujará MeshA. La cámaraB será capturada por el nodo Viewport junto con MeshB. Aunque MeshB está en la jerarquía de la escena, no será dibujada en el Root Viewport. Del mismo modo, MeshA no será visible desde el nodo Viewport porque los nodos Viewport sólo capturan los nodos que están debajo de ellos en la jerarquía.

Sólo puede haber una cámara activa por Viewport, así que si hay más de una, asegúrate de que la deseada tiene la propiedad "actual" establecida, o hazla la cámara actual llamando:

camera.make_current()

Por defecto, las cámaras renderizarán todos los objetos de su mundo. En 3D, las cámaras pueden usar su propiedad cull_mask combinada con la propiedad VisualInstance's layer para restringir qué objetos se renderizan.

Escalado y estiramiento

El Viewport tiene una propiedad "size", la que representa el tamaño del Viewport en pixeles. Para Viewport que son hijos de un ref:ViewportContainer <class_viewportcontainer>, esos valores son sobreescritos pero esto define su resolución.

También es posible escalar el contenido 2D y hacer que la resolución Viewport sea diferente de la especificada en el tamaño, llamando:

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

La raíz Viewport utiliza esto para las opciones de estiramiento en la configuración del proyecto. Para más información sobre escalado y estiramiento visite el Tutorial de Múltiples Resoluciones Multiple Resolutions Tutorial

Mundos

Para 3D, un Viewport contendrá un World. Este es básicamente el universo que une la física y la representación juntos. Los nodos de base espacial se registrarán usando el World del Viewport más cercano. Por defecto, los Viewports recién creados no contienen un World sino que usan el mismo que su padre Viewport (la raíz Viewport siempre contiene un World, que es al que se renderizan los objetos por defecto). Un World puede establecerse en un Viewport usando la propiedad "world", y eso separará a todos los nodos hijos de ese Viewport de la interacción con el padre Viewport's World. Esto es especialmente útil en escenarios donde, por ejemplo, podrías querer mostrar un personaje separado en 3D impuesto sobre el juego (como en StarCraft).

Como ayudante para situaciones en las que se quiera crear Viewports que muestren objetos individuales y no se quiera crear un World, Viewport tiene la opción de usar su propio World. Esto es muy útil cuando se desea crear personajes u objetos 3D en un 2D World.

Para 2D, cada Viewport siempre contiene su propio World2D. Esto es suficiente en la mayoría de los casos, pero en caso de que se desee compartirlo, es posible hacerlo configurando el Viewport's World2D manualmente.

Para un ejemplo de cómo funciona esto, ver los proyectos de demostración 3D en 2D y 2D en 3D respectivamente.

Captura

Es posible consultar una captura del contenido de Viewport. Para la raíz Viewport, esto es efectivamente una captura de pantalla. Esto se hace con el siguiente código:

# 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

Pero si usas esto en _ready() o desde el primer fotograma de la inicialización Viewport's, obtendrás una textura vacía porque no hay nada que obtener como textura. Puedes tratarlo usando (por ejemplo):

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

Contenedor del Viewport

Si el Viewport es hijo de un ViewportContainer, se activará y mostrará todo lo que tenga dentro. El diseño se ve así:

../../_images/container.png

El Viewport abarcará completamente el área de su padre ViewportContainer si Stretch está ajustado a true en ViewportContainer. Nota: El tamaño del ViewportContainer no puede ser menor que el tamaño del Viewport.

Renderización

Debido al hecho de que el Viewport es una entrada a otra superficie de renderizado, expone unas cuantas propiedades de renderizado que pueden ser diferentes de la configuración del proyecto. La primera es MSAA; puedes elegir usar un nivel diferente de MSAA para cada Viewport; el comportamiento por defecto es DISABLED. También puedes establecer el Viewport para usar HDR, HDR es muy útil para cuando quieras almacenar valores en la textura que estén fuera del rango 0.0 - 1.0.

Si sabes cómo se va a usar el Viewport, puedes establecer su uso en 3D o 2D. Godot restringirá entonces cómo se dibuja el Viewport de acuerdo a tu elección; por defecto es 3D. El modo de uso 2D es ligeramente más rápido y utiliza menos memoria en comparación con el 3D. Es una buena idea establecer la propiedad de uso de Viewport a 2D si tu viewport no renderiza nada en 3D.

Nota

Si necesitas renderizar las sombras 3D en la ventana, asegúrate de configurar la propiedad Shadow Atlas Size de la ventana a un valor superior a 0. De lo contrario, las sombras no se renderizarán. Como referencia, la Configuración del proyecto lo define a 4096 por defecto.

Godot también proporciona una forma de personalizar cómo se dibuja todo dentro Viewports usando "Debug Draw". Debug Draw permite especificar una de las cuatro opciones de cómo el Viewport mostrará las cosas dibujadas dentro de él. Debug Draw está desactivado por defecto.

../../_images/default_scene.png

Una escena dibujada con Debug Draw desactivado

Las otras tres opciones son sin sombra, sobregirado y alambrado. Unshaded dibuja la escena sin usar la información de la iluminación, así que todos los objetos aparecen coloreados de forma plana del color de su albedo.

../../_images/unshaded.png

La misma escena con Debug Draw ajustada a Unshaded

El sobredimensionamiento dibuja las mallas semitransparentes con una mezcla de aditivos para poder ver cómo se superponen las mallas.

../../_images/overdraw.png

La misma escena con Debug Draw puesta en Overdraw

Por último, Wireframe dibuja la escena usando sólo los bordes de los triángulos en las mallas.

Nota

Los efectos del modo Wireframe sólo son visibles en el editor, no mientras el proyecto está en marcha.

Renderizar el objetivo

Al renderizar a un Viewport, lo que esté dentro no será visible en el editor de escenas. Para mostrar el contenido, tienes que dibujar el Viewport's ViewportTexture en algún lugar. Esto se puede solicitar mediante un código usando (por ejemplo):

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

O se puede asignar en el editor seleccionando "New ViewportTexture"

../../_images/texturemenu.png

y luego seleccionando el Viewport que quieres usar.

../../_images/texturepath.png

Cada cuadro, la textura de Viewport se borra con el color claro por defecto (o un color transparente si Transparent Bg se establece en true). Esto se puede cambiar poniendo Clear Mode en Never o Next Frame. Como su nombre lo indica, Never significa que la textura nunca se borrará, mientras que el siguiente cuadro borrará la textura en el siguiente cuadro y luego se establecerá en Never.

Por defecto, la renderización de Viewport ocurre cuando el Viewport's ViewportTexture ha sido dibujado en un marco. Si es visible, se renderizará; de lo contrario, no lo hará. Este comportamiento puede cambiarse a renderizado manual (una vez), o siempre renderizado, sin importar si es visible o no. Esta flexibilidad permite a los usuarios renderizar una imagen una vez y luego usar la textura sin incurrir en el costo de renderizar cada fotograma.

¡Asegúrate de revisar las demos de Viewport! Carpeta Viewport en el archivo de demos disponible para descargar, o https://github.com/godotengine/godot-demo-projects/tree/master/viewport