OpenGL: Come determinare se un punto 3D (resa) è occluso da altre primitive (resi) 3D di fronte ad essa?

StackOverflow https://stackoverflow.com/questions/1311869

  •  19-09-2019
  •  | 
  •  

Domanda

Nel mio programma OpenGL, sto facendo la seguente in sequenza:

// Drawing filled polyhedrons
// Drawing points using GL_POINTS
// Displaying information for each above point beside it

Per visualizzare le informazioni sul punto (diciamo un punto identificativo / numero), posso convertire le coordinate 3D del punto da finestra 2D coordinate utilizzando gluProject (). Scrivo l'identificatore punto in quella posizione finestra 2D utilizzando glRasterPos () e 2D carattere codice di rendering.

Quando un punto di resa è occlusa da un altro primitivo, viene automaticamente visualizzata non a causa dell'occlusione prova automatica e test di profondità che accade in cantiere OpenGL. Tuttavia, il mio testo identificatore viene visualizzato accanto al punto, anche quando è occluso da quando non ho ricevuto queste informazioni occlusione.

Come determinare se un punto 3D (resa) è occluso da altre primitive (resi) 3D di fronte ad essa? O c'è un modo migliore per visualizzare il testo informazioni sul punto accanto ad essa solo quando non è occluso?

Nota: Sono consapevole dei metodi che richiedono un passaggio di rendering in più. Sento che coloro che sono costosi per il mio scopo.

È stato utile?

Soluzione

Se non siete disposti a utilizzare una query di occlusione secondo passaggio si può provare il campionamento del Z-buffer da confrontare con l'punto di prova.

Dal momento che si sta aggiungendo testo accanto a un punto, afferrare il valore del buffer Z normalizzato (dire usando gluProject) del punto, quindi confrontare tale valore alla Z-buffer campionato (usando glReadPixels) il valore in quel punto. Se il punto è dietro (superiore) al valore di profondità avete campionato, il tuo punto dovrebbe essere occluso e si può scegliere di non disegnare il testo.

Questo naturalmente richiede che si esegue il rendering tutta la geometria prima del testo, ma che non dovrebbe essere un problema.

Codice di esempio:

// Assumed to already hold 3D coordinates of point
GLdouble point3DX, point3DY, point3DZ;

// Project 3D point coordinates to 2D
GLdouble point2DX, point2DY, point2DZ;  // 2D coordinates of point
gluProject( point3DX, point3DY, point3DZ,
            mMatrix, pMatrix, vMatrix,      // MVP matrices
            &point2DX, &point2DY, &point2DZ);

// Read depth buffer at 2D coordinates obtained from above
GLfloat bufDepth = 0.0;
glReadPixels(   static_cast<GLint>( point2DX ), static_cast<GLint>( point2DY ),     // Cast 2D coordinates to GLint
                1, 1,                                                               // Reading one pixel
                GL_DEPTH_COMPONENT, GL_FLOAT,
                &bufDepth);

// Compare depth from buffer to 2D coordinate "depth"
GLdouble EPSILON = 0.0001;  // Define your own epsilon
if (fabs(bufDepth - point2DZ) < EPSILON)
    // 3D point is not occluded
else
    // 3D point is occluded by something

Altri suggerimenti

Lettura dal z-buffer può essere molto molto lento su hardware moderno. Ecco perché l'occlusione di query è stato inventato. Cercare l'estensione ARB-occlusione-query. Ha un paio di fotogrammi di ritardo prima di poter ottenere i risultati, ma non ha colpito le prestazioni.

Se la query di occlusione non è andare a lavorare per qualsiasi motivo, l'opzione di ripiego successivo è quello di fare un funzionamento del software ray-intersechi-mondo utilizzando un BSP-tree (che non utilizza affatto GL).

A seguito della risposta di Alan, si potrebbe verificare l'occlusione matematicamente proiettando un raggio dalla posizione della telecamera al punto, e determinare se si interseca qualsiasi geometria. Ci sono un sacco di riferimenti su Internet per fare ray-oggetto di test di intersezione (vedi, per esempio, il Oggetto / oggetto Intersezione Pagina ). Se hai un sacco di geometria allora si potrebbe desiderare di accelerare le cose usando i volumi di delimitazione o un albero BSP.

Come bonus, il codice di occlusione dovrebbe essere molto più facile da test di unità, perché non si basa su l'estrazione di valori da OpenGL.

Modulo risposta Ashwin Nanjappa è stato molto utile. Io non sono un esperto di OpenGL, quindi mi c'è voluto un po 'per scoprire come ottenere matrici MVP. Sto condividendo il codice qui per completare il suo posto:

    GLint viewport[4];
    GLdouble modelview[16];
    GLdouble projection[16];
    glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
    glGetDoublev( GL_PROJECTION_MATRIX, projection );
    glGetIntegerv( GL_VIEWPORT, viewport );
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top