Como fazer - técnicas de luz e sombra 2D em URP
Saiba como as luzes e sombras na demonstração Happy Harvest foram criadas usando o Universal Render Pipeline (URP) no Unity 2022 LTS.
Happy Harvest é um exemplo de jogo de simulação agrícola 2D de cima para baixo. As técnicas deste artigo, além de muitas outras, são abordadas em detalhes no e-book Arte, animação e iluminação de jogos 2D para artistas.
Leia os outros artigos desta série para aprender como replicar os efeitos e visuais no Happy Harvest:
- Como animar personagens 2D no Unity 2022 LTS
- Como criar arte e jogabilidade com mapas de blocos 2D
- Efeitos especiais 2D com VFX Graph e Shader Graph (disponível em breve)
Baixeo Happy Harvest na Unity Asset Store hoje mesmo.
A iluminação 2D dinâmica pode mudar drasticamente o clima de um nível e melhorar a jogabilidade. Os exemplos incluem iluminar uma caverna com uma tocha, irradiar luz através de uma janela para destacar partículas de poeira cintilantes e, no caso de Happy Harvest, animar uma simulação do ciclo do dia para a noite.
O avançado sistema de iluminação dinâmica 2Ddo Unity, junto com texturas secundárias em seus sprites, pode fazer seus personagens se destacarem com iluminação de borda eficaz e detalhes claramente sombreados.
Luzes 2D são GameObjects com o componente Light 2D anexado. Eles funcionam com Sprite Renderer, Sprite Shape Renderere Tilemap Renderer. Eles também usam camadas de classificação, e cada luz é capaz de afetar uma ou mais camadas. Você pode selecionar quais camadas serão afetadas na lista suspensa Camadas de classificação de destino.
Existem quatro tipos diferentes de luzes 2D:
Forma livre: Eles podem ter o formato de um polígono de n lados. Você pode usar esse tipo de luz em ambientes não orgânicos ou estilizados. É uma boa opção para iluminar com eficiência grande parte do ambiente (como uma piscina de lava), simulando formas de luz (como raios divinos saindo de uma abertura no teto) ou adaptando-se ao formato de uma janela onde a luz é projetada.
Sprite: Esta forma permite que você use qualquer sprite como textura de luz. Isso é útil se você deseja um formato específico que é impossível de obter com outros tipos de luz. Exemplos de texturas possíveis incluem reflexos de lente, brilhos, biscoitos de luz, projeções de formas de luz, como luzes de bolas de discoteca, ou lâmpadas projetando estrelas contra uma parede.
Ver: Esta luz pode ser um círculo ou um setor circular. Serve para holofotes, ou para iluminar um ponto específico com fogo de tocha, velas, luzes de carro, lanternas, luz volumétrica e assim por diante.
Global: Esta luz não tem forma, mas em vez disso ilumina todos os objetos nas camadas de classificação alvo. Apenas um Global Light pode ser usado por Blend Style (o método de interação entre a luz e os sprites) e por camada de classificação. Use-o primeiro para adicionar uma luz ambiente básica.
Estas configurações estão disponíveis para cada tipo de luz:
Estilo de mistura: Um estilo de mesclagem determina a maneira como uma luz específica interage com os sprites na cena. Todas as luzes na cena devem ter um dos quatro estilos ou modos de mesclagem disponíveis: Aditivo, Modulado, Subtrativo e Personalizado. Cada modo controla a forma como um sprite é iluminado pela luz.
Ordem de luzeoperação de sobreposição: Isso permite que você controle o que acontece quando várias luzes afetam os mesmos pixels.
Sombras: Quando você habilita esta opção, GameObjects com Shadow Caster projetarão sombras desta fonte de luz.
Volumétrico: Isso permite controlar a queda de luz e escuridão da sombra projetada.
Mapas normais: Quando ativado, as informações normais do mapa no sprite são usadas para calcular a quantidade de luz com base na direção do pixel.
Você pode atribuir Texturas Secundárias opcionais a cada ativo sprite em um projeto 2D via Sprite Editor > Texturas Secundárias. Existem dois tipos de texturas secundárias: Mapa normal e mapa de máscara. Em Happy Harvest, mapas normais e de máscara são usados para todos os elementos, desde o personagem até mapas de blocos e adereços, tornando possível criar efeitos de iluminação e sombra em tempo real de alta qualidade.
Mapa normal
Luzes e mapas normais são usados em Happy Harvest para criar a ilusão de volume e dar à demo uma aparência única. Você pode usar mapas normais com luzes Spot, Point e Freeform.
A forma como um mapa normal é feito pode criar ou quebrar a ilusão de um sprite ser 3D. Cada pixel em um mapa normal armazena dados sobre os ângulos da textura principal. Os canais vermelho, verde e azul (RGB) armazenam dados de ângulo para as coordenadas X, Y e Z. Cada luz que usa um mapa normal tem uma direção, e os pixels em uma textura com um mapa normal são sombreados com base nessa direção e também na direção do pixel. Isso imita como a luz funciona na vida real – se um pixel estiver voltado para a direção da luz, ele será aceso e, se estiver voltado para o lado oposto, não receberá luz.
Mapa de máscara
As máscaras controlam onde as luzes podem afetar um sprite. Existem quatro canais para selecionar como canal de máscara: Vermelho, Azul, Verde e Alfa. Um valor máximo de máscara significa luz total e um valor mínimo significa sem luz.
Os mapas de máscara ajudam a aprimorar seu jogo, permitindo que você adicione detalhes aos seus visuais. Eles também são usados pelos estilos de mistura de luz 2D.
O Blend Style pega o valor de uma luz em um determinado pixel e multiplica esse valor pela máscara no mesmo pixel. O valor de luz mascarada resultante é então adicionado, subtraído ou multiplicado pela cor daquele pixel, com base no estilo de mesclagem escolhido.
Mapas de máscara usados para luzes de aro
Para fins de legibilidade, os personagens geralmente têm uma luz ao redor de sua silhueta à medida que se movem. A iluminação da borda é um efeito usado para destacar os contornos de um personagem. Ele simula a luz vinda de trás de um objeto e as propriedades naturais de dispersão da luz. Isso também é chamado de efeito Fresnel. Em um jogo 2D de rolagem lateral, a superfície do solo e o fundo podem ajudar a amplificar a silhueta do personagem. Nos jogos de cima para baixo, as silhuetas ficam mais inseridas no ambiente, por isso se beneficiam de uma luz de borda transparente para diferenciar suas formas.
O personagem principal e os adereços de Happy Harvest incluem um mapa de máscara para o efeito de luz do aro. Para o personagem principal, a área de luz é desenhada no canal R e o canal G é usado para adereços. A razão para isso é iluminar a silhueta do personagem de forma diferente dos adereços normais (com diferentes conjuntos de luzes que afetam apenas o canal R no canal Blend Style).
Lembre-se, os mapas normais devem ser importados no Unity como Normal Map e os mapas de máscara como o tipo de textura Default. Isso garante que, ao empacotar texturas com Sprite Atlas, cada textura seja empacotada apenas em seu atlas correto para evitar duplicação.
A iluminação 2D não fica bem em um sprite que já tem sombras pintadas. Você também acabará fazendo o dobro da quantidade de trabalho porque estará “pintando” a iluminação em mapas normais. Se você pintar sombras não direcionais, seu sprite ficará melhor, desde que você evite qualquer luz direcional, como a luz solar.
Criar mapas normais para cada sprite, bloco ou formato de sprite pode ser demorado. Considere combinar diferentes técnicas de geração, investindo tempo em trabalho manual onde realmente importa e automatizando processos para acessórios de fundo. Observe que se você gerar o sprite 2D a partir de um software de modelagem 3D como Blender ou 3ds Max, essa textura deverá ser fácil de gerar.
Vejamos alguns exemplos:
- Morfe um mapa normal existente para adaptá-lo ao objeto 2D em questão. Por exemplo, um anel ou gema poderia usar os mapas normais de amostra da imagem.
- Use uma ferramenta normal de geração de mapas como SpriteIlluminator, NormalPainter, Krita's Tangent Normal Brush ou Laigter.
- Os aplicativos geradores não levam em consideração os ângulos do seu sprite, portanto, evite usá-los em todo o sprite. Eles também não reconhecem os objetos. Em vez disso, eles estimam as formas a partir das cores do sprite ou adicionando um filtro geral semelhante ao chanfro ou relevo em aplicativos de edição de imagens.
- Eles não conseguem reconhecer os ângulos de um rosto, mas tentam adivinhar onde deveria haver uma mudança no ângulo. Apesar dessa limitação, eles ainda são úteis para gerar mapas normais de seções de sprites chanfradas, como correntes, cabos ou cauda de dragão, bem como normais de superfície para tijolos, pedras, madeira e muito mais.
- O Unity oferece uma maneira de gerar mapas normais a partir de um mapa de altura em tons de cinza. Esta é uma textura onde o preto representa a altura mínima da superfície e o branco a altura máxima. Importe uma imagem como um mapa normal e marque a opção Criar em escala de cinza . Esta técnica é útil para gerar mapas normais rapidamente sem sair do mecanismo.
- Experimente a cor de uma imagem de amostra. Primeiro, obtenha uma paleta de mapa normal (você pode encontrar algumas on-line) para poder experimentar as cores usadas para representar os ângulos da superfície. Você só precisará copiar uma paleta para seu aplicativo de pintura favorito e usar o seletor de cores para selecionar uma cor para pintar em seu mapa normal.
- As cores dos ângulos não precisam ser 100% precisas. No entanto, certifique-se de manter a forma geral do sprite confiável. Se você usar uma cor de ângulo que não faça sentido no contexto, a forma se desfará quando acesa.
- Pintar mapas normais pode ser complicado inicialmente porque requer uma boa imaginação espacial. Tente começar com algo simples, como os planos básicos da cabeça. O exemplo usado aqui é um modelo simplificado de cabeça humana com aparência low-poly.
- Ao pintar um mapa normal, tente imaginar as formas 3D básicas que fazem parte do seu sprite e, em seguida, visualize os ângulos de cada parte individual. Se você conhece o ângulo, saberá de qual parte do sprite da paleta obter uma amostra de cor.
- A imagem de exemplo mostrada aqui está trabalhando em uma superfície plana, mas o processo é semelhante quando você pinta com pincéis mais macios. Você pode misturar arestas duras para obter uma aparência mais natural.
- Pinte manualmente as luzes e sombras do objeto de três ângulos diferentes, um por canal RGB, e combine os canais de cores. A luz que vem de cima deve usar o canal G, a luz que vem do lado direito deve usar o canal R e a luz que vem do centro deve usar o canal B. Observe que o canal B é opcional, então você pode reduzir a carga de trabalho e ao mesmo tempo obter uma aparência confiável.
As Luzes Globais afetam toda a cena, facilitando a mudança de clima. Eles são usados na demonstração (o GameObject chamado Ambient Light) para aplicar uma tonalidade geral e evitar áreas escuras.
Uma luz global 2D é adicionada por padrão em cada nova cena. Eles não precisam ser brancos nem alterar a cor, intensidade ou camadas afetadas para aplicar uma tonalidade uniforme à cena.
Deve haver apenas uma Luz Global na cena. Ao manipular seus parâmetros, você pode simular facilmente diferentes condições ambientais, como a noite, diminuindo a intensidade e aplicando uma tonalidade roxa à cena. Na demonstração, a cor muda de acordo com a hora do dia, efeito gerenciado pelo script DayCycleHandler , explicado posteriormente.
Uma grande luz Spot é usada no Happy Harvest como luz principal. Ele está acoplado à câmera, por isso está sempre na tela e gira com um script que simula o movimento do sol.
Uma cena 2D não possui luz de direção como as cenas 3D. No entanto, você pode usar uma fonte de luz que iluminará os sprites nas posições X e Y. Isso permite criar efeitos como o movimento do sol à medida que o dia avança, o que pode ser importante em jogos de simulação e de cima para baixo. Também é importante notar que o uso de luzes grandes tem um custo se você estiver almejando plataformas de baixo custo. Verifique a seção de dicas de desempenho no final deste artigo.
Na demonstração, procure o GameObject filho chamado LightsRotator, que possui quatro luzes anexadas:
Luz noturna: Simula a direção do luar
Luz do dia: Simula a direção da luz solar (posição oposta ao NightLight)
NightLightRim: Semelhante à luz de direção da lua NightLight, mas apenas para as luzes do aro do personagem e do adereço
DayLightRim: Semelhante à luz de direção da luz solar DayLight, mas apenas para as luzes do aro do personagem e dos adereços
O script que controla o movimento dessas luzes também controla a mudança de cor ao longo do dia. Os gradientes escolhem a cor de cada luz em um determinado momento. Você pode ver esses gradientes no script DayCycleHandler anexado ao DayCycleHandler GameObject.
Luzes e mapas normais são usados em todo o Happy Harvest para criar a ilusão de volume. Você pode usar mapas normais com luzes Spot, Point e Freeform. Lembre-se que você precisa habilitar mapas normais no objeto light para utilizá-los nos sprites. Duas configurações de qualidade estão disponíveis: Rápido e preciso.
Você pode ver como os arbustos simulam o volume com base na posição da luz quando os mapas normais estão ativados. Os postes de luz e outros adereços iluminam áreas de interesse e ajudam o jogador a navegar pelo caminho.
Objetos 2D podem projetar sombras infinitas anexando o componente Shadow Caster 2D a qualquer sprite ou personagem animado.
Sombras infinitas produzem um belo efeito quando a área de luz é limitada ou há uma fonte de luz forte e focada, como lâmpadas de rua ou uma lareira.
Lembre-se de habilitar mapas normais no objeto light para usar essa textura nos sprites, e de ativar a opção Shadows.
Além disso, a silhueta do personagem não deve projetar sombra, pois pareceria irreal em um jogo de cima para baixo. Um componente Shadow Caster 2D afeta os pés apenas, pois está anexado aos ossos do pé dentro do GameObject do personagem (Visual > Prefab_character_base > root_bone > … > foot_r_bone e foot_l_bone).
Em um jogo de cima para baixo, uma projeção infinita de sombra vinda da luz solar pode parecer estranha. Uma técnica empregada no Happy Harvest é usar uma sombra nas árvores e arbustos que gira e se estende de acordo com a hora do dia. O resultado é uma sombra mais suave que segue melhor a direção de arte.
A função UpdateShadow no script gira essa sombra. Como outras sombras de blob, esta é uma luz baseada em sprite. Você pode verificar isso inspecionando qualquer GameObject dentro do GameObject pai chamado Trees. Procure o GameObject filho chamado ShadowLong dentro do GameObject chamado RotationHandle. O script Shadow Instance adiciona RotationHandle ao script UpdateShadow. Este script atua então como gerenciador, usando uma função para atualizar o tamanho e a rotação das sombras.
As sombras em forma de bolha funcionam bem para objetos pequenos ou planos, como outdoors ou árvores. No entanto, um grande edifício com profundidade e uma forma bem definida precisa projetar uma sombra de aparência precisa. Em Happy Harvest, as luzes de forma livre criam essas sombras. Eles imitam a projeção que o edifício produziria no terreno, uma aproximação necessária, já que não há informação de profundidade em 2D.
O desafio das sombras bem definidas é como fazê-las funcionar com o ciclo do dia para a noite. Para fazer as sombras reagirem às diferentes posições do sol, um script Light Interpolator interpola os pontos vetoriais da luz Freeform entre diferentes sombras de referência.
Na hierarquia da demonstração, encontre o GameObject denominado Light_2D_Warehouse. Quatro luzes Freeform estão anexadas a ele, imitando a sombra que o edifício projetaria quando o sol estivesse alto, baixo e à direita e à esquerda do edifício. Este script cria uma interpolação suave, movendo os diferentes pontos do vetor usando a API.
A sombra superior é criada primeiro e depois modificada para criar as outras sombras. É importante garantir que cada sombra tenha o mesmo número de pontos e que a transição entre esses pontos seja considerada ao criar cada sombra.
Uma vez criadas as sombras, elas são adicionadas ao script do componente Light Interpolator com um parâmetro Normalized que indica o peso no tempo de cada sombra durante o dia. O recurso Preview Time no script permite pré-visualizar como eles ficarão no Editor.
O gerenciador DayCycleHandler é o script que orquestra o ciclo do dia para a noite. Vamos dar uma olhada em alguns de seus recursos.
O GameObject denominado Lights Root é o pai que contém luzes Spot para simular a luz do sol e da lua. Ele é girado pelo script DayCycleHandler.
As luzes noturna, ambiente e borda são nomeadas para transmitir sua finalidade. Os gradientes são a tonalidade de cor que cada luz exibe para criar a atmosfera apropriada.
Para a variável Duração do Dia em Segundos , você pode definir a duração do dia em segundos e definir o horário de início. Em Test Time, você pode pré-visualizar como o jogo ficará em diferentes momentos no Editor.
Os parâmetros para controlar os efeitos de sombra finitos são Shadow Angle e Shadow Length. Em cada um desses campos, a curva de animação indica o ângulo das sombras no sentido horário ao longo do dia. O parâmetro length define o comprimento das sombras em um determinado momento. Por exemplo, você pode precisar de uma sombra mais longa quando o sol está se pondo e de uma sombra mais curta quando o sol ilumina a cena perpendicularmente. Observe que pode ser necessário mover o controle deslizante Test Time para atualizar as configurações Shadow Angle e Shadow Length.
Uma preocupação comum ao usar iluminação 2D, especialmente em plataformas móveis, é o custo de adicionar luzes ao jogo. É recomendado testar no hardware alvo real com as especificações mais baixas suportadas. Existem também algumas otimizações gerais que você pode aplicar para aumentar o desempenho:
Mantenha a taxa de preenchimento o mais baixa possível. Uma luz grande pode ter um desempenho pior do que várias luzes pequenas.
As luzes têm melhor desempenho quando podem ser agrupadas. Luzes com a mesma configuração de iluminação em camadas contíguas podem ser desenhadas juntas.
Mantenha a escala de renderização o mais baixa possível. A escala de renderização ajusta o tamanho da textura usada ao renderizar a iluminação, e um tamanho de textura menor significa menos pixels a serem renderizados.
Minimize o número de luzes que projetam sombras na tela. Há um custo de desempenho não trivial ao mudar para desenhar sombras.
Minimize o número de diferentes estilos de mesclagem na tela. Há um custo significativo ao mudar para desenhar os estilos de mesclagem.
Ajuste o número de Max Light Render Textures e Max Shadow Render para atender às necessidades do seu projeto. Números mais altos aumentarão o desempenho (até certo limite), mas também aumentarão a memória necessária. Você precisará encontrar o número certo.
Se ainda não o fez, baixe estes e-books avançados que cobrem o desenvolvimento e renderização de jogos 2D (3D e 2D) no Unity:
Arte de jogos 2D, animação e iluminação para artistas
Introdução ao Universal Render Pipeline para criadores avançados de Unity
O guia definitivo para iluminação no pipeline de renderização de alta definição no Unity
Além disso, confira nossas outras demos 2D, The Lost Crypt e Dragon Crashers.
Você encontrará mais recursos para programadores avançados, artistas, artistas técnicos e designers no hub de práticas recomendadas do Unity.