Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
Usando Viewports
Introdução
Pense em um Viewport como uma tela na qual o jogo é projetado. Para ver o jogo, precisamos ter uma superfície na qual desenhá-lo. Essa superfície é o Viewport Raiz (Root Viewport).
SubViewports são um tipo de Viewport que pode ser adicionado à cena para que existam múltiplas superfícies para desenhar. Quando estamos desenhando para uma SubViewport, chamamos isso de render target (destino de renderização). Podemos acessar o conteúdo de um render target acessando sua textura correspondente. Usando uma SubViewport como render target, podemos renderizar múltiplas cenas simultaneamente ou podemos renderizar para uma ViewportTexture que é aplicada a um objeto na cena, por exemplo, um skybox dinâmico.
Os SubViewports têm uma variedade de casos de uso, incluindo:
Renderização de objetos 3D em um jogo 2D
Renderização de elementos 2D em um jogo 3D
Renderização de texturas dinâmicas
Geração de texturas procedurais durante a execução
Renderização de várias câmeras na mesma cena
O que todos esses casos de uso têm em comum é que você tem a capacidade de desenhar objetos em uma textura como se fosse outra tela e pode então escolher o que fazer com a textura resultante.
Outro tipo de Viewport no Godot são as Windows (Janelas). Elas permitem que seu conteúdo seja projetado em uma janela. Embora o Viewport Raiz seja uma Window, elas são menos flexíveis. Se você quiser usar a textura de um Viewport, trabalhará com SubViewports na maioria das vezes.
Entrada
Os Viewports também são responsáveis por entregar eventos de entrada devidamente ajustados e dimensionados para seus nós filhos. Por padrão, os SubViewports não recebem entrada automaticamente, a menos que a recebam de seu nó pai direto SubViewportContainer. Neste caso, a entrada pode ser desativada com a propriedade Disable Input.
Para mais informações sobre como o Godot lida com entradas, leia o Tutorial de Eventos de Entrada.
Ouvinte (Listener)
O Godot suporta som 3D (tanto em nós 2D quanto 3D). Mais sobre isso pode ser encontrado no Tutorial de Audio Streams. Para que esse tipo de som seja audível, o Viewport precisa estar ativado como um ouvinte (listener) (para 2D ou 3D). Se você estiver usando um SubViewport para exibir seu World3D ou World2D, não se esqueça de ativar isso!
Câmeras (2D e 3D)
Ao usar uma Camera3D ou Camera2D, ela sempre será exibida no Viewport pai mais próximo (indo em direção à raiz). Por exemplo, na seguinte hierarquia:
A CameraA será exibida no Viewport Raiz e desenhará o MeshA. A CameraB será capturada pelo SubViewport junto com o MeshB. Mesmo que o MeshB esteja na hierarquia da cena, ele ainda não será desenhado no Viewport Raiz. Da mesma forma, o MeshA não estará visível a partir do SubViewport, porque os SubViewports apenas capturam nós abaixo deles na hierarquia.
Só pode haver uma câmera ativa por Viewport, então se houver mais de uma, certifique-se de que a desejada esteja com a propriedade current definida, ou torne-a a câmera atual chamando:
camera.make_current()
camera.MakeCurrent();
Por padrão, as câmeras renderizarão todos os objetos em seu mundo. Em 3D, as câmeras podem usar sua propriedade cull_mask combinada com a propriedade de camada do VisualInstance3D para restringir quais objetos são renderizados.
Escala e alongamento
Os SubViewports possuem uma propriedade size, que representa o tamanho do SubViewport em pixels. Para SubViewports que são filhos de SubViewportContainers, esses valores são substituídos, mas para todos os outros, isso define sua resolução.
Também é possível dimensionar o conteúdo 2D e fazer com que a resolução do SubViewport seja diferente da especificada no tamanho, chamando:
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.
subViewport.Size2DOverride = new Vector2I(width, height); // Custom size for 2D.
subViewport.Size2DOverrideStretch = true; // Enable stretch for custom size.
Para informações sobre redimensionamento e esticamento com o Viewport Raiz, visite o Tutorial de Múltiplas Resoluções
Mundos
Para 3D, um Viewport conterá um World3D. Este é basicamente o universo que vincula a física e a renderização. Nós baseados em Node3D se registrarão usando o World3D do Viewport mais próximo. Por padrão, Viewports recém-criados não contêm um World3D, mas usam o mesmo do Viewport pai. O Viewport Raiz sempre contém um World3D, que é aquele para o qual os objetos são renderizados por padrão.
Um World3D pode ser definido em um Viewport usando a propriedade World 3D, o que separará todos os nós filhos deste Viewport e os impedirá de interagir com o World3D do Viewport pai. Isso é especialmente útil em cenários onde, por exemplo, você queira mostrar um personagem separado em 3D sobreposto ao jogo (como em StarCraft).
As a helper for situations where you want to create Viewports that display single objects and don't want to create a World3D, Viewport has the option to use its Own World3D. This is useful when you want to instantiate 3D characters or objects in World2D.
Para 2D, cada Viewport sempre contém seu próprio World2D. Isso basta na maioria dos casos, mas caso deseje compartilhá-los, é possível fazê-lo definindo world_2d no Viewport por meio de código.
Para um exemplo de como isso funciona, veja os projetos de demonstração 3D in 2D e 2D in 3D, respectivamente.
Captura
É possível solicitar uma captura dos conteúdos do Viewport. Para o Viewport Raiz, isso é efetivamente uma captura de tela. Isso é feito com o seguinte código:
# 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
// Retrieve the captured Image using get_image().
var img = GetViewport().GetTexture().GetImage();
// Convert Image to ImageTexture.
var tex = ImageTexture.CreateFromImage(img);
// Set sprite texture.
sprite.Texture = tex;
Mas se você usar isso no _ready() ou a partir do primeiro quadro da inicialização do Viewport, obterá uma textura vazia porque não há nada para capturar como textura. Você pode lidar com isso usando (por exemplo):
# Wait until the frame has finished before getting the texture.
await RenderingServer.frame_post_draw
# You can get the image after this.
// Wait until the frame has finished before getting the texture.
await ToSignal(RenderingServer.Singleton, RenderingServer.SignalName.FramePostDraw);
// You can get the image after this.
Viewport Container
Se o SubViewport for filho de um SubViewportContainer, ele se tornará ativo e exibirá o que tiver dentro. A estrutura se parece com isto:
O SubViewport cobrirá totalmente a área do seu SubViewportContainer pai se Stretch estiver definido como true no SubViewportContainer.
Nota
O tamanho do SubViewportContainer não pode ser menor do que o tamanho do SubViewport.
Renderização
Devido ao fato de o Viewport ser uma porta de entrada para outra superfície de renderização, ele expõe algumas propriedades de renderização que podem ser diferentes das configurações do projeto. Você pode optar por usar um nível diferente de MSAA para cada Viewport. O comportamento padrão é Disabled.
Se você sabe que o Viewport só será usado para 2D, você pode Desativar o 3D. O Godot irá então restringir como o Viewport é desenhado. Desativar o 3D é um pouco mais rápido e usa menos memória em comparação com o 3D ativado. É uma boa ideia desativar o 3D se o seu viewport não renderizar nada em 3D.
Nota
Se precisar renderizar sombras 3D no viewport, certifique-se de definir a propriedade positional_shadow_atlas_size do viewport para um valor maior que 0. Caso contrário, as sombras não serão renderizadas. Por padrão, a configuração equivalente do projeto é definida como 4096 em plataformas de desktop e 2048 em plataformas móveis.
O Godot também oferece uma maneira de customizar como tudo é desenhado dentro dos Viewports usando o Debug Draw. O Debug Draw permite especificar um modo que determina como o Viewport exibirá as coisas desenhadas dentro dele. O Debug Draw é Disabled por padrão. Algumas outras opções são Unshaded, Overdraw e Wireframe. Para uma lista completa, consulte a Documentação do Viewport.
Debug Draw = Disabled (padrão): A cena é desenhada normalmente.
Debug Draw = Unshaded: O Unshaded desenha a cena sem usar informações de iluminação, de modo que todos os objetos aparecem com cores planas em sua cor de albedo.
Debug Draw = Overdraw: O Overdraw desenha as malhas de forma semitransparente com uma mistura aditiva para que você possa ver como as malhas se sobrepõem.
Debug Draw = Wireframe: O Wireframe desenha a cena usando apenas as arestas dos triângulos nas malhas.
Nota
Os modos de Debug Draw atualmente não são suportados ao usar o método de renderização Compatibility. Eles aparecerão como modos de desenho normais.
Destino da renderização
Ao renderizar para um SubViewport, o que quer que esteja dentro não estará visível no editor de cena. Para exibir o conteúdo, você deve desenhar a ViewportTexture do SubViewport em algum lugar. Isso pode ser solicitado via código usando (por exemplo):
# This gives us the ViewportTexture.
var tex = viewport.get_texture()
sprite.texture = tex
// This gives us the ViewportTexture.
var tex = viewport.GetTexture();
sprite.Texture = tex;
Ou pode ser atribuído no editor selecionando "New ViewportTexture"
e então selecionando o Viewport que você deseja usar.
A cada quadro, a textura do Viewport é limpa com a cor de limpeza padrão (or uma cor transparente se Transparent BG estiver definido como true). Isso pode ser alterado definindo o Clear Mode para Never ou Next Frame. Como o nome indica, Never significa que a textura nunca será limpa, enquanto o next frame limpará a textura no próximo quadro e depois se definirá como Never.
Por padrão, a renderização do SubViewport acontece quando sua ViewportTexture foi desenhada em um quadro. Se visível, ela será renderizada, caso contrário, não será. Este comportamento pode ser alterado definindo o Update Mode para Never, Once, Always ou When Parent Visible. Never e Always nunca ou sempre renderizarão novamente, respectivamente. Once renderizará novamente no próximo quadro e mudará para Never depois. Isso pode ser usado para atualizar manualmente o Viewport. Essa flexibilidade permite que os usuários renderizem uma imagem uma vez e depois usem a textura sem incorrer no custo de renderização a cada quadro.
Nota
Certifique-se de verificar as demonstrações de Viewport. Elas estão disponíveis na pasta viewport do arquivo de demonstrações, ou em https://github.com/godotengine/godot-demo-projects/tree/master/viewport.