OpenGL.org 3Dsource.de: Infos rund um 3D-Computergrafik, OpenGL und VRML
space Telefon-Tarife space VDI - Arbeitskreis Fahrzeugtechnik space Beschallungsanlagen und Elektroakustik space Heise-News space

3 Kantenverlauf auf Polygonen, Polygonoffset

13.010 Was sind die Grundlagen, um den Polygon Offset nutzen zu können ?

Es ist schwierig, mit OpenGL zwei auf annähernd gleicher Position (coplanar) liegende Polygone korrekt darzustellen, so dass diese sich nicht durchdringen (z.B. die Markierungen auf der Fahrbahn). Dafür gibt es zwei Gründe:

  • Zwei sich schneidende/überlappende Primitive mit verschiedenen Eckpunkten können durch Rundungsfehler leicht abweichende Z-Werte erhalten. Das heisst, einige Pixel der eigentlich nicht sichtbaren Fläche liegen für die OpenGL vor den anderen und werden deshalb angezeigt.
  • Für coplanare Linien und Polygone können trotz Deckungsgleicheit deutlich verschiedene Z-Werte für gleiche Pixel berechnet werden. Das liegt daran, dass während der Rasterisation für Polygone eine Flächengleichung, für Linien dagegen eine einfache Geradengleichung zur Interpolation genutzt wird.

Auch das Festlegen des Tiefentests auf GL_LEQUAL oder GL_EQUAL hilft nicht.

Polygon Offset war bereits in der OpenGL Version 1.0 als Extension verfügbar und ist fester Bestandteil der OpenGL seit Version 1.1. Es erlaubt der Anwendung, einem ausgefüllten Primitive einen zusätzlichen Tiefenoffset zu geben, der dieses Primitive vor einem anderen an gleicher Position zeichnet. Mit OpenGL 1.1 ist es sogar möglich, den angegebenen Offset getrennt für Flächen, Linien und Punkten anzugeben und zu aktivieren. Damit kann ein Programm zunächst ein Primitiv zeichnen und das zweite an gleicher Stelle, nachdem der Polygon Offset aktiviert wurde.

Der Polygon Offset kann zwar den Z-Wert von Flächen beeinflussen, aber nicht den von Primitiven wie GL_POINTS, GL_LINES, GL_LINE_STRIP, oder GL_LINE_LOOP. Damit kann man den Polygon Offset nutzen, um ein auf gleicher Höhe wie z.B. eine Linie liegendes Polygon etwas nach hinten zu schieben, nicht aber um die Linien oder Punkte nach vorn zu holen.

Da Polygon Offset den Z-Wert beim Rasterisieren beeinflusst, kann der im Tiefenbuffer verändert vorliegende Wert auch das angezeigte Bild der Szene nachteilig verändern. Unter vielen Umständen ist es möglich, dass unerwünschte Durchdringungserscheinungen die Folge sind oder ein Objekt im Vordergrund gezeichnet wird, obwohl es da gar nicht hingehört. Besonders sich schneidende Polygone können betroffen sein.

Als Startwert für die Parameter factor und units kann man zunächst jeweils 1.0 wählen und dann für die Szene eine individuelle Anpassung ermitteln.

13.020 Was bedeuten die beiden Parameter in der Funktion glPolygonOffset() ?

Polygon Offset wird durch zwei Parameter gesteuert. Das sind factor und units (Faktor und Einheit). factor legt die maximale Abweichung in Z (abhängig von X und Y) fest und units den kleinsten unterscheidbaren Z-Wert. Die Kombination dieser Ergebnisse bestimmt den endgültigen Wert für den Polygon Offset. Dieser wird im Bildschirmkoordinatensystem als positiver Wert (bzw. negativ bei entsprechendem Vorzeichen der Parameter) dem vorgegebenen Z-Wert eines Vertex hinzu addiert.

Der Offset o berechnet sich wie folgt:
o = const1 * factor + const2 * units

Der Parameter factor wird benötigt, um als ausgefüllte Flächen gezeichneten Primitive, die nicht parallel zur vorderen/hinteren Clipping Fläche und damit in einem Winkel zum Betrachter liegen, korrekt darzustellen. In diesem Fall kann der unterschiedliche Z-Wert für zwei coplanar liegende Primitive der maximalen Abweichung in X oder Y entsprechen. Die Unterschiede in Z sind gross für Primitive, deren Kanten nahe am Betrachter verlaufen (also schräg zum Betrachter liegen) und klein für Primitive, deren Flächen dem Betrachter zugewandt sind. Der Parameter factor bestimmt also die unterschiedliche Abweichung in Z für diese beiden Fälle.

Eine typische Parameterangabe kann z.B. sein, beide Werte auf jeweils 1.0 und den Polygon Offset auf GL_FILL zu setzen. Damit werden die als Flächen gezeichneten Polygone in positiver Z-Richtung (in den Bildschirm hinein) verschoben. Dann kann man das Polygon zweimal zeichnen, einmal als Fläche (bzw. Körper) und einmal als Drahtgittermodell. So werden die Kanten des Polygons durch die Linien des Drahtgittermodells nachgezeichnet. In einem Winkel zum Betrachter liegende Flächen werden jetzt deutlich vom Augpunkt weg geschoben, während bei einem annähernd parallel zur vorderen Clipping Fläche liegenden Polygon nur ein minimaler Z-Offset addiert wird.

13.030 Was ist der Unterschied zwischen der Polygon Offset Extension von OpenGL 1.0 und der Offset-Funktion ab OpenGL 1.1 ?

Die Polygon Offset Extension von OpenGL 1.0 liess sich nur für Polygone im GL_FILL Modus verwenden, Drahtgitter- oder Eckpunktoffset war damit nicht möglich.

Die Extension arbeitet statt mit dem factor Parameter mit bias, der direkt zum normalisierten Z-Wert addiert wird. Im Regelfall stellt der Wert 0.001 eine brauchbare Wahl dar.

Das GLUT Beispiel zeichnet zwei Zylinder, einmal mit der 1.0 Extension, dann mit den OpenGL 1.1 Befehlen.

13.040 Warum arbeitet der Polygon Offset nicht, wenn ich eine Linie über Farbflächen der Primitive zeichne ?

Polygon Offset beeinflusst gemäss seinem Namen auch nur Polygone, also Primitive der Form: GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS, GL_QUAD_STRIP und GL_POLYGON. Ab OpenGL 1.1 sind alle Darstellungsformen (GL_FILL, GL_LINE, or GL_POINT) möglich.

Primitive der Art GL_POINTS, GL_LINES, GL_LINE_STRIP oder GL_LINE_LOOP lassen sich also nicht mit einem Offset zu versehen.

13.050 Was habe ich noch für Optionen, um Primitive auf gleicher Ebene ohne Nutzung des Polygon Offset zu zeichnen ?

Man kann den Effekt des Polygon Offset erreichen, indem man mit der Funktion glDepthRange() arbeitet. Das geht z.B. mit folgendem Code:

    glDepthRange (0.1, 1.0);
    /* jetzt im Hintergrund liegende Geometrie zeichnen */
    glDepthRange (0.0, 0.9);
    /* jetzt im Vordergrund liegende Geometrie zeichnen */

Dieser Code legt einen festen Offset in Z fest, ohne die Ausdehnung bzw. den Winkel des Polygons zu berücksichtigen. Damit ist es ungefähr vergleichbar mit einem factor = 0.0 des Polygon Offset.

Man kann auch coplanar liegende Primitive mit der Hilfe des Stencil Buffers zeichnen. Das Red Book zeigt eine mögliche Lösung auf. Als Beispiel kann auch folgender Code dienen:

  1. Zunächst werden die Kanten in den Farb-, Z- und Stencil Buffer gezeichnet.
  2. Dann wird das Polygon im GL_FILL Modus in den Farb- und Tiefenbuffer gezeichnet, wobei die bereits im Stencil Buffer belegten Bereiche ausgelassen werden.
  3. Nun wird der Kantenverlauf ausschliesslich in den Stencil Buffer gezeichnet, so dass dieser wieder gelöscht wird.

Auf einigen SGI Systemen steht auch die SGIX_reference_plane Extension zur Verfügung. Damit kann man eine gemeinsame Flächengleichung für coplanare Primitive festlegen. Wird diese Flächengleichung aktiviert, werden auch alle Z-Werte der verschiedenen Primitive hierüber berechnet und sind damit garantiert identisch.

Seite durchsuchen nach:

Fragen oder Ideen an:
Thomas.Kern@3Dsource.de
Linux-Counter
(C) Thomas Kern