J'ai donc récemment essayé cela et j'ai rencontré beaucoup des mêmes problèmes que vous. La solution de texture de rendu est un peu un hareng rouge. J'ai pu le résoudre en utilisant la manipulation de pixels multithreads sur un thread séparé.
https://www.youtube.com/watch?v=T_zpFk1mdCI
Donc, normalement, on utilise graphics.blit()
et transmet la texture de rendu là où elle doit aller, mais les données lightmap ne prennent pas en charge les textures, elles nécessitent texture2ds. La prochaine étape logique serait de copier les données dans un texture2d, puis de les alimenter dans les données lightmap. Cette technique ruine les fréquences d'images car elle bloque le GPU pour envoyer des données au CPU, plutôt qu'une simple référence aux données.
La solution est alors de ne pas utiliser le GPU.
Les transitions de la carte de lumière se produisent sur une longue période de temps, il n'est donc pas nécessairement important de mettre à jour la carte de lumière à chaque image. En fait, les joueurs ne remarqueraient probablement pas si les cartes lumineuses n'étaient mises à jour que toutes les 20 à 40 minutes en temps de jeu.
Donc, ce que vous faites, vous lancez la tâche vers le CPU sur des threads séparés pour chaque carte de lumière.
Ordinairement, Unity ne prend pas en charge le multithreading. Mais ça va, C # le fait. Ce gars fait un travail phénoménal pour expliquer le multithreading dans Unity, donc si vous n'en avez jamais entendu parler, ou si vous n'avez jamais su comment multithread dans Unity, voici la vidéo:
https://www.youtube.com/watch?v=ja63QO1Imck
Tout ce que vous devez faire est de créer une classe de threads de travail qui varie les copies des données de pixels du plan optique dans les tableaux de couleurs, puis de créer une fonction de fusion.
Un simple lerp d'une couleur à l'autre fera l'affaire.
Créez ensuite le fil, démarrez-le, et lorsque toutes les lightmaps sont terminées dans les threads séparés, vous pouvez recopier les données de pixels dans la texture de données lightmap2d.
J'ai posté un exemple de code ci-dessous. Ce n'est certainement pas la version entièrement implémentée, mais elle vous montre les principaux concepts de création de la classe, de création du thread, puis de définition des données de lumière.
Les autres choses que vous devriez faire sont d'appeler une fonction de temps en temps pour déclencher la mise à jour des lightmaps. Vous devez également copier toutes les données de pixels dans la classe de travail au démarrage ou au moment de la compilation. Bonne chance à tous ceux qui trouveront ça. Je suppose que l'op a changé sa vie, mais je sais que d'autres personnes ayant des problèmes similaires pourraient tomber dessus.
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;
}