2012-04-22 12 views
17

Quindi, ho un impostore (la geometria reale è un cubo, possibilmente ritagliato, e la geometria del filtro è una spugna di Menger) e ho bisogno di calcolarne la profondità.GLSL gl_FragCoord.z ​​Calcolo e impostazione gl_FragDepth

Posso calcolare la quantità da compensare nello spazio mondiale abbastanza facilmente. Sfortunatamente, ho passato ore a non riuscire a perturbare la profondità con esso.

Gli unici risultati corretti posso ottenere sono quando vado:

gl_FragDepth = gl_FragCoord.z 

Fondamentalmente, ho bisogno di sapere come gl_FragCoord.z ​​è calcolato in modo che io possa:

  • Prendere la trasformazione inversa da gl_FragCoord.z ​​allo spazio degli occhi
  • Aggiungere la profondità perturbazione
  • Trasformare questa profondità perturbata nello stesso spazio dell'originale gl_FragCoord.z.

Mi scuso se sembra una domanda doppia; c'è un certo numero di altri post qui che affrontano cose simili. Tuttavia, dopo averli implementati tutti, nessuno funziona correttamente. Piuttosto che cercare di sceglierne uno per ottenere aiuto, a questo punto, sto chiedendo il codice completo che lo faccia. Dovrebbero essere solo poche righe.

+0

Hai scritto anche un vertex shader? o solo un frammento shader? –

+2

Non ti darò codice su principio generale, ma posso darti [questo link al Wiki OpenGL] (http://www.opengl.org/wiki/Compute_eye_space_from_window_space). Così come questo link ad un mio tutorial su [impostors e depth che mostra come fare anche questo] (http://www.arcsynthesis.org/gltut/Illumination/Tut13%20Deceit%20in%20Depth.html). Trasformare la profondità indietro è banale. –

+0

Michael: sì, ma è solo un passaggio attraverso lo shader.Come succede, i calcoli sono fatti nello spazio mondiale, quindi posso calcolare lo spazio degli occhi nel programma frammento. Nicol, avevo già visto quella pagina. Lo implemento come: vec4 clip_pos = gl_ProjectionMatrix * vec4 (eye_pos, 1.0); float ndc_depth = clip_pos.z/clip_pos.w; gl_FragDepth = (((clip_far-clip_near) * ndc_depth) + clip_near + clip_far)/2.0; Sfortunatamente, la profondità sembra non rientrare nell'intervallo di profondità, anche se non c'è compensazione. Grazie, – imallett

risposta

28

Per riferimento futuro, il codice della chiave è:

float far=gl_DepthRange.far; float near=gl_DepthRange.near; 

vec4 eye_space_pos = gl_ModelViewMatrix * /*something*/ 
vec4 clip_space_pos = gl_ProjectionMatrix * eye_space_pos; 

float ndc_depth = clip_space_pos.z/clip_space_pos.w; 

float depth = (((far-near) * ndc_depth) + near + far)/2.0; 
gl_FragDepth = depth; 
+0

Non dovrebbe "gl_DepthRange.far" e "gl_DepthRange.near;" essere sostituito con gli intervalli vicini e lontani della matrice di proiezione invece dei valori del piano della clip? – Tara

+0

Niente affatto. gl_DepthRange non è la stessa cosa dei valori del piano vicino e lontano usati per calcolare la matrice di proiezione. Tuttavia potrei fraintendere il tuo punto. – Tara

+0

@Dudeson I piani di clip determinano semplicemente, tramite la matrice di proiezione, quali valori verranno mappati all'esterno del NDC (e quindi verranno ritagliati dall'hardware). Abbiamo finito con loro una volta specificata la matrice di proiezione. Nel frattempo, 'gl_DepthRange. (Ne | f) ar' è l'intervallo del buffer di profondità ed è necessario per convertire da NDC al buffer di profondità. HTH – imallett

4

Per un altro riferimento futuro, questa è la stessa formula dato da imallett, che stava lavorando per me in un'applicazione OpenGL 4.0:

vec4 v_clip_coord = modelview_projection * vec4(v_position, 1.0); 
float f_ndc_depth = v_clip_coord.z/v_clip_coord.w; 
gl_FragDepth = (1.0 - 0.0) * 0.5 * f_ndc_depth + (1.0 + 0.0) * 0.5; 

Qui, modelview_projection è una matrice di proiezione del modello 4x4 e v_position è la posizione oggetto-spazio del pixel che viene eseguito il rendering (nel mio caso calcolato da un raymarcher).

L'equazione proviene dalla sezione di window coordinatesthis manual. Si noti che nel mio codice, vicino è 0.0 e lontano è 1.0, che sono i valori predefiniti di gl_DepthRange. Notare che gl_DepthRange è non la stessa cosa della distanza vicina/remota nella formula per perspective projection matrix! L'unico trucco sta usando il 0.0 e 1.0 (o gl_DepthRange nel caso in cui hai veramente bisogno di cambiarlo), ho lottato per un'ora con l'altra gamma di profondità - ma che è già "forno" nel mio (prospettiva) matrice di proiezione .

Si noti che in questo modo, l'equazione contiene in realtà solo un singolo multiplo per una costante ((far - near)/2) e una singola aggiunta di un'altra costante ((far + near)/2). Confrontalo per moltiplicare, aggiungere e dividere (eventualmente convertito in multiplo da un compilatore ottimizzante) che è richiesto nel codice di imallett.