In Minecraft quando guardi l'acqua più in profondità vedi più diventa scuro. Qualcuno sa come codificare qualcosa del genere?
Minecraft con effetto
gioco simile senza effetto
In Minecraft quando guardi l'acqua più in profondità vedi più diventa scuro. Qualcuno sa come codificare qualcosa del genere?
Minecraft con effetto
gioco simile senza effetto
Risposte:
Esistono essenzialmente due approcci diversi per l'illuminazione dell'acqua in base alla profondità:
Minecraft utilizza l'illuminazione basata su voxel, che funziona propagando la luce in cubi adiacenti, riducendo la luminosità in base al tipo di blocco. Gli oceani scuri sono un effetto collaterale di questo sistema.
L'acqua blocca la luce solare e riduce la luce di 3 livelli per blocco (anziché il livello predefinito 1), il che significa che la luminosità in un oceano per ogni distanza dalla superficie è:
0 (surface): 15 (direct sunlight)
1: 12
2: 9
3: 6
4: 3
5 and below: 0 (darkness)
Fonte: Minecraft Wiki - Light
Nei giochi con un modello di illuminazione tradizionale, questo effetto può essere creato misurando la quantità di acqua che si trova tra la sorgente luminosa e il fondo dell'oceano. La luce viene quindi sbiadita in base a questa distanza. Esistono alcuni metodi per farlo:
Se hai una superficie piana, puoi facilmente calcolare la distanza che la luce percorre nell'acqua se passi la superficie normale lontano dal corpo idrico e il prodotto punto di questa normale e una posizione della superficie nello shader della geometria.
La distanza effettiva dell'acqua è
dov'è la posizione del vertice ed è l'angolo tra la direzione della luce sotto la superficie e la superficie dell'acqua normale verso il corpo idrico.
Al tramonto, raggiunge solo un po 'meno di 50 ° perché la luce viene rifratta quando si entra nell'acqua.
Ecco un post sul blog con una buona spiegazione: la fotocamera digitale: riflessione interna totale
Un altro post con maggiori dettagli: la fotocamera digitale: la legge di rifrazione di Snell
Se stai usando una mappa di altezza su una superficie parallela all'acqua, diventa . Il fattore giusto equivale a 1 se il sole è direttamente sopra la superficie dell'acqua.
Con una luce puntiforme, devi calcolare per ciascun vertice in base alla posizione relativa alla sorgente luminosa.
Con un livello dell'acqua fisso o una direzione della luce fissa, parti dell'equazione sono costanti e non dovrebbero essere calcolate nello shader per motivi di prestazioni.
Se si esegue il rendering della superficie dell'acqua su una mappa di profondità separata (vista dalla sorgente luminosa), è possibile utilizzare quella trama di profondità per calcolare la distanza che la luce percorre nell'acqua prima di colpire la superficie.
Per fare ciò, proietti ciascun vertice nella proiezione della vista della sorgente luminosa nello shader di vertice ed esegui la ricerca della trama nel pixel shader.
Se la superficie è relativamente piatta, è necessario utilizzare un'origine di luce rifratta per risultati migliori.
* È possibile determinare la quantità di acqua davanti alla superficie solida più vicina contando la profondità dal POV della luce come segue:
La trama del risultato ora contiene la quantità di acqua davanti alla luce nello spazio della vista della luce, quindi il valore deve essere trasformato indietro prima di usarlo. Questo metodo funziona per calcolare la luce direzionale (meno la rifrazione), ma porterà a una luce ambientale errata se le superfici sono molto irregolari e c'è una grande quantità di aria tra i corpi idrici che colpiscono gli stessi frammenti.
I pro e i contro sono gli stessi della normale mappatura dell'ombra, tranne per il fatto che è necessario un altro buffer durante il calcolo della profondità e le prestazioni sono peggiori perché è necessario disegnare più geometria.
Il ray tracing è di gran lunga la soluzione più accurata ma anche più costosa per il rendering di volumi trasparenti. Esistono due modi per farlo: 1. Traccia dal fondo dell'oceano verso la superficie e 2. Traccia dalla sorgente luminosa verso l'acqua. Per calcolare la luminosità sono necessari più raggi per ogni punto del pavimento.
Ci sono alcune altre cose da prendere in considerazione quando si rende l'acqua:
La luce nell'acqua viene nuovamente diffusa mentre viaggia verso l'osservatore, quindi dovresti fonderla verso un colore solido.
Se l'osservatore è immerso , è possibile eseguire il rendering della nebbia in base al risultato finale del buffer di profondità. Il colore della nebbia, ma non la sua densità, dovrebbe cambiare con la distanza dell'osservatore dalla superficie! (Minecraft utilizza solo questa parte dell'effetto.)
Se l'osservatore osserva l'acqua dall'alto , è necessario calcolare la nebbia in base alla differenza di profondità tra la superficie e la geometria sott'acqua. Il colore della nebbia dovrebbe diventare leggermente più scuro con differenze di profondità maggiori, ma dovrebbe cambiare solo nel punto in cui la nebbia è completamente opaca.
Il colore della nebbia dovrebbe anche dipendere dalla direzione della vista per ciascun pixel, quindi è leggermente più scuro quando si guarda in basso in entrambi i casi.
Se si utilizza una texture 3D di piastrellatura senza soluzione di continuità anziché una decalcomania per falsi caustici, è possibile evitare l'allungamento su superfici verticali. La forza della luce diffusa vicino alla superficie varia in tre dimensioni, quindi l'uso di una trama 2D di solito produce uno stiramento da qualche parte nella scena. È possibile modellare gli angoli di luce cambiando proiettando le posizioni dei vertici del pavimento in un diverso sistema di coordinate.
Un'altra possibilità è calcolare la densità della luce in base alla posizione della superficie nel sistema di coordinate della luce, anche se molto probabilmente costerebbe alcune prestazioni.
Le sostanze caustiche dovrebbero sbiadire più velocemente della luce diffusa con profondità crescente.
I colori sono sparsi in modo diverso, quindi il colore della luce dovrebbe cambiare con l'aumentare della profondità. Ciò impedisce anche bordi improvvisi in cui, ad esempio, una spiaggia interseca la superficie dell'acqua.
A causa della rifrazione, la luce colpisce il fondale oceanico molto più ripida di quanto farebbe normalmente. L' articolo di Wikipedia sulla legge di Snell contiene formule per angoli e vettori.
Credo che l'effetto della luce del cielo in Minecraft sia diretto: le cose vengono ombreggiate da ciò che sta sopra, indipendentemente da dove si trovi il sole. Quindi l'illuminazione locale da torce, ecc. Viene applicata con un effetto di discesa: più è lontana dalla sorgente luminosa, meno luce riceve un cubo.
Se fatto in questo modo, ogni strato d'acqua oscurerebbe cumulativamente lo strato sottostante, quindi ognuno diventerà progressivamente più scuro. Il fogliame dell'albero fornisce ombra come questa, tuttavia non è cumulativa. Ottieni la stessa ombra sotto un albero che si tratti di 1 o 100 cubetti di fogliame.
Un indizio del fatto che questo è il metodo utilizzato è che l'acqua non diventa più scura quando è più lontana dallo spettatore - solo mentre scendi. Sì, l'effetto nebbia si attiva a distanza, ma non l'effetto acqua scura.
Quindi la formula di base per calcolare l'illuminazione sarebbe qualcosa di simile in pseudo-codice ...
light_on_cube = 1.0
for each cube above target cube, from lowest to highest {
if cube being examined is tree foliage
light_on_cube = 0.5
else if cube being examined is water
light_on_cube = light_on_cube - 0.1
else if cube being examined is solid
light_on_cube = 0
}
Questo non è perfetto per il calcolo dell'illuminazione sotto sporgenze o in grotte, poiché con questo metodo sarebbe buio pesto sotto una sporgenza. Ma si potrebbero aggiungere sia fonti di luce locale (torce, fuochi, ecc.) Che trattare i blocchi illuminati dal sole come fonti di luce. Qualcosa del genere potrebbe farlo ...
L'idea qui è che se un cubo è illuminato dal sole o da una torcia, anche il cubo accanto ad esso verrà illuminato in qualche modo. E più lontano sei da quel cubo illuminato, meno luce ci sarà. È una specie di modo kludge per stimare l'illuminazione diffusa ma penso (?) Che funzionerebbe.
Forse sto fraintendendo la domanda, ma perché non puoi semplicemente cambiare il colore dei blocchi a seconda della loro profondità?
Se hai la profondità d (in blocchi, a partire da 0), un'equazione ragionevole per la luminosità sarebbe:
L = (1- m ) e - kd + m
Codice: L = (1.0 - m) * exp(-k * d) + m;
k controlla quanto velocemente diventa più scuro (più alto = più veloce). Un valore ragionevole sarebbe 0,5.
m è la luminosità minima desiderata.
L varia da 0 a 1.
Se non sai come cambiare il colore dei blocchi in qualsiasi API grafica che stai utilizzando, ti preghiamo di porre questa domanda separatamente (indicando quale API usi e se stai usando gli shader).
e^-kd
bit è solo un decadimento esponenziale, che è una funzione standard per cose che tendono gradualmente verso lo zero oltre un certo valore (profondità). La moltiplicazione (1-m)
e l'aggiunta di m
sono solo per ridimensionare e compensare il decadimento in modo che finisca al minimo m
ma inizi comunque a 1
. en.wikipedia.org/wiki/Exponential_decay