OpenGL: Wie bestimmen, ob ein 3D (gerendert) Punkt von anderen 3D (gerendert) Primitiven vor ihm verschlossen ist?

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

  •  19-09-2019
  •  | 
  •  

Frage

In meinem OpenGL Programm, ich tue das folgende in der Reihenfolge:

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

Für die Punktinformationen angezeigt wird (sagen wir eine Punktkennung / Nummer), konvertiere ich die 3D-Koordinaten des Punktes auf 2D-Fenster-Koordinaten mit gluProject (). Ich schreibe die Punktkennung in diesem 2D-Fenster Standort mit glRasterPos () und 2D-Zeichen Rendering-Code.

Wenn eine gerenderte Punkt durch einen anderen primitiven verschlossen wird, ist es automatisch nicht angezeigt durch automatische Okklusion Test und Tiefentest, der in der OpenGL-Pipeline passiert. Allerdings ist mein Punkt Bezeichnertext neben dem Punkt angezeigt, auch wenn sie verschlossen ist, da ich nicht über diese Okklusion Informationen erhalten.

Wie bestimmen, ob ein 3D (gerendert) Punkt von anderen 3D (gerendert) Primitiven vor ihm verschlossen ist? Oder gibt es einen besseren Weg, um die Punktinformationen Text daneben angezeigt werden nur , wenn es nicht verschlossen?

Hinweis: Ich bin mir bewusst, die Methoden, die einen zusätzlichen Rendering-Pass benötigen. Ich glaube, dass diejenigen, für meine Zwecke teuer sind.

War es hilfreich?

Lösung

Wenn Sie nicht bereit sind, Abfrage eine Okklusion verwenden zweite passieren können Sie versuchen, die Z-Puffer Abtasten gegen den Testpunkt zu vergleichen.

Da Sie das Hinzufügen von Text neben einen Punkt, den normierten Z-Puffer-Wert greifen (etwa mit gluProject) des Punktes, vergleichen, dann diesen Wert auf den abgetastete Z-Pufferwert an diesem Punkt (glReadPixels verwenden). Wenn Ihr Punkt hinter ist (größer als) der Tiefenwert Du abgetastet, sollte Ihr Punkt verschlossen werden und Sie können nicht den Text zu zeichnen.

Dies erfordert natürlich, dass Sie alle Ihre Geometrie vor dem Text machen, aber das sollte kein Problem sein.

Beispielcode:

// 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

Andere Tipps

Beim Lesen aus dem Z-Puffer kann sehr sehr langsam auf moderne Hardware. Deshalb Okklusion Abfrage erfunden wurde. Schauen Sie die ARB-Absorptions-Abfrage Verlängerung. Es hat ein paar Frames Verzögerung, bevor Sie die Ergebnisse zu bekommen, aber es wird treffen Sie Ihre Leistung nicht.

Wenn Okklusion Abfrage aus irgendeinem Grunde nicht zur Arbeit gehen, die nächste Ersatzoption ist ein Software-ray-intersect-Welt Betrieb mit einem BSP-Baum zu tun (die GL gar nicht verwendet werden).

Im Anschluss an Alans Antwort, könnten Sie für Okklusion testen mathematisch durch einen Strahl von der Kamera Position zu Ihrem Punkt vorsteht, und zu bestimmen, ob es irgendwelche Ihrer Geometrie schneidet. Es gibt viele Referenzen im Internet zu tun Kreuzung Test ray-Objekt (siehe zum Beispiel des Objekt / Objektschnitt Seite ). Wenn Sie viel Geometrie haben, dann sollten Sie die Dinge beschleunigen mit Begrenzungsvolumen oder eine BSP-Baum.

Als Bonus Ihre Okklusion Code viel einfacher zu Unit-Test sein sollte, denn es lässt sich nicht verlassen Werte von OpenGL zu extrahieren.

Antwort von Ashwin Nanjappa war sehr hilfreich. Ich bin kein OpenGL-Experte, so dauerte es eine Weile, um herauszufinden, wie MVP Matrizen zu erhalten. Ich teile den Code hier seinen Beitrag zu ergänzen:

    GLint viewport[4];
    GLdouble modelview[16];
    GLdouble projection[16];
    glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
    glGetDoublev( GL_PROJECTION_MATRIX, projection );
    glGetIntegerv( GL_VIEWPORT, viewport );
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top