Come si fondono 2 mappe luminose per il ciclo giorno / notte in Unity?


16

Prima di dire qualsiasi altra cosa: sto usando due mappe luminose, il che significa che devo fondere sia un vicino che un lontano.

Quindi ci sto lavorando da un po 'di tempo, ho impostato un intero ciclo giorno / notte per i renderer e l'illuminazione, e tutto funziona bene e non è un processo intenso.

L'unico problema che sto riscontrando è capire come potrei fondere due mappe luminose insieme, ho capito come cambiare le mappe luminose, ma il problema è che sembra un po 'brusco e interrompe l'esperienza.

Ho fatto ore di ricerche su questo, provato tutti i tipi di shader, miscelazione pixel per pixel, e tutto il resto senza alcun risultato. La fusione pixel per pixel in C # si è rivelata un po 'impegnativa per i miei gusti, anche se sto ancora lavorando per ripulirlo e farlo funzionare in modo più fluido. Gli shader sembravano promettenti, ma non riuscivo a trovare uno shader in grado di fondere correttamente due mappe di luce.

Qualcuno ha qualche indizio su come potrei farlo? Ho solo bisogno di una sorta di transizione graduale tra la mia mappa luminosa diurna e notturna. Forse potrei sovrapporre le due trame e usare un canale alfa? O qualcosa di simile?


Se hai Pro, forse puoi renderizzare le due trame della lightmap in una terza e quindi utilizzare questa terza texture come una lightmap? Dovrebbe essere proprio come la fusione dei pixel, ma enormemente più veloce.
Nevermind

Ho un professionista. Come farei per rendere insieme le due trame lightmap? Questo è stato il mio principale vantaggio, ma ho cercato di capire il codice / processo per realizzarlo.
Timothy Williams,

Umm crea un materiale che fonde due trame, usi Graphics.Blit()per renderlo? Non l'ho mai fatto, ma guardando nel manuale, dovrebbe funzionare.
Nevermind

Quindi creare un nuovo materiale in grado di fondere due trame in un output, applicare Afar-1 e Bfar-1, quindi utilizzare la trama in uscita per la variabile lightmap?
Timothy Williams,

Sì, qualcosa del genere. Lo testerei, ma al momento non ho accesso alla versione Pro.
Nevermind,

Risposte:


3

Quindi di recente ho provato a farlo e ho riscontrato molti degli stessi problemi che voi ragazzi avete. La soluzione di texture di rendering è un po 'un'aringa rossa. Sono stato in grado di risolverlo usando la manipolazione di pixel multithreading su un thread separato.

https://www.youtube.com/watch?v=T_zpFk1mdCI

Quindi di solito si userebbe graphics.blit()e passerebbe la trama di rendering dove deve andare, ma i dati di lightmap non supportano le trame, richiedono texture2ds. Il prossimo passo logico sarebbe quello di copiare i dati in una texture2d e quindi di inviarli ai dati della mappa luminosa. Questa tecnica rovina i frame rate perché sta bloccando la GPU per inviare dati alla CPU, piuttosto che solo un riferimento ai dati.

La soluzione è quindi di non utilizzare la GPU.

Le transizioni della mappa di luce avvengono per un lungo periodo di tempo, quindi non è necessariamente importante aggiornare la mappa di luce ogni fotogramma. È un dato di fatto, i giocatori probabilmente non noterebbero se le mappe luminose fossero aggiornate solo ogni 20-40 minuti nel tempo di gioco.

Quindi, ciò che fai è inviare l'attività alla CPU su thread separati per ogni mappa luminosa.

Normalmente Unity non supporta il multithreading. Ma va bene, C # lo fa. Questo ragazzo fa un lavoro fenomenale spiegando il multithreading in Unity, quindi se non ne hai mai sentito parlare o non hai mai saputo come fare il multithread in Unity questo è il video:

https://www.youtube.com/watch?v=ja63QO1Imck

Tutto quello che devi fare è creare una classe di thread di lavoro che vari le copie dei dati dei pixel della mappa luminosa negli array Color e quindi creare una funzione di fusione.

Sarà sufficiente un semplice passaggio da un colore all'altro.

Quindi creare il thread, avviarlo e quando tutte le mappe luminose sono terminate in thread separati è possibile copiare nuovamente i dati dei pixel nella texture2d dei dati della mappa luminosa.

Ho pubblicato un codice di esempio di seguito. Non è certamente la versione completamente implementata, ma ti mostra i concetti principali di come creare la classe, creare il thread e quindi impostare i dati di luce.

L'altra cosa che dovresti fare è chiamare una funzione ogni tanto per attivare l'aggiornamento delle mappe luminose. Inoltre, è necessario copiare tutti i dati pixel nella classe lavoratore all'avvio o al momento della compilazione. Buona fortuna a chiunque lo trovi. Immagino che l'operazione sia andata avanti con la loro vita, ma so che altre persone con problemi simili potrebbero inciampare in questo.

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;
}

1

C'è uno shader skybox che si fonde tra due serie di trame skybox. Pensa al ciclo giorno e notte!

Se vuoi creare o animare lo skybox dallo script, usa skyboxmaterial.SetFloat("_Blend", yourBlend)per cambiare la fusione; può anche utilizzare le SetTexturefunzioni dei materiali per impostare o modificare le trame.

Tutorial video sul ciclo giorno / notte: http://www.youtube.com/watch?v=FTfv9JhkmIA

Il codice di esempio è il seguente:

Shader "RenderFX/Skybox Blended" {
Properties {
    _Tint ("Tint Color", Color) = (.5, .5, .5, .5)
    _Blend ("Blend", Range(0.0,1.0)) = 0.5
    _FrontTex ("Front (+Z)", 2D) = "white" {}
    _BackTex ("Back (-Z)", 2D) = "white" {}
    _LeftTex ("Left (+X)", 2D) = "white" {}
    _RightTex ("Right (-X)", 2D) = "white" {}
    _UpTex ("Up (+Y)", 2D) = "white" {}
    _DownTex ("Down (-Y)", 2D) = "white" {}
    _FrontTex2("2 Front (+Z)", 2D) = "white" {}
    _BackTex2("2 Back (-Z)", 2D) = "white" {}
    _LeftTex2("2 Left (+X)", 2D) = "white" {}
    _RightTex2("2 Right (-X)", 2D) = "white" {}
    _UpTex2("2 Up (+Y)", 2D) = "white" {}
    _DownTex2("2 Down (-Y)", 2D) = "white" {}
}

SubShader {
    Tags { "Queue" = "Background" }
    Cull Off
    Fog { Mode Off }
    Lighting Off        
    Color [_Tint]
    Pass {
        SetTexture [_FrontTex] { combine texture }
        SetTexture [_FrontTex2] { constantColor (0,0,0,[_Blend]) combine texture lerp(constant) previous }
        SetTexture [_FrontTex2] { combine previous +- primary, previous * primary }
    }
    Pass {
        SetTexture [_BackTex] { combine texture }
        SetTexture [_BackTex2] { constantColor (0,0,0,[_Blend]) combine texture lerp(constant) previous }
        SetTexture [_BackTex2] { combine previous +- primary, previous * primary }
    }
    Pass {
        SetTexture [_LeftTex] { combine texture }
        SetTexture [_LeftTex2] { constantColor (0,0,0,[_Blend]) combine texture lerp(constant) previous }
        SetTexture [_LeftTex2] { combine previous +- primary, previous * primary }
    }
    Pass {
        SetTexture [_RightTex] { combine texture }
        SetTexture [_RightTex2] { constantColor (0,0,0,[_Blend]) combine texture lerp(constant) previous }
        SetTexture [_RightTex2] { combine previous +- primary, previous * primary }
    }
    Pass {
        SetTexture [_UpTex] { combine texture }
        SetTexture [_UpTex2] { constantColor (0,0,0,[_Blend]) combine texture lerp(constant) previous }
        SetTexture [_UpTex2] { combine previous +- primary, previous * primary }
    }
    Pass {
        SetTexture [_DownTex] { combine texture }
        SetTexture [_DownTex2] { constantColor (0,0,0,[_Blend]) combine texture lerp(constant) previous }
        SetTexture [_DownTex2] { combine previous +- primary, previous * primary }
    }
}

Fallback "RenderFX/Skybox", 1
}

2
La domanda è stata posta sulle mappe luminose, non sullo skybox. Grazie per il link, sembra che mi sarà utile.
jhocking

0

Se sai come passare, perché non continuare con la creazione di una serie di mappe luminose di transizione sul thread di sfondo e quindi abilitare le transizioni quando le mappe luminose sono pronte?

Puoi anche dare un'occhiata a una risorsa interessante su AssetStore: https://www.assetstore.unity3d.com/en/#!/content/5674

Immagino che includa la fusione delle mappe di luce, anche se non so come.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.