Unity3D: como descobrir o grau de iluminação de um ponto em uma cena?

Saudações!

Eu sei, e no fundo você sabe quais estão faltando seus jogos de cartas ou três em um. Sistemas furtivos!

E, é claro, qualquer sistema de furtividade que se preze deve poder levar em conta a iluminação do ambiente ao redor do jogador. Fiquei surpreso ao desenterrar o tópico e encontrar uma quantidade anormalmente pequena de informações. Portanto, apresso-me a compartilhar os frutos.

Hoje não desenvolveremos um sistema de furtividade completo para o jogador, consideraremos puramente interações com a iluminação.

Método 1: coletores


Uma maneira simples e com pouco uso de recursos.

Adicionamos um colisor esférico a cada fonte de luz. Tornamos isso um gatilho. Definimos as dimensões aproximadamente iguais ao raio da luz.

O resto é tão claro quanto uma sombra. Estamos escrevendo um script simples, onde OnTriggerEnter () colocamos a ativação do cálculo da luz (para que as fontes de luz não funcionem "ociosas" quando o player não estiver por perto).

O próprio cálculo de iluminação estará localizado em Update (). Em essência, este é o Physics.Raycast usual (). Se atingir o jogador, ele estará na zona de luz. Se não cair, significa que o jogador está atrás de obstáculos e, portanto, na sombra.

Você também pode adicionar aqui o cálculo da distância entre o player e a fonte de luz. Assim, para determinar a iluminação, usaremos um flutuador simples, que variará dependendo da distância das fontes de luz. E você pode usá-lo onde seu coração desejar.

Exemplo

No ponto 1, a iluminação está próxima do máximo. No ponto 2, a iluminação é mínima - há um obstáculo entre a luz e o ponto. No ponto 3, a iluminação é média.

E isso não é tudo! Você pode adicionar coletores de gatilho a várias "zonas de sombra" onde o jogador deve se esconder. Nas melhores tradições de Manhunt. Da mesma forma, você pode marcar as zonas brilhantes com o colisor, simulando, por exemplo, a luz de um refletor.

Vantagens:


  • Fácil de personalizar Luzes pontuais.
  • Bastante econômico em termos de recursos, se você não envia spam para fontes de luz.

Desvantagens:


  • A luz do ponto e a luz direcional estão fortemente ajustadas. Se, pela primeira vez, basta posicionar o colisor no campo de luz (para aumentar a visibilidade do jogador na entrada), o segundo é um verdadeiro horror. Você precisa colocar coletores em cada sombra (para reduzir a visibilidade do jogador na entrada) ou verificar constantemente com Physics.Raycast () entre o jogador e o "sol" - ele está localizado sob os raios ou na sombra.
  • Um grande número de colecionadores atravessa a cena, complicando a física.
  • Cuidados devem ser tomados com fontes de luz que se cruzam.
  • A luz dinâmica (movimento ou mudança de intensidade) precisa ser adicionada separadamente por meio de scripts.

Método 2: RenderTexture


O que estamos fazendo aqui? De fato, obtemos uma "captura de tela" da câmera, e não necessariamente da câmera principal. E então analisamos a cor da captura de tela para descobrir como a luz cai sobre o assunto.

Para começar, precisamos de um objeto do qual "leremos" a luz. Crie uma esfera ou plano regular, faça-o pequeno (escala 0.1), coloque-o próximo ao chão, faça-o branco, remova o colisor:

Texto oculto


Adicione uma câmera (remova o ouvinte de áudio e verifique se a etiqueta MainCamera não vale a pena). Vincule-o ao nosso objeto. Colocamos um pouco mais alto, direcionamos para baixo. Nós expomos nas configurações não a tela principal. Fazer ortografia é para o seu gosto.

No final, nós o posicionamos de modo que ele olhe para o nosso objeto e apenas para ele.

Texto oculto


No final, configure a máscara de descarte das câmeras principal e secundária para que a principal não exiba nossos objetos “leves”, enquanto as secundárias os veem apenas sem desordenar mais nada.

E aqui começa a diversão. Anexamos o script à câmera:

public Camera cam; //   RenderTexture tex; Texture2D _tex; void Start () { //    "". // ,       -   . // Depth   0   -   . tex = new RenderTexture (1, 1, 8); // RenderTexture "" , //   ,    . _tex = new Texture2D (1, 1, TextureFormat.RGB24, false); } void Update () { //   ""  cam.targetTexture = tex; cam.Render (); //     RenderTexture.active = tex; //   Texture2D _tex.ReadPixels (new Rect (0, 0, 1, 1), 0, 0); _tex.Apply (); Color col = _tex.GetPixel (0, 0); float vis = (col.r + col.g + col.b) / 3; } 

Na saída, obtemos um float vis, que, em essência, é uma representação numérica do nível de iluminação incidente em nosso objeto. Se a fonte estiver próxima - o objeto é branco - vis é 1. Se estiver escuro - o objeto é preto - vis é ~ 0.

Não precisamos executar a operação acima em todos os quadros, portanto incorporamos um pequeno segundo temporizador:

 float interval = 0; void Update () { interval += Time.deltaTime; if (interval < 1) return; interval = 0; //   } 

Em seguida, amarramos todo o sistema ao jogador para que ele se mova com ele. E nossa variável vis retorna automaticamente a luz ao redor do player!

Este sistema pode ser usado não apenas em conjunto com o reprodutor. Você pode colocá-lo em qualquer lugar e como quiser, criando um tipo de sensor de luz. Como regra, existem maneiras mais eficazes de implementá-las, mas é sempre bom ter alternativas?

As vantagens são óbvias, vamos falar sobre as desvantagens.

Desvantagens


  • Cada "detector de luz" (se houver mais de um) requer uma câmera separada.
  • Texture2D.ReadPixels () - bem, extremamente lento. Mesmo que você faça isso uma vez por segundo, e nem todos os quadros, mesmo que você divida as funções de escrever e ler texturas em quadros diferentes, ainda existem layouts entre 40 e 110 ms.
  • Este sistema não leva em consideração alguns casos raros. Por exemplo, uma lanterna brilha em um personagem. O personagem está bem iluminado, mas a luz cai sobre ele e atrás dele, e não para baixo, respectivamente, nosso detector de luz mostra um baixo nível de iluminação. Você pode resolver o problema, por exemplo, colocando o detector não no chão, mas no nível do peito do personagem. Então você precisa colocar duas câmeras em lados opostos para ler a luz de ambos os lados. O que diminuirá a velocidade do sistema pela metade.

Source: https://habr.com/ru/post/pt417135/


All Articles