2014-09-11 17 views
9

Se si desidera eseguire il rendering di una geometria impostore (ad esempio a sphere), la pratica standard consiste nel disegnarla utilizzando due triangoli (ad esempio passando un vertice e creando una striscia triangolare con uno shader geometrico) .gl_PointSize Corrispondente alle dimensioni dello spazio mondiale

Questo è bello perché consente di impostare l'estensione del tabellone pubblicitario in modo piuttosto semplice: si calcolano direttamente le posizioni dello spazio del mondo reale.

Gli shader di geometria possono alternativamente generare primitive punti e non vedo un motivo per cui non dovrebbero. L'unico problema è trovare un modo per ridimensionare gl_PointSize in modo da ottenere quell'effetto.

L'unico precedente che ho trovato era this question (la cui risposta sono incerto è corretta) e this question (che non ha risposta).

Vale la pena notare che è abbastanza semplice scalare correttamente il punto con la distanza (facendo gl_PointSize = constant/length(gl_Position), ma questo non è controllabile, non si può dire ad esempio: voglio che questo punto assomigli a due unità del mondo . attraverso

Quindi: qualcuno sa come fare questo

risposta

12

un'idea dritto in avanti è quella di trasformare un punto nella parte superiore e inferiore della particella nello spazio dello schermo e la distanza questo annulla molto bene e che è?. abbastanza semplice da utilizzare con la coordinata y.

Il conto la scheda è allineata sullo schermo e le matrici di visualizzazione generalmente non si ridimensionano, quindi la dimensione delle particelle nello spazio del mondo è uguale a quella dell'occhio. Ciò lascia solo la proiezione per arrivare a NDC, la divisione per w e il ridimensionamento in base alla dimensione della finestra.

Una tipica matrice di proiezione, P, potrebbe apparire qualcosa di simile ...

[ +1.2990 +0.0000 +0.0000 +0.0000 ] 
[ +0.0000 +1.7321 +0.0000 +0.0000 ] 
[ +0.0000 +0.0000 -1.0002 -0.0020 ] 
[ +0.0000 +0.0000 -1.0000 +0.0000 ] 

Partendo y_eye, ay coordinate nello spazio degli occhi, la coordinata spazio dell'immagine y_image si ottiene in pixel ...

enter image description here

Collegamento raggio sopra/sotto il cartellone e sottrazioni annulla per ...

enter image description here

Oppure, nel testo, pixelSize = vpHeight * P[1][1] * radius/w_clip

Per una proiezione prospettica, P[1][1] = 1/tan(fov_y/2). w_clip è gl_Position.w, che è anche -z_eye (dallo -1 nella matrice prospettica). Per garantire che il tuo punto copra ogni pixel che desideri, potrebbe essere necessaria una piccola costante aggiuntiva.


Nota a margine: una sfera su un cartellone apparirà OK nel mezzo dello schermo. Se si dispone di una proiezione prospettica con un ampio campo visivo, una vera sfera dovrebbe deformarsi mentre si avvicina ai bordi dello schermo. È possibile ritrasmettere implicitamente la sfera virtuale per ciascun pixel nel tabellone per ottenere un risultato corretto, ma il contorno del tabellone per le affissioni dovrà essere regolato di conseguenza.risultati di Google rapidi: 1234


[EDIT ]
Beh, da quando ho preso la briga di provare questo mi butto i miei shader anche qui ...

Vertex:

#version 150 

in vec4 osVert; 

uniform mat4 projectionMat; 
uniform mat4 modelviewMat; 
uniform vec2 vpSize; 

flat out vec2 centre; 
flat out float radiusPixels; 

const float radius = 1.0; 

void main() 
{ 
    gl_Position = projectionMat * modelviewMat * osVert; 
    centre = (0.5 * gl_Position.xy/gl_Position.w + 0.5) * vpSize; 
    gl_PointSize = vpSize.y * projectionMat[1][5] * radius/gl_Position.w; 
    radiusPixels = gl_PointSize/2.0; 
} 

frammento:

#version 150 

flat in vec2 centre; 
flat in float radiusPixels; 

out vec4 fragColour; 

void main() 
{ 
    vec2 coord = (gl_FragCoord.xy - centre)/radiusPixels; 
    float l = length(coord); 
    if (l > 1.0) 
     discard; 
    vec3 pos = vec3(coord, sqrt(1.0-l*l)); 
    fragColour = vec4(vec3(pos.z), 1.0); 
} 

enter image description here

(noti il ​​divario visibile in basso a destra è corretto come descritto sopra)

+0

+1; grazie per la risposta approfondita Tuttavia, non sono stato in grado di ottenere il risultato corretto; Penso che intendessi 'cot (fov_y/2)'? In questo caso, il mio test mostra che il punto è troppo grande di un fattore di 2,0. – imallett

+0

@IanMallett corretto su tutti gli account! scuse. aggiornato. Ho dimenticato di prendere in considerazione la dimensione NDC è 2 (-1 a 1) che annulla in seguito. – jozxyqk

+0

in webgl Ho usato projectionMat [1] [1] invece di projectionMat [1] [5] – Inuart

Problemi correlati