Oltre il l'Arte Retro Pixel con il 3D Flat Shaded 3D di Unity
() translation by (you can also view the original English article)
In questo tutorial, vi mostrerò come creare la grafica flat-shading 3D per il vostro gioco Unity e spiegherò come impiegarlo.
Oggi, ci sono una grande varietà di strumenti 3D e motori che permettono a chiunque di fare giochi 3D. Tuttavia, le sfide nell'arte 3D sono scoraggianti e spesso richiedono una grande quantità di tempo, impegno e competenza che lo sviluppatore solitario di videogiochi e l'hobbista non hanno. Modelli a basso numero di poligoni, in combinazione il flat shading, riportano lo stile dei primi anni '90, con tecniche che chiunque può imparare. E non è solo un ritorno al passato nostalgico; il flat-shading può essere facilmente combinato con tecniche moderne come le mappe di occlusione ambientale per dare al vostro gioco un look suggestivo e all'avanguardia.
Prendete il progetto Unity d'esempio da qui
Questo tutorial presuppone che si conosca già come fare modellazione 3D, o che siate capaci di trovare modelli 3D gratuiti su internet. Userò modelli d'esempio dal nulla; ci sono tonnellate di tutorial su internet su come iniziare con la modellazione 3D. Se si sta appena iniziando, posso raccomandare Wings 3D e SketchUp. Entrambi hanno interfacce estremamente accessibili rispetto alle applicazioni di modellazione professionali, ed esportano formati che Blender e Unity possono utilizzare.
Perché usare il Flat Shading?
Così avete deciso di sporcarvi le mani con Unity ed iniziare a fare un completo gioco in 3D. Forse non avete precedenti conoscenze artistiche, o forse avete fatto un po' di grafica per i giochi 2D; in entrambi i casi, è facile rendersi conto che per creare giochi 3D è richiesto un grande insieme di competenze. Non solo è necessario imparare a creare modelli 3D, è necessario di smontare i modelli per disegnarci correttamente una texture sulla sua superficie. È inoltre necessario creare la texture, ovviamente.
Che cosa succede se avete appena creare il modello, finito e pronto per il vostro gioco dopo averlo colorato e ombreggiato? Potreste finire con qualcosa di simile:
O questo:
Certo, il look è spartano ma questo è il punto! Se si sta puntando ad un nostalgico '90, o ad più un moderno aspetto astratto, o semplicemente si vuole risparmiare un sacco di tempo per fare assets per un gioco, il flat shading è una scelta eccellente di stile per principianti ed esperti 3D allo stesso modo.
Se avete appena iniziato con la grafica dei giochi, la semplicità del flusso di lavoro vi permette di concentrarvi sui fondamentali: imparare a creare un modello 3D con una bella silhouette e la sua forma, e la colorazione con un piccolo set di colori. Concentrandosi su questi fondamenti si apprendono le tecniche di base di questa arte senza distrazioni.
Come funziona il Flat Shading
Ogni modello 3D è composto da un insieme di vertici che determinano la sua forma. Per ogni vertice, c'è anche un vettore chiamato normale, pensatelo come un piccolo spillo che spunta dal vertice.
Il motore di rendering utilizza la normale di ogni vertice e confronta la sua direzione con la direzione di qualsiasi fonte di luce(i) in entrata e con la direzione in cui la telecamera è rivolta, per determinare la quantità di luce da applicare a tale vertice.
Il renderer svanisce lentamente la quantità di luce da un vertice all'altro, dando al modello di base 3D un aspetto "morbidoso". Se non si applica una texture (e spesso, anche se lo si fa), ha un aspetto davvero terribile su tutto ciò che non è una superficie "morbidosa" tutta curve:



Con il flat shading, l'intera superficie di un poligono riceve una quantità uniforme di luce, calcolata da un applicazione normale verso l'esterno dal centro del poligono:



Le applicazioni di modellazione moderne utilizzano "spigoli" o "gruppi di smoothing (ammorbidire)" per regolare le normali ai vertici del proprio modello in modo che corrisponda al poligono cui sono adiacenti, facendo si che in tal modo che venga uniformemente ombreggiato flat. Un artista 3D esperto lo utilizzerà per rendere spigoli vivi come fossero taglienti e quelle piatte per renderle piatte, ma noi siamo interessati a fare apparire tutto il modello tagliente e piatto. Per fortuna, Unity lo rende molto semplice.
Tecnica Base
Se avete abbastanza familiarità con il vostro strumento di modellazione è possibile dare al vostro modello un aspetto flat shaded impostando tutti i bordi come "hard". Tuttavia, in Unity si può semplicemente scegliere di lasciargli creare automaticamente gli spigoli:
Passo 1
Cliccate sul vostro modello nella finestra Project per ottenere gli Import Settings dal pannello Ispector.

Passo 2
Andate alla sezione Normals & Tangents e nel menu a discesa Normals, selezionate Calculate.

Passo 3
Impostate Smoothing Angle a 0
e fate clic su Apply.

Unity trasformerà ogni bordo con un angolo molto acuto in un bordo molto più marcato. Vogliamo che tutti i nostri bordi siano marcati e l'effetto lo otterremo naturalmente impostando a 0
.
Sperimentate liberamente con diversi angoli il livellamento, può essere un modo incredibilmente semplice per dare un aspetto completamente diverso, a seconda della geometria del modello.



Passo 4
Ora che abbiamo il nostro modello flat shad, abbiamo bisogno di dargli un po' di colore! Ci sono molti modi per farlo, ma alcuni sono migliori di altri:
- Selezionate le diverse parti del modello ed impostate un materiale diverso per ciascun colore che si desidera utilizzare.
- Assegnate i colori dei vertici nel vostro programma di modellazione.
- Create una "tavolozza di texture" che contiene una serie di quadrati colorati e mappate la texture sul modello.
Io preferisco di gran lunga l'ultimo metodo, che vi descriverò qui sotto. Normalmente, dopo la creazione di un modello 3D, è necessario srotolarlo a fatica (n.d.a.unwrap significa proiettare in 2D il modello per ottenere una mappa da texturizzare) per abbinagli una texture artigianale. Tuttavia, dal momento che siamo interessati solo ad avere un singolo colore per ogni poligono, non importa come viene il vostro lavoro di srotolatura UV, potrebbe essere solo un miscuglio casuale di vertici, basta che dia una corretta colorazione!
Il primo passo nella colorazione è quello di creare la texture. Per il nostro esempio, diciamo che vogliamo quattro colori:

Quindi, caricate il modello 3D completo nel modellatore che avete scelto e caricate la texture. Selezionate tutte le facce del modello che si vuole abbiano un certo colore e srotolatele automaticamente la sua UV (n.d.a. coordinata di unwrap). Il risultato sarà probabilmente un miscuglio confuso di poligoni.



Come ho detto, però, in realtà non importa. Spostate tutti i poligoni uno sopra l'altro e scalateli in un piccola area che rientri in una dei rettangoli della tavolozza della texture. Poi, trascinateli nella parte superiore del colore scelto.



Date un'occhiata al vostro modello; le corrette sezione della texture ora hanno il colore giusto! Ripetere questo processo per il resto delle facce del modello, di nuovo la selezionate e srotolatele in base al colore che volete abbiano. Se si commette un errore, non è un grosso problema, basta selezionare le facce di nuovo, srotolare di nuovo se necessario, e metterle al posto giusto sulla texture. Lo stesso non si può dire per una "reale" mapping UV!



Voilà! Avete un modello flat-shaded colorato che è possibile importare nel vostro gioco.



E gli altri metodi?
Nel caso ve lo stiate chiedendo, ecco alcuni motivi per evitare gli altri due metodi:
Molteplici Materiali
Questo metodo crea un sacco di materiali di cuisi dovrà tenere traccia di in Unity e cosa ancora più importante, Unity non lo farà predispone dinamicamente i vostri modelli e anzi utilizza un intero chiamata di disegno per ordinare ogni materiale, che è spesso il più piccolo collo di bottiglia nei moderni hardware grafici.
In poche parole, si otterranno prestazioni terribili se si un largo uso di questo metodo.
Colorazione dei vertici
In realtà funziona abbastanza bene, ed in effetti si consiglia di utilizzare questo a seconda delle vostre particolari esigenze o del flusso di lavoro artistico. Tuttavia, noterete qualcosa subito: quando si importa il modello e si utilizza uno shader Diffuse, la vostra colorazione dei vertici non appare!
Questo perché gli shader di base li ignorano; avrete bisogno di usare shader speciali che effettivamente utilizzano i dati relativi ai colori di vertice. Questi possono essere facilmente recuperati, ma le cose si complicano se si vogliono anche altri effetti di rendering con altri shaders: questi shader spesso non usano la colorazione dei vertici e avrete bisogno di modificare lo shader da soli.
Se non si conosce già come scrivere uno shader, questo può farvi perdere tempo che altrimenti potreste spendere nel resto del vostro gioco. Inoltre, potrebbe essere io, ma trovo molto più facile cambiare colori multipli in una sola volta con una texture sola piuttosto che impostarli manualmente con un modellatore o in-game con uno script.
Ottimizzazione
Ora che avete una tavolozza di texture e avete appreso una tecnica di base, si può continuare a creare il resto dei modelli per il vostro gioco. Come si può sospettare, possiamo solo continuare ad aggiungere colori alla palette e utilizzando la stessa texture per tutto il gioco.
In realtà ci sono alcuni grandi vantaggi prestazionali nel farlo: se utilizzate lo stesso materiale per l'intero gioco, Unity di solito disegnerà tutti gli oggetti in modo più efficiente "preparandoli" in anticipo. Come ho detto prima, le "draw calls" (n.d.a. chiamate del motore grafico per disegnare gli oggetti) sono un serio ostacolo nella computer grafica ed è una buona idea per mantenerle al minimo.
L'unità cercherà automaticamente di disengnare la vostra scena con meno chiamate possibili se si utilizza un unico materiale per ogni cosa, anche se ogni modello deve essere ridimensionato allo stesso modo e ha meno di 300 vertici. Vi informerà quanto sta facendo bene nella finestra Stats:






Suggerimento: Se volete sapere di più sul batching (n.d.a. operazione che ne anticipa e ottimizza altre), assicuratevi di controllare la documentazione Unity sull'argomento. Questa dovrebbe essere una lettura obbligatoria per chiunque sia interessato allo svolgimento del rispettivo gioco!
Modifica dei colori al volo
Disponete di un insieme di modelli che flat shaded e colorati, tutto sembra a posto, ma cosa succede se si vuole modificare i colori, mentre il gioco è in esecuzione?
Per esempio, diciamo che avete uno script che fa apparire il vostro aereo, ma in seguito si desidera colorarlo di blu se è amichevole o rosso se si tratta di un nemico. Potremmo certamente creare tavolozze separate e distinte di materiali, ma ciò significhere perdere l'ottimizzazione delle prestazioni dato dal batching per questi due tipi di aeroplani.
Questo non è un grosso problema se ci pochi di loro sono visibili in una sola volta. Tuttavia, prendiamo ad esempio un terreno procedurale generato fatto di tonnellate e tonnellate di tessere (tile) o cubi, con molti tipi di terreno diversi, come un certo gioco sandbox molto popolare. Questo significherebbe un sacco di chiamate draw ma non temete, c'è un modo per continuare ad utilizzare un solo materiale!



Ricordate come avete colorato il vostro modello spingendo le sue coordinate UV dentro i rettangoli colorati? Unity consente di modificare i vertici del modello al volo, comprese le coordinate UV, quindi per ogni tipo di terreno diverso si può semplicemente spostare le coordinate UV nella casella di colore corretto tramite script.
Create un nuovo script C# in Unity chiamato PaletteColorizer
e incollateci questo codice:
1 |
using UnityEngine; |
2 |
using System.Collections; |
3 |
|
4 |
public class PaletteColorizer : MonoBehaviour |
5 |
{ |
6 |
public int colorsPerRow = 4; |
7 |
public int colorIndex = 0; |
8 |
public bool overrideUVs = false; |
9 |
|
10 |
void Awake () |
11 |
{ |
12 |
if(!enabled) |
13 |
{ |
14 |
return; |
15 |
} |
16 |
|
17 |
SetUVsToColor(colorIndex); |
18 |
} |
19 |
|
20 |
void Update() |
21 |
{ |
22 |
} |
23 |
|
24 |
public void SetUVsToColor(int colorIndex) |
25 |
{ |
26 |
if(overrideUVs) |
27 |
{ |
28 |
SetUVs(gameObject, GetColorOffset(colorIndex)); |
29 |
} |
30 |
else |
31 |
{ |
32 |
TranslateUVs(gameObject, GetColorOffset(colorIndex)); |
33 |
} |
34 |
} |
35 |
|
36 |
Vector2 GetColorOffset(int colorIndex) |
37 |
{ |
38 |
Vector2 offset = new Vector2(); |
39 |
float row = Mathf.Floor(colorIndex / colorsPerRow); |
40 |
float step = 1.0f / colorsPerRow; |
41 |
|
42 |
offset.x = (colorIndex - (row * colorsPerRow)) * step; |
43 |
offset.y = (1.0f - (row / colorsPerRow)); |
44 |
|
45 |
return offset; |
46 |
} |
47 |
|
48 |
static public void TranslateUVs(GameObject obj, Vector2 offset) |
49 |
{ |
50 |
var meshFilter = obj.GetComponent(); |
51 |
Mesh mesh = meshFilter.mesh; |
52 |
|
53 |
var newUVs = new Vector2[mesh.uv.Length]; |
54 |
|
55 |
for(int i=0; i < mesh.uv.Length; i++) |
56 |
{ |
57 |
newUVs[i] = new Vector2(mesh.uv[i].x + offset.x, mesh.uv[i].y + offset.y); |
58 |
} |
59 |
|
60 |
mesh.uv = newUVs; |
61 |
} |
62 |
|
63 |
static public void SetUVs(GameObject obj, Vector2 offset) |
64 |
{ |
65 |
var meshFilter = obj.GetComponent(); |
66 |
Mesh mesh = meshFilter.mesh; |
67 |
|
68 |
var newUVs = new Vector2[mesh.uv.Length]; |
69 |
|
70 |
for(int i=0; i < mesh.uv.Length; i++) |
71 |
{ |
72 |
newUVs[i] = new Vector2(offset.x + 0.01f, offset.y - 0.01f); |
73 |
} |
74 |
|
75 |
mesh.uv = newUVs; |
76 |
} |
77 |
} |
Per utilizzare questo script, è sufficiente aggiungerlo come un componente ad ogni oggetto di gioco con un materiale che usa una tavolozza texture, impostare il numero di colori per riga ed impostare l'indice di colore (a partire da 0 nell'angolo superiore sinistro e contare fino in basso a destra).
Se le coordinate UV del vostro modello non sono impostate per adattarsi all'interno delle tavolozza texture (come ad esempio nel caso del quadrato "acqua" intorno agli esagoni), selezionare il check Override UVs; come potete vedere sopra, questo renderà lo script capace di riscrivere tutte le nuove coordinate piuttosto che spostare quelle esistenti.
Una cosa da tenere a mente per questo metodo è che, quando si modificano le mesh poligonali (gli insiemi di vertici), Unity creerà tranquillamente una nuova mesh poligonale in memoria. Se si esegue questa operazione particolarmente spesso su un gran numero di mesh, si potrebbe incorrere in problemi di memoria, vi consiglio di cercarvi un sistema di caching e di condivisione di tutte le mesh colorate allo stesso modo. Tuttavia, con un numero ragionevole di modelli a basso numero di poligoni non ci sarà bisogno di preoccuparsi.
Baked Ambient Occlusion (Occlusione Ambientale Precalcolata)



Il flat shading non deve necessariamente essere sempre accoppiato a blocchi uniformi di colore. Un modo con cui è possibile aggiungere qualche sottile dettaglio ed un aspetto più realistico e "polveroso" a qualsiasi superficie è quello di aggiungere l'occlusione ambientale. Unity Pro (n.d.a.si riferisce a Unity3d 4.x) fornisce metodii per aggiungere l'ambient occlusion come filtro di post-processing, ma voglio mostrarvi un modo per aggiungere quel tocco di smalto senza la necessità della versione Pro e nemmeno senza particolari shaders.



Tutto quello che dovete fare è srototolare il vostro modello e "bake" (precalcolare, precuocere) l'effetto occlusione ambientale su una texture. Questo non richiede altro tempo se non quello di srotolare correttamente il modello e poco più, dopo questo passo è solo questione di pochi clic e di un po' di armeggio nel vostro programma di disegno per dare al modello un aspetto reale più avant-garde.
Passo 1
In primo luogo, avviamo Blender con una scena vuota: Premere A
per selezionare tutti gli oggetti nella scena di avvio, premete Canc
, quindi premere D
per confermare. Se non si desiderano luci o camere perché queste verrebbero importati come oggetti spazzatura e vuoti in Unity.
Passo 2
Quindi, importare il modello. (File > Import > Wavefront (.obj)). Per questo esempio, cominciamo con un masso.

Passo 3
Aprite l'Editor UV e create una texture che abbia la qualità desiderata. Sono abbastanza avaro, di solito mi tengo a 256x256px per tutto (una roccia o un albero) tranne che il giocatore e vado di dimensioni maggiori solo per oggetti molto grandi (come le montagne su cui si cammina).



Passo 4
Ora srotolate la mappatura del modello. Ci sono molti modi per farlo, tutti gestiti in modo molto più dettagliato di quanto potessi mai sperare, quindi vi prego di consultare la documentazione di Blender o altri tutorial online su come correttamente ed efficientemente si fa l'unwrap delle coordinate di mapping dei vostri modelli.
Passo 5
Ora che si dispone di un modello srotolato, si è pronti a precalcolare la ambient occlusion sulla vostra texture. Blender creerà l'ambient occlusion direttamente sulla vostra texture, rispettando le coordinate UV appena srotolate. Basta seguire questi passaggi:
- Fare clic sul pulsante Render (l'icona della fotocamera) sul pannello delle Properties sul lato destro dello schermo.
- Scorrere verso il basso alla sottosezione Bake (in basso) ed espandetelo.
- Cambiate il Bake Mode da Full Render a Ambient Occlusion.
- Fare clic sul pulsante Bake direttamente sopra.




Passo 6
Ora avete la texture AO appena sfornata (cotta a puntino!) ed un modello che ha le UV corrette adatte ad usarlo. Salvate la texture di un file immagine ed esportate il modello in Blender in un formato che Unity può utilizzare (ad esempio .fbx
).
Passo 7
A seconda delle esigenze, potete usare la texture così come è. È sufficiente creare un materiale Diffuse che utilizzi la nuova texture di AO e impostare il colore a qualcosa che sia per voi piacevole.



Comunque, è probabile che desideriate avere modelli con più colori, come ad esempio un albero. Vi serve solo seguire alcuni passaggi aggiuntivi. Seguite le indicazioni di cui sopra per creare una texture AO precalcolata per il vostro modello di albero. Questa volta, però, vi consigli di tenere traccia di dove si mettono le coordinate UV, perché avrete bisogno di colorare manualmente queste posizioni sulla texture.
Sarebbe saggio raggruppare le vostre aree di UV per colore. In questo esempio, assemblo le parti del tronco nella parte superiore della texture e le parti della chioma sul fondo.






Passo 8
Aprite la vostra texture AO con il vostro programma di grafica preferito (va bene qualsiasi che supportai i livelli o layer, come ad esempio GIMP). Create un nuovo livello e mettetelo sopra il livello di AO, quindi utilizzate il livello AO come guida per colorare il nuovo livello secondo i colori che volete vedere nel modello.
Utilizzare lo strumento Lazo, o un altro strumento di selezione della vostra scelta, per selezionare le parti della texture che volete colorare, poi riempitele con il colore corretto.






Passo 9
Ora avete creato i colori, quindi è il momento per il passaggio finale: mescolare la AO sopra gli altri colori. Spostare il livello AO sopra lo strato di colore e cambiate il metodo di fusione su Multiply.



Impostare l'opacità del livello a vostro piacimento. Utilizzare il proprio giudizio, ma ricordatevi di salvare quella percentuale, dal momento che la applicherete, per un effetto uniforme, su tutte le texture su cui vorrete usare lo stesso metodo di miscelazione.



Salvate la texture in un file e importatelo in Unity insieme al modello dell'albero. Create un materiale proprio come avete fatto per il masso, utilizzando la texture che avete appena creato.



Che è praticamente molto! Utilizzare questa tecnica su tutti i vostri modelli darà a tutta la scena un aspetto tangibile più lucido di quanto si potrebbe ottenere con il solo flat-shading.
Si può notare che i vostri materiali utilizzano uno shader diffuse basilare. Una delle cose belle sull'utilizzo delle AO precalcolate e miscelate direttamente sopra le texture del colore è che è possibile utilizzare questa texture con qualsiasi altro shader che prende una texture di diffusione ... senza che sia necessario alcun codice specifico per AO!
Conclusioni
Ora avete a portata di mano una cassetta degli attrezzi di tecniche grafiche che è possibile utilizzare per creare un intero gioco flat shaded. Con un po' di pratica, è possibile realizzare una grafica mozzafiato pronta all'uso e da renderizzare in modo efficiente.