Então, eu tentei recentemente e encontrei muitos dos mesmos problemas que vocês têm. A solução de textura de renderização é um pouco de um arenque vermelho. Consegui resolvê-lo usando a manipulação de pixels multithreading em um thread separado.
https://www.youtube.com/watch?v=T_zpFk1mdCI
Então, normalmente, alguém usaria graphics.blit()
e passaria a textura de renderização para onde quer que fosse, mas os dados do lightmap não suportam texturas, eles exigem texture2ds. O próximo passo lógico seria copiar os dados para um texture2d e depois alimentá-los com os dados do lightmap. Essa técnica arruina as taxas de quadros porque está impedindo a GPU de enviar dados para a CPU, em vez de apenas uma referência aos dados.
A solução é então não usar a GPU.
As transições do mapa de luz acontecem por um longo período de tempo, portanto, não é necessariamente importante atualizar o mapa de luz a cada quadro. Por uma questão de fato, os jogadores provavelmente não notariam se os mapas de luz eram atualizados apenas a cada 20-40 minutos no tempo do jogo.
Então, o que você faz é emitir a tarefa para a CPU em threads separados para cada mapa de luzes.
Normalmente, o Unity não suporta multithreading. Mas tudo bem, C # faz. Esse cara faz um trabalho fenomenal ao explicar multithreading no Unity, por isso, se você nunca ouviu falar ou nunca soube multithread no Unity, este é o vídeo:
https://www.youtube.com/watch?v=ja63QO1Imck
Tudo o que você precisa fazer é criar uma classe de encadeamento de trabalho que varie cópias dos dados de pixel do lightmap nas matrizes Color e criar uma função de mesclagem.
Um simples lerp de uma cor para a próxima serve.
Em seguida, crie o encadeamento, inicie-o e, quando todos os mapas de luz estiverem concluídos nos encadeamentos separados, você poderá copiar os dados de pixel de volta na textura de dados lightmap2d.
Publiquei um código de exemplo abaixo. Certamente não é a versão totalmente implementada, mas mostra os principais conceitos de criação da classe, criação do thread e configuração dos dados da luz.
As outras coisas que você teria que fazer é chamar uma função de vez em quando para acionar a atualização dos mapas de luz. Além disso, você deve copiar todos os dados de pixel na classe worker no início ou no tempo de compilação. Boa sorte para quem encontrar isso. Eu acho que a operação mudou sua vida, mas sei que outras pessoas com problemas semelhantes podem tropeçar nisso.
public class work
{
Color[] fromPixels;
Color[] toPixels;
public float LerpValue = 0;
public bool Finished = false;
public Color[] mixedPixels;
public work(Color[] FromPix, Color[] ToPix)
{
fromPixels= FromPix;
toPixels= ToPix;
Finished = false;
mixedPixels = new Color[FromPix.Length];
}
public void DoWork()
{
for (int x = 0; x < fromPixels.Length; x++)
{
mixedPixels[x] = Color.Lerp(fromPixels[x], toPixels[x], LerpValue);
}
Finished = true;
}
}
IEnumerator LightMapSet()
{
Thread workerThread = new Thread(someworker.DoWork);
someworker.LerpValue = lerpValue;
workerThread.Start();
yield return new WaitUntil(() => someworker.Finished);
mixedMap.SetPixels(someworker.mixedPixels);
mixedMap.Apply(true);
LightmapData someLightmapData;
someLightmapData.lightmapColor = mixedMap;
lightDatas = { someLightmapData};
LightmapSettings.lightmaps = lightDatas;
}