2012-12-13 8 views
13

Sto scrivendo un'app OpenGL ES 2.0 che esegue il rendering di un'isola 3D. Ho già il codice per generare una cupola del cielo intorno all'isola. Questo è un emisfero composto da triangoli che sovrappongono l'isola con z punto verso l'alto.Come si esegue il rendering di uno skydome convincente?

La cupola presenta alcune nuvole di spostamento molto semplici create utilizzando una trama di rumore perlin sovrapposta a se stessa e spostando velocità diverse.

Ma alla fine ho bisogno la cupola di rendere anche:

  • Sun (che tiene traccia nel cielo) Luna (tra cui fase)
  • Stelle (di notte)
  • terra lontana come texture statica
  • colori diversi per simulare la notte, alba, crepuscolo, giorno

ho bisogno di fare questo in modo molto efficiente in quanto andrà a finire o n Android anche se per il momento è in esecuzione in un'imbracatura di test. Quindi il sole, la luna e le stelle, ad esempio, saranno solo trame sebbene i loro punti possano essere tracciati con ragionevole accuratezza.

Ho già il codice per generare la cupola e il codice per tracciare un sole contro una data e un'ora. Quindi per lo più sono gli shader di cui ho bisogno e di cosa sono dotati.

C'è qualche esempio che dimostra queste cose? Ho trovato molte cose che fanno mappe cubiche di base o roba limitata, ma nulla al livello di sofisticazione di cui ho bisogno. Ovviamente dato che questo è OpenGL ES 2.0 deve essere fatto in shader.

Lo shader per la mia cupola cielo esistente esegue 2 livelli di rumore perlin per simulare le nuvole. La trama si avvolge continuamente così posso calcolare l'offset u in base all'angolo del vertice di una cupola nel piano xy (alimentando xey in atan) e l'offset v utilizzando il vertice z della cupola.

Il vertex shader dimostra come lo faccio:

#ifdef GL_ES 
precision mediump float; 
precision mediump int; 
#endif 

attribute vec4 aVertex; 

uniform mat4 uPMVMatrix; 
uniform float uTime; 
uniform float uSkyDomeRadius; 

const float PI = 3.1415926535897932384626433832795; 

varying vec2 texCoord0, texCoord1; 

void main() 
{ 
    vec2 centre = vec2(600., 600.); 

    gl_Position = uPMVMatrix * aVertex; 

    float slow_time = uTime/100.; 

    vec2 dome_point = aVertex.xy - centre; 
    float tex_u = atan(dome_point.x, dome_point.y);///(.25 * PI); 
    float tex_v = aVertex.z/(uSkyDomeRadius * .5); 

    texCoord0 = vec2(tex_u/2.0 + slow_time, tex_v/2.0); 
    texCoord1 = vec2(tex_u + slow_time/2.0, tex_v); 
} 

Io uso anche un momento per compensare u un po 'ogni fotogramma in modo che le nuvole si muovono. Funziona benissimo eccetto che atan passa da -PI a PI e improvvisamente texCoord0 e texCoord1 valorizzano le interpolazioni del frammento shader separate da una grande distanza che blocca l'interpolazione.

Il modo migliore per descriverlo è che se ho 16 triangoli nella mia base, allora l'interpolazione da 0/16 a 1/16 funziona, da 1/16 a 2/16 funziona e così via. Ma quando arrivo da 15/16 a 0/16 l'interpolatore torna indietro e la grande variazione fa sì che lo shader di frammenti ripeta la trama più e più volte in un piccolo spazio che porta a strisce come mostrato.

Interpolation goes haywire as angle goes into reverse

non riesco a vedere alcun modo per avere una perfetta visione a 360 gradi Credo che l'unico modo in cui io risolvere questo problema è se ruoto l'intera cupola in modo che la cucitura è sempre dietro la macchina fotografica, ma potrebbe ancora mostra se la telecamera punta direttamente verso l'alto di una cupola.

Un esempio funzionante con la fonte sarebbe grandioso specialmente se risolve questo tipo di problemi.

+0

domanda stupida ma può tex_x essere> PI o <-PI – BevynQ

+0

tex_x sarà sempre tra PI e -PI perché atan restituisce quei valori. Ho 16 triangoli alla base della cupola in modo che ogni base triangolare prescriva un arco di 2PI/16 o PI/8. Quindi v0 potrebbe essere il 3/16 e la v1 4/16th e così tex_x interpola correttamente. Il problema si presenta se v0 erano 15/16 e v1 erano 0/16 e l'interpolazione è completamente avvitata. Non riesco a pensare ad alcun modo per sistemarlo correttamente, quindi sto speculando sul fatto che dovrò ruotare la cupola in modo che la cucitura sia sempre dietro la macchina da presa e compensare qualsiasi cosa io mostri di una quantità equivalente. – locka

+0

Ho aggiornato la domanda per chiarire questo aspetto e ho rinominato tex_x e tex_y come tex_u e tex_v – locka

risposta

3

Il problema è che si utilizzano gli stessi vertici con un angolo di 0 ° e 360 ​​°. Quindi ora hai un triangolo in cui il primo vertice ha una coordinata di trama di 15/16, 0 e il secondo ha 0, 0 invece di 1,0.Per risolvere il problema, devi aprire la sfera in modo da avere una coppia di vertici nelle stesse posizioni spaziali, una per 0 ° e una per 360 °. In questo modo i due vertici possono avere diverse coordinate di trama e non ci saranno trame disturbate.

Per ruotarli è necessario utilizzare le modalità di avvolgimento, assicurarsi che l'involucro della trama sia impostato per la ripetizione. Se non è stato modificato, è necessario impostarlo correttamente, ma può essere impostato con la funzione glTexParameter, i parametri sono GL_TEXTURE_WRAP_S e GL_TEXTURE_WRAP_T e il valore deve essere GL_REPEAT. Quindi se un valore di trama è> 1 non si avvolge ma ripete la trama. Ora devi solo essere in grado di dire i vertici all'inizio della sfera (per i vertici a 0 °) da quelli alla fine (per i vertici a 360 °) in modo da poter correggere tex_u, probabilmente hai bisogno di un attributo aggiuntivo per quello .

+0

Grazie, ci provo. Sono consapevole del fatto che il problema è che l'angolo torna a zero in modo efficace, ma vedrò se riesco a generare lo skydome in qualche modo che compensi ciò come suggerisci. – locka