2011-02-04 12 views
20

Desidero regolare i colori in base alla posizione xyz in cui si trovano nel mondo.GLSL: come ottenere la posizione del mondo pixel x, y, z?

Ho provato questo nel mio frammento di shader:

varying vec4 verpos; 

void main(){ 
    vec4 c; 
    c.x = verpos.x; 
    c.y = verpos.y; 
    c.z = verpos.z; 
    c.w = 1.0; 

    gl_FragColor = c; 
} 

ma sembra che i colori cambiano a seconda del mio angolazione/posizione, come faccio a fare le coordinate indipendenti dalla mia posizione della fotocamera/angolo?

Heres mia vertex shader:

varying vec4 verpos; 

void main(){ 
    gl_Position = ftransform(); 
    verpos = gl_ModelViewMatrix*gl_Vertex; 
} 

Edit2: titolo cambiato, quindi voglio coordinate mondo, non a schermo coordinate!

Edit3: aggiunto il mio codice completo

+2

Non moltiplicare dal tuo gl_ModelViewMatrix. – Hannesh

risposta

27

In vertex shader avete gl_Vertex (o qualcosa d'altro, se non si utilizza gasdotto fisso), che è la posizione di un vertice in coordinate modello. Moltiplica la matrice del modello di gl_Vertex e otterrai la posizione del vertice nelle coordinate del mondo. Assegnalo a variando la variabile, quindi leggi il suo valore in framment shader e otterrai la posizione del frammento nelle coordinate del mondo.

Ora il problema è che non si dispone necessariamente di una matrice modello se si utilizza la matrice modelview predefinita di OpenGL, che è una combinazione di matrici di modelli e di viste. Di solito risolvere questo problema avendo due matrici separati invece di una sola matrice modelview:

  1. matrice modello (modello mappe coordinate coordinate mondo), e
  2. vista matrice (mappe coordinate globali a telecamera).

Quindi basta passare due diverse matrici al vertex shader separatamente. Puoi farlo definendo

uniform mat4 view_matrix; 
uniform mat4 model_matrix; 

All'inizio del vertex shader. E allora invece di ftransform(), dicono:

gl_Position = gl_ProjectionMatrix * view_matrix * model_matrix * gl_Vertex; 

Nel programma principale è necessario scrivere i valori di entrambe queste nuove matrici. Innanzitutto, per ottenere la matrice di visualizzazione, effettuare le trasformazioni della telecamera con glLoadIdentity(), glTranslate(), glRotate() o gluLookAt() o qualunque cosa si preferisca normalmente, quindi chiamare glGetFloatv (GL_MODELVIEW_MATRIX, & array); per ottenere i dati della matrice su un array. E in secondo luogo, in modo simile, per ottenere la matrice del modello, chiamate anche glLoadIdentity(); e fai le trasformazioni dell'oggetto con glTranslate(), glRotate(), glScale() ecc. e infine chiama glGetFloatv (GL_MODELVIEW_MATRIX, & array); per ottenere i dati matrix da OpenGL, in modo da poterli inviare al vertex shader. Soprattutto notare che è necessario chiamare glLoadIdentity() prima di iniziare a trasformare l'oggetto. Normalmente si dovrebbe prima trasformare la fotocamera e quindi trasformare l'oggetto che risulterebbe in una matrice che esegue sia la vista che le funzioni del modello. Ma poiché si utilizzano matrici separate, è necessario reimpostare la matrice dopo le trasformazioni della telecamera con glLoadIdentity().

gl_FragCoord sono le coordinate dei pixel e non le coordinate del mondo.

+1

@ltjax grazie, modificato la mia risposta. – kynnysmatto

+0

Non riesco a farlo funzionare, varia ancora i colori quando cambio la posizione/rotazione della mia videocamera. vedere il mio codice corrente nelle modifiche. – Rookie

+0

@Rookie, mi dispiace, ho modificato la mia risposta un paio di volte. hai letto e capito questa ultima versione? – kynnysmatto

-2

Il modo più semplice è passare la posizione del mondo verso il basso dal vertex shader tramite una variabile variabile.

Tuttavia, se è davvero necessario ricostruirlo da gl_FragCoord, l'unico modo per farlo è di invertire tutti i passaggi che hanno portato alle coordinate gl_FragCoord. Consulta le specifiche OpenGL, se davvero devi farlo, perché sarà necessaria una profonda comprensione delle trasformazioni.

10

Oppure si può semplicemente dividere la coordinata z con la coordinata w, che essenzialmente non-fa la proiezione prospettica; dandoti le tue coordinate del mondo originale.

ie.

depth = gl_FragCoord.z/gl_FragCoord.w; 

Naturalmente, questo funziona solo per le coordinate non ritagliate ..

quelli Ma chi se ne frega Clipped comunque?

+1

Questo essenzialmente mi darà la distanza dalla fotocamera a un frammento? Dolce ... è esattamente quello che volevo. – mpen

0

È necessario passare la matrice Mondo/modello come una divisa per il vertex shader, e poi moltiplicarlo per la posizione di vertice e inviarlo come un diverso allo shader frammento:

/*Vertex Shader*/ 

layout (location = 0) in vec3 Position 

uniform mat4 World; 
uniform mat4 WVP; 

//World FragPos 
out vec4 FragPos; 

void main() 
{ 
FragPos = World * vec4(Position, 1.0); 
gl_Position = WVP * vec4(Position, 1.0); 
} 

/*Fragment Shader*/ 

layout (location = 0) out vec4 Color; 

... 

in vec4 FragPos 

void main() 
{ 
Color = FragPos; 
} 
Problemi correlati