Atividade Com Sombras
O que acontece quando você tenta renderizar sombras sem entender o básico
Vou direto ao ponto. Atividade com sombras, seja em engines de jogos, motores de renderização 3D ou pipelines de visualização, é um dos primeiros obstáculos que todo desenvolvedor encontra e um dos que mais gera dor de cabeça se for tratado como algo trivial. A realidade é que sombras parecem simples na teoria — um objeto bloqueia a luz e cria uma área escura no chão — mas na prática envolvem depth buffering, projeções de matriz, filtering e centenas de artefatos visuais que aparecem só porque alguém não ajustou um bias corretamente. O método mais comum é shadow mapping. Você renderiza a cena a partir da perspectiva da fonte de luz, guarda os valores de profundidade em um mapa, e depois usa esse mapa durante a renderização da câmera principal para decidir se cada pixel está em sombra ou não. Simples assim. O problema é que entre o conceito e o resultado final existem dezenas de pontos de falha. A primeira coisa que preciso deixar clara: o desempenho. Shadow mapping puro, usando uma textura de profundidade de 1024x1024, consome entre 8 e 15 milissegundos por frame em hardware médio, dependendo da complexidade da geometria e do número de fontes de luz. Se você tem três luzes pontuais com shadow mapping ativo, esse tempo pode dobrar ou triplicar. Não existe mágica aí.
Uma configuração típica funciona assim. Primeiro, você configura a light view matrix e a light projection matrix. Depois, faz o first pass, renderizando toda a cena relevante com um shader que simplesmente escreve profundidade na framebuffer. O segundo pass aplica o shadow map usando um shader fragment que compara a profundidade do pixel com a profundidade amostrada do mapa. Se o pixel estiver mais distante do que o valor no mapa, ele está em sombra.
O problema que ninguém conta
Eu perdi uma semana inteira tentando resolver shadow acne em um projeto de jogo indie. O problema era que, mesmo aplicando bias, as sombras oscilavam e tremiam conforme a câmera se movia. A causa raiz não era o bias em si — era a taxa de amostragem da textura. Quando o ângulo entre a superfície e a direção da luz fica muito rasante, a resolução efetiva do shadow map cai drasticamente, e o z-fighting entre a geometria e a comparação de profundidade começa a gerar linhas e padrãoes erráticos. A workaround que funcionou foi uma combinação de três coisas: aumentar a resolução do shadow map apenas para luzes com ângulos rasantes, usar PCF (Percentage Closer Filtering) com pelo menos 4 amostras, e aplicar um slope-scaled bias em vez de um bias fixo. O slope-scaled bias ajusta a baseado na inclinação da superfície relativa à direção da luz, o que elimina a maior parte do acne sem precisar de valores artificialmente altos que causam shadow peter panning. A matemática por trás disso é direta. Você calcula o dot product entre a normal da superfície e a direção da luz, e usa esse valor para escalar o bias. Superfícies perpendiculares à luz precisam de menos bias, superfícies quase paralelas precisam de mais. Esse ajuste fino faz toda a diferença entre uma sombra que parece renderizada e uma que parece um erro de debug.

Erros comuns que atrasam seu projeto
O erro mais frequente que vejo em código novo é não considerar o near plane da projeção da luz. Se o near plane estiver muito longe, objetos próximos à câmera mas fora do frustum da luz não serão inclusos no shadow map, criando buracos nas sombras. Se estiver muito perto, a precisão da profundidade é desperdiçada nas partes irrelevantes do frustum. Outro problema crônico é o número de lights com shadow mapping ativo simultaneamente. Cada luz adicional exige um primeiro pass completo de renderização de profundidade. Em mobile, isso é devastador. A solução pragmática é usar light culling baseada no frustum da câmera e limitar o número de sombras ativas por frame a dois ou três no máximo. Luzes distantes podem usar baked lightmaps em vez de shadow maps dinâmicos, o que elimina completamente o custo de renderização delas. Há também a questão do filtering. Shadow mapping com sampling point é rápido mas gera bordas serrilhadas. PCF é melhor visualmente mas custa mais. VSM (Variance Shadow Maps) oferece blur natural mas tem o problema clássico of light bleeding, onde luz parece vazar através de objetos finos. No meu uso, PCF com 4x4 samples foi o melhor equilíbrio entre qualidade e performance para a maioria dos casos.
Quando atividade com sombras simplesmente não funciona
Vou ser honesto sobre as limitações. Shadow mapping falha catastéricamente com geometria transparente ou semi-transparente. Se você tem vidros, cercas de madeira, grama ou qualquer coisa que permita passagem parcial de luz, o mapa de profundidade não consegue representar essas variações. A solução real para esses casos é either usar stencil shadows (shadow volumes) para objetos específicos, ou fazer baking de sombras para cenários estáticos e reservar shadow mapping dinâmico apenas para luzes principais. Outro cenário onde shadow mapping é problemático é quando a geometria é extremamente detalhada e densa. Árvores com milhares de polígonos, cercas vivas, gradeados ornamentais — tudo isso aumenta drasticamente o tempo do primeiro pass. Nesses casos, o uso de impostors ou billboards para a geometria secundária reduz o custo em cerca de 60-70% sem perda visual perceptível. Se você está trabalhando em mobile ou em plataformas com recursos limitados, considere alternativas como baked shadows combinadas com sphere illumination approximation. Funciona bem para cenas internas com iluminação controlada, e o custo é praticamente zero após o bake inicial, que leva entre 20 minutos e 2 horas dependendo do tamanho do cenário.
Configuração prática em poucas linhas
Se você está usando WebGL ou uma engine baseada nele, a estrutura básica envolve criar uma framebuffer com textura de profundidade, configurar o viewport para o tamanho do shadow map, e renderizar a cena com um shader que calcula a posição no espaço da luz. O shadow map resultante é então amostrado no shader de iluminação da cena principal. Os parâmetros que você precisa ajustar, nessa ordem de prioridade, são: resolução do shadow map, bias, slope-scaled bias, filtering mode, e o número de samples. Comece com resolução 1024, bias 0.001, slope-scaled bias 0.5, PCF 4 samples, e vá refinando. Mudar a resolução para 2048 melhora significativamente a qualidade em ângulos rasantes mas dobra o custo de memória e bandwidth. A manutenção do shadow map também merece atenção. Se sua cena tem objetos que se movem rapidamente, o shadow map pode mostrar artifacts de tearing quando a geometria se move mais rápido do que a taxa de atualização. Nesse caso, aumentar a frequência de regeneração do shadow map ou usar cascaded shadow maps resolve o problema. Cascaded shadow maps dividem o espaço de visão em regiões, cada uma com seu próprio shadow map na resolução apropriada, e entregam qualidade consistente da câmera até o horizonte.

O custo adicional dos cascaded shadow maps é real — você está renderizando a cena três ou quatro vezes por frame em vez de uma — mas a qualidade justificada para cenas open world ou de grande escala torna o investimento necessário. Em testes práticos, com três cascades e resolução total de 2048 por cascade, o impacto foi de aproximadamente 12ms extras em GPU dedicada de gama média, o que é aceitável para um frame target de 16ms em 60fps.
Galeria
-
Atividades com sombras: modelos pronto para imprimir | INDAGAÇÃO -
Atividades com sombras - educação infantil e ensino fundamental. -
Atividades com sombras para crianças - Educação Infantil e Fundamental ...