Questa è una risposta lunga, ma in realtà la premessa di base della divisione per camera-z è molto semplice: più qualcosa è lontano da te, più piccolo appare. Inoltre, appaiono le distanze minori tra due cose.
Posizioni (lettura non obbligatoria se si utilizza Unity!)
Innanzitutto, devi renderizzare posizioni / punti usando la prospettiva corretta.
Le posizioni si trovano su un piano piatto. Vuoi qualcosa di simile all'immagine a destra ... considera gli angoli delle tessere come punti / posizioni campione.
Ecco come ti avvicini alla trasformazione dei punti:
- Il sistema di coordinate è il seguente: positivo
z
scorre nello schermo, mentre x
corre da sinistra a destra e y
scende. Camera z è world z. Questa è la scorciatoia che rende tutto molto più semplice rispetto alla scrittura di un motore 3D completo. Svantaggio? La fotocamera non può cambiare l'orientamento (sebbene possa cambiare posizione).
- Memorizza la posizione 3D iniziale della videocamera. Rimettilo un po 'indietro (meno
z
) dalle origini del mondo.
- Memorizza una raccolta di punti 3D sul piano xz (forniscili
y=0
). Provate a centrare loro attraverso l'origine mondo x
, (0,0,0)
cioè da negativo n
a positivo n
. Questo per centrarli nella finestra, quando inizia il rendering.
- Considera l'origine del punto decrescente / del grafico a pixel come il centro dello schermo.
- Decidi una distanza dalla telecamera alla quale 1 unità spaziale mondiale = 1 pixel. Ciò significa che se sposti la telecamera di 1 unità spaziale mondiale, qualsiasi oggetto a 10 unità di distanza si sposterà di solo 1 pixel - abbastanza lontano! Memorizza questa distanza come costante
K
.
Ora, per ogni punto, esegui il rendering in una posizione usando la seguente formula: screenPosition(x,y) = screenOrigin + (worldPosition(x,y) - cameraPosition(x,y)) / ((worldPosition(z) - cameraPosition(z)) * K)
... come puoi vedere, stiamo basando la posizione di rendering sulla distanza z
tra il punto corrente e la telecamera.
Gioca con la posizione z della videocamera fino a quando non vedi i punti renderizzati. Ma quello che vedrai è che tutti i punti verranno visualizzati attraverso la linea centrale dello schermo. Quindi dobbiamo porvi rimedio. Prova K=1
vs. K=10
per vedere la differenza.
Ora puoi spostare la videocamera y
per vedere come la videocamera va al di sopra e al di sotto del piano dei punti (ovvero i punti verranno renderizzati, corretti in prospettiva, sotto o sopra la linea mediana dello schermo, rispettivamente, mentre sposti la videocamera su e giù ).
Queste sono linee guida molto approssimative. Esistono diversi dettagli di implementazione che dipenderanno da te. Il primo passo è solo quello di visualizzare qualcosa, quindi modificare da lì. Un dettaglio che viene in mente è che se si desidera che la telecamera assomigli di più al suolo, è necessario spostare l'origine del rendering verso l'alto, più vicino alla parte superiore della finestra. Un altro dettaglio è che la tua distanza tra la fotocamera e il punto potrebbe essere necessario includere un rapporto di scatto ... Penso che l'utilizzo tan
offra una prospettiva più realistica. Non ricordarti chiaramente di questo, ma vedrai rapidamente se la prospettiva sembra strana e può adattarsi di conseguenza. Non posso essere più specifico senza riscrivere un campione.
Deformazione e ridimensionamento per tabellone (richiesto)
Ora che puoi vedere la prospettiva tra le tue posizioni di punti e aggiungere, rimuovere o spostare le posizioni (come con i personaggi) a piacimento, devi anche applicare la prospettiva ai singoli sprite che saranno radicati in quelle posizioni.
In D2, mi è sempre sembrata una semplice funzione di curvatura laterale che si applica più ai cartelloni che si trovano nella parte inferiore dello schermo, che a quelli in alto, e anche di più man mano che ti allontani dalla linea mediana che scende lo schermo.
Ci possono essere alcuni ridimensionamenti verticali applicati anche ai cartelloni pubblicitari, ad es. gli alberi si accorciano rispetto alla loro scala prevista, più vicino alla parte inferiore dello schermo (per far sembrare che la telecamera guardi verso il basso sugli alberi - ho scoperto che gli alberi di Tristram sono il modo migliore per esplorarlo in sicurezza, nel giorno;)).
Quello che vorrei fare è:
- Attiva la funzione di ridimensionamento di base in base alla distanza dalla fotocamera al suolo in punti diversi. Quindi avresti un ridimensionamento simile per ogni linea di scansione.
- Solo dopo averlo fatto, avrei guardato l'ordito laterale, prima in base alla distanza dalla linea mediana che corre lungo lo schermo.
- Infine, vorrei indagare su come quell'ordito laterale è influenzato dalla distanza lungo lo schermo (e ho la sensazione che un semplice trig ratio sarebbe al centro di questo).
Piastrellatura corretta in prospettiva (lettura non obbligatoria se si utilizza Unity!)
Speriamo che quanto sopra ti fornisca sprite "alzati" correttamente posizionati e deformati (cioè oggetti che si trovano perpendicolarmente al piano terra, come personaggi, alberi, case).
Tuttavia, devi anche considerare come far deformare correttamente e senza soluzione di continuità le piastrelle del terreno. E penso che scoprirai che è la parte che, in particolare, ha richiesto una GPU su D2. Ricordo che su sistemi senza GPU, l'opzione prospettiva era disabilitata. La ragione di ciò sarebbe quasi sicuramente stata che la GPU può prendere una superficie di trama e applicare la correzione prospettica su di essa molto rapidamente, senza problemi tra le tessere e senza preoccupazioni sull'esecuzione di trasformazioni non affine nel codice dell'applicazione, che comporta alcuni matematici a matrice e può essere un po 'costoso:
Ho alcuni suggerimenti per farvi fronte:
- (Unity) Utilizzare una Unity Camera per fornire il rendering del piano di terra piatto e strutturato, quindi gestire le distorsioni del tabellone separatamente in base alle posizioni dello schermo.
- Esegui questa logica (o anche tutta la logica di rendering) negli shader GPU.
- Non usare mai piastrelle a terra. Invece, basta usare gli sprite dei punti - proprio come i personaggi stessi - su un piano uniformemente colorato (es. Verde per l'erba) per fornire dettagli affinché quell'aereo non sembri noioso. Ciò aumenterà i costi di rendering, ma è sicuramente il modo più semplice per affrontare questo problema.