Luzes 2D e sombras
Introdução
Por padrão, cenas 2D no Godot são não iluminadas, sem luzes nem sombras visíveis. Embora isso seja rápido para renderizar, cenas não iluminadas podem parecer sem graça. O Godot oferece a capacidade de usar iluminação e sombras 2D em tempo real, o que pode melhorar muito a sensação de profundidade em seu projeto.
Sem luzes 2D ou sombras, a cena não tem sombras
2D lights enabled (without shadows)
2D lights and shadows enabled
Nós
Existem vários nós envolvidos em uma configuração completa de iluminação 2D:
CanvasModulate (to darken the rest of the scene)
PointLight2D (para luzes omnidirecionais ou spot)
DirectionalLight2D (para luz solar ou luz da lua)
LightOccluder2D (for light shadow casters)
Outros nós 2D que recebem iluminação, como Sprite2D ou TileMapLayer.
CanvasModulate é usado para escurecer a cena especificando uma cor que atuará como a cor "ambiente" base. Esta é a cor final da iluminação nas áreas que não são atingidas por nenhuma luz 2D. Sem um nó CanvasModulate, a cena final pareceria muito clara, pois as luzes 2D somente clareariam a aparência não iluminada existente (que parece totalmente iluminada).
Sprite2Ds are used to display the textures for the light blobs, the background, and for the shadow casters.
PointLight2Ds are used to light the scene. The way a light typically works is by adding a selected texture over the rest of the scene to simulate lighting.
LightOccluder2Ds are used to tell the shader which parts of the scene cast shadows. These occluders can be placed as independent nodes or can be part of a TileMapLayer node.
The shadows appear only on areas covered by the PointLight2D and their direction is based on the center of the Light.
Nota
A cor de fundo não recebe iluminação. Se você quiser que a luz incida sobre o fundo, precisará adicionar uma representação visual para ele, como um Sprite2D.
As propriedades de Região do Sprite2D podem ser úteis para criar rapidamente uma textura de fundo repetitiva, mas lembre-se também de definir Textura > Repetir como Ativado nas propriedades do Sprite2D.
Point lights
Luzes pontuais (também chamadas de luzes posicionais) são os elementos mais comuns na iluminação 2D. Luzes pontuais podem ser usadas para representar a luz de tochas, fogo, projéteis, etc.
O PointLight2D oferece as seguintes propriedades para ajustes no inspetor:
Textura: A textura a ser usada como fonte de luz. A dimensão da textura determina o tamanho da luz. A textura pode ter um canal alfa, o que é útil ao usar o modo de mesclagem Mistura do Light2D, mas não é necessário se usar os modos de mesclagem Adicionar (padrão) ou Subtrair.
Deslocamento: O deslocamento da textura de luz. Ao contrário de quando você move o nó de luz, alterar o deslocamento não faz com que as sombras se movam.
Escala de Textura: O multiplicador para o tamanho da luz. Valores mais altos farão com que a luz se estenda mais. Luzes maiores têm um custo de desempenho maior, ao afetarem mais pixels na tela, portanto, considere isso antes de aumentar o tamanho de uma luz.
Altura: A altura virtual da luz em relação ao mapeamento normal. Por padrão, a luz está muito próxima das superfícies que recebem iluminação. Isso fará com que a iluminação seja pouco visível se o mapeamento normal for usado, então considere aumentar esse valor. Ajustar a altura da luz faz diferença visível apenas em superfícies que utilizam mapeamento normal.
Se você não tiver uma textura pronta para usar em uma luz, pode usar esta textura de luz pontual "neutra" (clique com o botão direito > Salvar imagem como…):
Neutral point light texture
Se precisar de um fator de degradação da luz (falloff) diferente, você pode criar uma textura proceduralmente atribuindo uma Nova Textura de Gradiente2D à propriedade Textura da luz. Após criar o recurso, expanda a seção Preenchimento e defina o modo de preenchimento como Radial. Em seguida, você terá que ajustar o gradiente para começar do branco opaco ao branco transparente e mover sua posição inicial para o centro.
Directional light (Luz direcional)
Novo no Godot 4.0 é a capacidade de ter iluminação direcional em 2D. A iluminação direcional é usada para representar a luz do sol ou da lua. Os raios de luz são projetados paralelamente entre si, como se o sol ou a lua estivesse infinitamente distante da superfície que recebe a luz.
DirectionalLight2D offers the following properties:
Altura: A altura virtual da luz em relação ao mapeamento normal (
0.0= paralela às superfícies,1.0= perpendicular às superfícies). Por padrão, a luz está totalmente paralela às superfícies que recebem iluminação. Isso fará com que a iluminação seja pouco visível se o mapeamento normal for usado, então considere aumentar esse valor. Ajustar a altura da luz faz diferença visual somente em superfícies que utilizam mapeamento normal. Altura não afeta a aparência das sombras.Distância Máxima: A distância máxima do centro da câmera que os objetos podem estar antes que suas sombras sejam ocultadas (em pixels). Diminuir esse valor pode evitar que objetos localizados fora da câmera projetem sombras (além de melhorar o desempenho). O zoom da Camera2D não é levado em conta pela Distância Máxima, o que significa que, em valores de zoom mais altos, as sombras parecerão desaparecer mais rapidamente ao aproximar o zoom em um ponto específico.
Nota
Sombras direcionais sempre parecerão infinitamente longas, independentemente do valor da propriedade Altura. Essa é uma limitação do método de renderização de sombras usado para luzes 2D no Godot.
Para que as sombras direcionais não sejam infinitamente longas, você deve desabilitar as sombras no DirectionalLight2D e usar um shader personalizado que leia do campo de distância assinado 2D (signed distance field). Esse campo de distância é gerado automaticamente a partir dos nós LightOccluder2D presentes na cena.
Common light properties
Tanto o PointLight2D quanto o DirectionalLight2D oferecem propriedades comuns, que fazem parte da classe base Light2D:
Habilitado: Permite alternar a visibilidade da luz. Ao contrário de ocultar o nó da luz, desabilitar esta propriedade não ocultará os filhos da luz.
Somente Editor: Se habilitado, a luz só fica visível no editor. Ela será desativada automaticamente no projeto em execução.
Cor: A cor da luz.
Energia: Multiplicador de intensidade da luz. Valores mais altos resultam em uma luz mais brilhante.
Modo de Mesclagem: A fórmula de blend usada para os cálculos da luz. O padrão Adiciona é adequado para a maioria dos casos. Subtrair pode ser usado para luzes negativas, que não são fisicamente precisas, mas podem ser usadas para efeitos especiais. O modo de mistura Misturar mistura o valor dos pixels correspondentes à textura da luz com os valores dos pixels abaixo dela por interpolação linear.
Intervalo > Z Min: O menor índice Z afetado pela luz.
Intervalo> Z Máx.: O maior índice Z afetado pela luz.
Intervalo> Layer Mín.: A camada visual mais baixa afetada pela luz.
Intervalo > Layer Máx.: A camada visual mais alta afetada pela luz.
Intervalo > Máscara Seletiva de Item: controla quais nós recebem luz deste nó, dependendo das camadas visuais habilitadas dos outros nós, Máscara de Luz Oclusora. Isso pode ser usado para impedir que certos objetos recebam luz.
Setting up shadows
Após ativar a propriedade Sombra > Ativado em um nó PointLight2D ou DirectionalLight2D, você não verá nenhuma diferença visual inicialmente. Isso ocorre porque nenhum nó na sua cena possui occluders ainda, que são usados como base para a projeção de sombras.
Para que as sombras apareçam na cena, os nós LightOccluder2D devem ser adicionados à cena. Esses nós também devem ter polígonos de oclusão projetados para corresponder ao contorno do sprite.
Junto com o recurso de polígono (que deve ser definido para ter qualquer efeito visual), os nós LightOccluder2D têm duas propriedades:
Colisão SDF: Se ativado, o ocluder fará parte de um Campo de Distância com Sinal gerado em tempo real que pode ser usado em shaders personalizados. Quando não se utiliza shaders personalizados que leem deste SDF, ativar essa opção não faz diferença visual nem causa custo de desempenho; por isso, está ativada por padrão para conveniência.
Máscara de Luz do Ocluder: Essa máscara é usada em conjunto com a propriedade Sombra > Máscara de Projeção de Elemento do PointLight2D e DirectionalLight2D para controlar quais objetos projetam sombras para cada luz. Isso pode ser usado para impedir que objetos específicos projetem sombras.
There are two ways to create light occluders:
Geração automática de um oclusor de luz
Os oclusores podem ser criados automaticamente a partir de nós Sprite2D selecionando o nó, clicando no menu Sprite2D na parte superior do editor 2D e escolhendo Criar LightOccluder2D Irmão.
Na caixa de diálogo exibida, um contorno envolverá as bordas do sprite. Se o contorno corresponder perfeitamente às bordas do sprite, você poderá clicar em OK. Se o contorno estiver muito distante das bordas do sprite (ou estiver “comendo” as bordas do sprite), ajuste Crescer (pixels) e Reduzir (pixels) e, em seguida, clique em Atualizar Visualização. Repita essa operação até obter resultados satisfatórios.
Desenho manual de um oclusor de luz
Crie um nó LightOccluder2D, selecione o nó e clique no botão “+” na parte superior do editor 2D. Quando solicitado a criar um recurso de polígono, responda Sim. Em seguida, você pode começar a desenhar um polígono de oclusão clicando para criar novos pontos. Você pode remover os pontos existentes clicando com o botão direito do mouse sobre eles e pode criar novos pontos a partir da linha existente clicando na linha e arrastando-a.
As seguintes propriedades podem ser ajustadas em luzes 2D que tenham sombras ativadas:
Cor: A cor das áreas sombreadas. Por padrão, as áreas sombreadas são totalmente pretas, mas isso pode ser alterado para fins artísticos. O canal alfa da cor controla o quanto a sombra é tingida pela cor especificada.
Filtro: O modo de filtro a ser usado para sombras. O padrão Nenhum é o mais rápido de renderizar, sendo adequado para jogos com estética de pixel art (devido ao seu visual “em blocos”). Se você quiser uma sombra suave, use PCF5. O PCF13 é ainda mais suave, mas é o mais exigente para renderização. O PCF13 só deve ser usado para algumas luzes de uma vez devido ao seu alto custo de renderização.
Filtro Suavizador: Controla o grau de suavização aplicado às sombras quando o Filtro é definido como PCF5 ou PCF13. Valores mais altos resultam em uma sombra mais suave, mas podem causar artefatos de faixas visíveis (especialmente com PCF5).
Item de Máscara seletiva: Controla quais nós LightOccluder2D projetam sombras, dependendo de suas respectivas propriedades Occluder Light Mask.
Hard shadows
Sombras suaves (PCF13, filtro Smooth 1.5)
Sombras suaves com artefatos de listras devido à suavidade do filtro ser muito alta (PCF5, suavidade do filtro 4)
Mapas normais e especulares
Os mapas normais e os mapas especulares podem melhorar muito a sensação de profundidade da iluminação 2D. Semelhante ao modo como funcionam na renderização 3D, os mapas normais podem ajudar a tornar a iluminação menos plana, variando sua intensidade conforme a direção da superfície que recebe a luz (em uma base por pixel). Os mapas especulares ajudam a melhorar ainda mais os visuais, fazendo com que parte da luz seja refletida de volta para o visualizador.
Tanto o PointLight2D quanto o DirectionalLight2D suportam mapeamento normal e mapeamento especular. Desde o Godot 4.0, os mapas normal e especular podem ser atribuídos a qualquer elemento 2D, incluindo nós que herdam de Node2D ou Control.
Um mapa normal representa a direção para a qual cada pixel está “apontando”. Essas informações são usadas pela engine para aplicar corretamente a iluminação às superfícies 2D de uma forma fisicamente plausível. Normalmente, os mapas normais são criados a partir de mapas de altura pintados à mão, mas também podem ser gerados automaticamente a partir de outras texturas.
Um mapa especular define o quanto cada pixel deve refletir a luz (e em que cor, se o mapa especular contiver cor). Valores mais brilhantes resultarão em um reflexo mais brilhante em um determinado ponto da textura. Normalmente, os mapas especulares são criados com edição manual, usando a textura difusa como base.
Dica
Se você não tiver mapas normais ou especulares para seus sprites, poderá gerá-los usando a ferramenta gratuita e de código aberto Laigter.
Para configurar mapas normais e/ou mapas especulares em um nó 2D, crie um novo recurso CanvasTexture para a propriedade que desenha a textura do nó. Por exemplo, em um Sprite2D:
Criação de um recurso CanvasTexture para um nó Sprite2D
Expanda o recurso recém-criado. Você pode encontrar várias propriedades que precisará ajustar:
Difusa > Textura: A textura da cor base. Nessa propriedade, carregue a textura que você está usando para o sprite em si.
Mapa normal > Texture: A textura do mapa normal. Nessa propriedade, carregue uma textura de mapa normal que você gerou a partir de um mapa de altura (consulte a dica acima).
Especular > Textura: A textura do mapa especular, que controla a intensidade especular de cada pixel na textura difusa. O mapa especular geralmente é em escala de cinza, mas também pode conter cores para multiplicar a cor dos reflexos de acordo. Nessa propriedade, carregue uma textura de mapa especular que você tenha criado (consulte a dica acima).
Especular > Cor: O multiplicador de cores para reflexos especulares.
Especular > Brilho: O expoente especular a ser usado para reflexos. Valores mais baixos aumentam o brilho dos reflexos e os tornam mais difusos, enquanto valores mais altos fazem com que os reflexos fiquem mais localizados. Valores altos são mais adequados para superfícies com aparência molhada.
Textura > Filtro: Pode ser definido para sobrescrever o modo de filtragem da textura, independentemente da configuração da propriedade do nó (ou da configuração do projeto Renderização > Texturas > Texturas de Canvas > Filtro de Textura Padrão).
Textura > Repetição: Pode ser definido para sobrescrever o modo de repetição da textura, independentemente da configuração da propriedade do nó (ou da configuração do projeto Renderização > Texturas > Texturas de Canvas > Padrão de Repetição de Textura).
Após ativar o mapeamento normal, você poderá notar que suas luzes parecem estar mais fracas. Para resolver isso, aumente a propriedade Altura em seus nós PointLight2D e DirectionalLight2D. Talvez você também queira aumentar ligeiramente a propriedade Energia das luzes para se aproximar da intensidade da iluminação antes de ativar o mapeamento normal.
Uso de sprites aditivos como uma alternativa mais rápida às luzes 2D
Se você tiver problemas de desempenho ao usar luzes 2D, pode valer a pena substituir algumas delas por nós Sprite2D que usam mistura aditiva. Isso é particularmente adequado para efeitos dinâmicos de curta duração, como balas ou explosões.
Sprites aditivos são muito mais rápidos de renderizar, pois não precisam passar por um pipeline de renderização separado. Além disso, é possível usar essa abordagem com AnimatedSprite2D (ou Sprite2D + AnimationPlayer), permitindo a criação de "luzes" 2D animadas.
No entanto, os sprites aditivos têm algumas desvantagens em comparação com as luzes 2D:
A fórmula de mistura é imprecisa em comparação com a iluminação 2D “real”. Em geral, isso não é um problema em áreas suficientemente iluminadas, mas impede que os sprites aditivos iluminem corretamente áreas totalmente escuras.
Os sprites aditivos não podem projetar sombras, pois não são luzes.
Os sprites aditivos ignoram os mapas normais e especulares usados em outros sprites.
Para exibir um sprite com mistura aditiva, crie um nó Sprite2D e atribua uma textura a ele. No inspetor, role para baixo até a seção CanvasItem > Material, desdobre-a e clique no menu suspenso ao lado da propriedade Material. Escolha Novo CanvasItemMaterial, clique no material recém-criado para editá-lo e, em seguida, defina Modo de Mesclagem como Adicionar.