2011-07-05 10 views
10

Continuo a colpire questo problema quando si costruisce motori di gioco in cui le mie lezioni vogliono assomigliare a questo:architettura OO per il rendering in giochi basati dello shader

interface Entity { 
    draw(); 
} 

class World { 
    draw() { 
    for (e in entities) 
     e.draw(); 
    } 
} 

questo è solo pseudo-codice per mostrare più o meno come il disegno accade. Ogni sottoclasse di entità implementa il proprio disegno. Il mondo scorre attraverso tutte le entità senza un ordine particolare e dice loro di disegnarsi a uno a uno.

Ma con la grafica basata su shader, questo tende ad essere orribilmente inefficiente o addirittura non fattibile. Probabilmente ogni tipo di entità avrà il proprio programma shader. Per ridurre al minimo le modifiche al programma, tutte le entità di ogni particolare tipo devono essere disegnate insieme . Semplici tipi di entità, come le particelle, possono anche voler aggregare il loro disegno in altri modi, come la condivisione di un grande array di vertici. E diventa molto peloso con la fusione e tale in cui alcuni tipi di entità devono essere resi in determinati momenti rispetto agli altri, o anche in più occasioni per passaggi diversi.

Quello che normalmente si ottiene è una sorta di renderer singleton per ogni classe di entità che mantiene un elenco di tutte le istanze e le disegna tutte in una volta. Non è così male poiché separa il disegno dalla logica del gioco. Ma il renderer deve capire quale sottoinsieme di entità disegnare e ha bisogno di accedere a più parti differenti della pipeline grafica. È qui che il mio modello di oggetti tende a diventare disordinato, con un sacco di codice duplicato, accoppiamento stretto e altre cose brutte.

Quindi la mia domanda è: che cos'è una buona architettura per questo tipo di disegno del gioco che sia efficiente, versatile e modulare?

+0

Il fatto che tu lo stia separando da tutto il resto è buono per iniziare, e suona come se fosse disordinato perché è ... beh ... _messy_. ** Il pasticcio ** necessario è sfortunato, ma comunque necessario. Ma dubito che la vedrai come una risposta ... –

risposta

1

Questa non è una domanda facile a cui rispondere, poiché ci sono molti modi per affrontare il problema. Una buona idea è quella di esaminare alcuni motori di gioco/rendering e vedere come viene gestito lì. Un buon punto di partenza sarebbe Ogre, dal momento che è ben documentato e open source.

Per quanto ne so, separa i dati dei vertici dai componenti del materiale (shader) attraverso gli script di materiali incorporati. Il renderer stesso sa quale mesh deve essere disegnata in quale ordine e con quale shader (e i suoi passaggi).

So che questa risposta è un po 'vaga, ma spero di poterti dare un suggerimento utile.

8

Utilizzare un approccio a due fasi: Primo ciclo attraverso tutte le entità, ma invece di disegnare consentono di inserire riferimenti a se stessi in un (il) elenco batch di disegni. Quindi ordina l'elenco in base allo stato OpenGL e all'utilizzo dello shader; dopo l'ordinamento inserire oggetti di cambio di stato ad ogni transistione di stato.

Infine, scorrere l'elenco che esegue la routine di disegno di ciascun oggetto a cui si fa riferimento nell'elenco.

+0

e se avessi motori diversi? OpenGL, DirectX? – GorillaApe

+0

@Parhs: Né OpenGL né DirectX sono motori. Sono API. E questa prima fase chiamata "frame setup" viene solitamente eseguita in parte dal codice di rendering che parla con l'API e in parte dal codice di gestione delle scene. Ad esempio il frustum culling è qualcosa per cui il codice di scena è più adatto, lo stato di texture e shader deve essere ordinato dal codice di rendering. Inoltre non devi fare tutto in un solo passaggio. È perfettamente corretto attraversare dapprima (nel codice della scena) su tutti i riquadri di delimitazione, fino al frustum e alla selezione per profondità. Quindi passa questa lista al renderer per ulteriori perfezionamenti. – datenwolf

+0

Grazie per la risposta. Comunque il mio problema è qui.Hai detto "eseguendo la routine di disegno di ogni oggetto". Cosa succede se si desidera utilizzare più API (direct2d, opengl ecc.)? Voglio dire draw() all'interno di ogni oggetto dovrebbe avere l'implementazione per tutte le API? O il renderer si occupa anche del disegno? – GorillaApe

Problemi correlati