PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : OpenGL Problem mit Depth Test und Culling


Dee
2003-09-29, 22:33:52
Hallo!

Ich bin recht unerfahren in OpenGL and hab so meine Probleme. Ich programmiere unter Linux (Mandrake 9.1) mit QT 3.2.1. Als kleine Bestimmung will ich nur die gl.h benutzen, dürfte aber kein Problem sein.
Ich hab mir zum lernen das Buch „Jetzt lerne ich OpenGl“ gekauft. Leider ist das nur für MS Visual C++, aber die OpenGL Befehle sind ja die gleichen unter Linux.

Mein größtest Problem ist der GL_DEPTH_TEST. Wenn ich das anschalte, erhalte ich eine leere Szene. Ich hatte schon mal im OpenGL-Forum gesucht, leider nix passendes gefunden. Hatte auch schon manuell glDpethFunc(GL_LESS) angeschaltet, half aber auch nichts. Wenn ich auf GL_GREATER stellte, sah ich zumindest ein klein wenig was.

Zweites Problem ist das Culling. In den Beispieldateien aus dem Buch ist immer glCullFace(GL_FRONT) gesetzt. Sieht unter Windows, wo ich es mal kompiliert habe, auch ganz gut aus. Under Linux fehlen aber dann die Vorderseiten eines Hauses z.B. Stelle ich auf GL_BACK, ist unter Linux alles okay. Beides mal ist glFrontFace(CCW) aktiviert.

Ich muß sagen, daß ich unter Linux wahrscheinlich keinen Hardwaresupport habe. Für das neue Kernel habe ich keien Ati-Treiber finden können und die Treiber für das alte Kernel ließen Linux immer abstürzen. Sollte aber nix ausmachen, da OpenGL ja auch in Software berechnet werden kann.

Ich hoffe, daß hier jemand bescheid weiß. Loewe aus dem Mitrax-Forum hat mich an zeckensack und Xmas verwiesen, die in der Hinsicht viel Ahnung haben sollen. Wäre schön, wenn sich diese oder auch alle anderen melden könnten! :)

Gruß, Dee

PS: Wenn das Thema hier verkehrt ist (Umfaßt eben zu viele Bereiche!) , dann bitte verschieben!

Gnafoo
2003-09-29, 22:57:31
Zu eins:

Kann man schlecht sagen ohne Code, da es eigentlich alles mögliche
sein kann. Vor jedem Frame auch den Depth-Buffer leer gemacht ?
Also:

// leert backbuffer und depthbuffer
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

(funktioniert das erste Programm unter Windows?)

Zu zwei:

Also wenn das Programm genau das selbe ist wie unter Windows ist es
wirklich komisch. Ansonsten hört es sich verdächtig danach an, als
wenn du die Vertices in der falschen Reihenfolge an OGL weiter-
gegeben hast. (Glaube ich aber nicht wenn ich deinen Post so lese)
Also du müsstest die gegen den Uhrzeigersinn an OGL schicken.
Auch hier hilft evtl. ein bisschen Code weiter.

cu DerTod

Xmas
2003-09-29, 23:04:32
Original geschrieben von Dee
Mein größtest Problem ist der GL_DEPTH_TEST. Wenn ich das anschalte, erhalte ich eine leere Szene. Ich hatte schon mal im OpenGL-Forum gesucht, leider nix passendes gefunden. Hatte auch schon manuell glDpethFunc(GL_LESS) angeschaltet, half aber auch nichts. Wenn ich auf GL_GREATER stellte, sah ich zumindest ein klein wenig was.

Rufst du glClear mit DEPTH_BUFFER_BIT auf?

Zweites Problem ist das Culling. In den Beispieldateien aus dem Buch ist immer glCullFace(GL_FRONT) gesetzt. Sieht unter Windows, wo ich es mal kompiliert habe, auch ganz gut aus. Under Linux fehlen aber dann die Vorderseiten eines Hauses z.B. Stelle ich auf GL_BACK, ist unter Linux alles okay. Beides mal ist glFrontFace(CCW) aktiviert.
Wenn das beim selben Code auftritt, ist es wohl ein Treiberbug. Allerdings kann ich mir so einen gravierenden Bug wirklich nicht vorstellen, das würde man ja bei jedem Test bemerken.
Sicher dass nicht irgendwo doch der Culling-Modus geändert wird?

Das Thema ist übrigens durchaus richtig hier.

Dee
2003-09-30, 08:43:24
Also hier ein paar Teile des Codes... (Hab dazu eh unten noch Fragen!)

void GLBox::paintGL() {
glClear( GL_COLOR_BUFFER_BIT );
glLoadIdentity();
glRotatef(-65.0,1.0,0.0,0.0);
glRotatef(-75.0,0.0,0.0,1.0);
glTranslatef( -2.8, 0.0, -1.4 );
glCallList( object );
}

void GLBox::resizeGL( int w, int h ) {
GLdouble ClientRatio =(GLdouble) w/h;
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( -1.0, +1.0, -1.0, +1.0, -100.0, +100.0 );
if (ClientRatio <= 1.0) glViewport((GLint)0, (GLint) (h*(1.0-ClientRatio)/2.0), (GLint) w, (GLint) (h*ClientRatio));
else glViewport((GLint) (w*(1.0-(1.0/ClientRatio))/2.0), (GLint) 0, (GLint) (w/ClientRatio), (GLint) h);
glMatrixMode( GL_MODELVIEW );
}

void GLBox::initializeGL() {
glClearColor(0.0F,0.0F,0.0F,0.0F);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_NORMALIZE);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_DEPTH_TEST); // derzeit deaktiviert
glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
glCullFace(GL_BACK);
glShadeModel(GL_SMOOTH); //Schattierungsmodell
glEnable(GL_LIGHT0); //Lichtquelle 0 EIN
glEnable(GL_LIGHTING); // ...EINschalten
glEnable(GL_COLOR_MATERIAL);//glColor-Materialdef.

// Licht- und Materialdefinitionen folgen hier

GLfloat LMA[4]={0.2F,0.2F,0.2F,1.0F};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, &LMA[0]);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_FALSE);
glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);

makeObjects(); // generiert objects
}

Das ist der Code, sowohl unter Linux als auch unter Windows. (Mehr oder weniger. Unter Windows gibt es zum Beispiel resize und paint nicht, wo ich den Code selbst schreiben mußte.) Ich dürfte eigentlich auch nichts an der Reihenfolge vertauscht haben, aber wer weiß da schon.

Was ich noch als Problem mit dem Code habe. Schalte ich GL_COLOR_MATERIAL aus, dann zeigt er beim ersten Bild die richtig colorierte Szene, sobald aber resize oder paint aufgerufen wird, erscheint die Szene, als wäre GL_COLOR_MATERIAL enabled. Ich hab es doch nirgends wieder aktiviert.... ???

Und als weiteres dreht er doch bei paint() die ganze Szene, oder? Ich hab es partout nicht hinbekommen, die Kamera zu drehen, in dem ich vorher GL_PROJECTION geladen habe. Oder geht das nicht? Wenn nein, wie richtet man die Kamera denn dann aus? Fände ich einfacher als immer die ganze Szene zu drehen.

Ich hoffe, der Code hilft um mir zu helfen. :)

Gruß, Dee

Xmas
2003-09-30, 13:16:00
Original geschrieben von Dee
Das ist der Code, sowohl unter Linux als auch unter Windows. (Mehr oder weniger. Unter Windows gibt es zum Beispiel resize und paint nicht, wo ich den Code selbst schreiben mußte.) Ich dürfte eigentlich auch nichts an der Reihenfolge vertauscht haben, aber wer weiß da schon.
Für Code kannst du hier im Forum auch den [code]-Tag verwenden, dann bleibt die Formatierung erhalten.

Was meinst du mit "unter Windows gibt es resize und paint nicht"? Auf welchen Fenstermanagement-System setzt dieses Beispiel auf?

Für korrekten Depth Test musst du in der paintGL-Methode glClear mit GL_DEPTH_BUFFER_BIT aufrufen.

Was ich noch als Problem mit dem Code habe. Schalte ich GL_COLOR_MATERIAL aus, dann zeigt er beim ersten Bild die richtig colorierte Szene, sobald aber resize oder paint aufgerufen wird, erscheint die Szene, als wäre GL_COLOR_MATERIAL enabled. Ich hab es doch nirgends wieder aktiviert.... ???
Das kann ich anhand dieses Codeausschnitts nicht nachvollziehen.

Und als weiteres dreht er doch bei paint() die ganze Szene, oder? Ich hab es partout nicht hinbekommen, die Kamera zu drehen, in dem ich vorher GL_PROJECTION geladen habe. Oder geht das nicht? Wenn nein, wie richtet man die Kamera denn dann aus? Fände ich einfacher als immer die ganze Szene zu drehen.
Das geht nicht, und dafür ist die Projektionsmatrix auch gar nicht da, diese definiert lediglich die Sichtpyramide.

Es gibt keinen Unterschied zwischen einer Bewegung der Kamera in eine Richtung und der Bewegung der ganzen Szene in die entgegengesetzte Richtung. Relativität ahoi. Auch die Berechnung ist absolut identisch.

Dee
2003-09-30, 13:42:32
Was meinst du mit "unter Windows gibt es resize und paint nicht"? Auf welchen Fenstermanagement-System setzt dieses Beispiel auf?

Mich hat es auch gewundert, aber ich habe in der Klasse, welches die ganzen OpenGL-Darstellung macht keine paint- oder resize-Methode gefunden. Hab den Code leider grad nicht bei der Hand, da ich an der Arbeit bin. Werde zuhause mal nachschauen!


Für korrekten Depth Test musst du in der paintGL-Methode glClear mit GL_DEPTH_BUFFER_BIT aufrufen.

Okay, danke. Das werde ich einmal testen! :)


Das kann ich anhand dieses Codeausschnitts nicht nachvollziehen.

Ehrlich gesagt war das schon fast der ganze Code... :) Es fehlen eigentlich nur die Def. der Lichter, Materialen und Objekte... Werde den kompletten Code aber mal heut Abend anhängen.


Das geht nicht, und dafür ist die Projektionsmatrix auch gar nicht da, diese definiert lediglich die Sichtpyramide.

Dachte ich mir fast, wollte nur sicher gehen. Das heißt also, daß auf die Projektionsmatrix auch keine Translationen oder Rotationen wirken können, richtig?

Ich muß unbedingt nochmal den Windows-Code anschauen, da ich glaube, daß dort die Rotation auf die Sichtpyramide und nicht auf die Szene angwendet wird. Wer das aber nochmal überprüfen!

Danke schonmal! :)
Gruß, Dee

Xmas
2003-09-30, 14:02:23
Original geschrieben von Dee
Dachte ich mir fast, wollte nur sicher gehen. Das heißt also, daß auf die Projektionsmatrix auch keine Translationen oder Rotationen wirken können, richtig?
Im Prinzip geht es schon, aaaber:

http://www.opengl.org/developers/faqs/technical/viewing.htm
http://sjbaker.org/steve/omniv/projection_abuse.html

Matti
2003-09-30, 14:52:35
@Dee
Haste vielleicht diese Zeilen bei der Initialisierung vergessen:


glMatrixMode(GL_PROJECTION); // Change Matrix Mode to Projection
glLoadIdentity(); // Reset View
gluPerspective(45.0, Width/Height, 0.1, 100.0); // Do the perspective calculations. Last value = max clipping depth
glMatrixMode(GL_MODELVIEW); // Return to the modelview matrix
glLoadIdentity(); // Reset View

Dee
2003-09-30, 15:46:15
Hallo Matti!

Ich bevorzuge vorerst die reinen gl-Bibliotheken, also ohne glu.h. (Was wohl eher dran liegt, daß ich es net schaffe, die unter Linux einzubinden. *g*)
Jedenfalls nutze ich glOrtho, um die Perspektive darzustellen. Hab auch schon mit glFrustum experimentiert, aber das ist ja eher für die perspektivische Darstellung zuständig, auf die ich erst einmal verzichten möchte.

Aber zum Verständnis: In welcher Reihenfolge werden denn initialize(), paint() und resize() aufgerufen, sprich wo muß ich wann welche Befehle einbinden?

Gruß, Dominik

Xmas
2003-09-30, 15:51:16
Original geschrieben von Dee
Aber zum Verständnis: In welcher Reihenfolge werden denn initialize(), paint() und resize() aufgerufen, sprich wo muß ich wann welche Befehle einbinden?

Gruß, Dominik
Na initialize einmal zu Programmstart, resize immer wenn du die Fenstergröße veränderst und paint wenn der Inhalt des Fensters neu gezeichnet werden muss.
Da ich nicht weiß welches Fenstermanagement du da verwendest, kann ich dir nicht genau sagen ob paint regelmäßig (also x-mal pro Sekunde) aufgerufen wird, oder nur wenn wirklich Neuzeichnen notwendig ist (also bei Fenstergröße ändern, ein überlappendes Fenster bewegen u.ä.)

Matti
2003-09-30, 16:01:40
Hab mir deinen Code mal angeguckt. Bei
glOrtho( -1.0, +1.0, -1.0, +1.0, -100.0, +100.0 );
weiß ich nicht genau, ob man auch einen negativen Wert für die Near-Clipping-Plane angeben kann. Versuch's mal mit 0.1 anstatt -100. Dann mußt du natürlich immer glVertex3f(...,...,>0.1) verwenden, oder das Objekt mit glTranslatef(...) entsprechend verschieben.
...ist aber nur eine Vermutung, kann natürlich auch sein daß es nicht daran liegt...

zeckensack
2003-09-30, 16:11:11
Matti,
bei glOrtho ist die near plane eigentlich Wurscht. Man muß sie halt immer nur so legen, daß die Geometrie komplett hineinpaßt. Bei gluPerspective (bzw glFrustum) beeinflußt dagegen der Abstand der near plane die Präzisionsverteilung des Z-Buffers. 0 ist sowieso strikt verboten, und zu kleine Werte führen verstärken z fighting. Empfehlenswert sind Werte >=1.

Matti
2003-09-30, 16:14:55
Original geschrieben von zeckensack
Bei gluPerspective (bzw glFrustum) beeinflußt dagegen der Abstand der near plane die Präzisionsverteilung des Z-Buffers. 0 ist sowieso strikt verboten, und zu kleine Werte führen verstärken z fighting. Empfehlenswert sind Werte >=1.

Ist das bei glOrtho nicht auch so? Dee verwendet ja glOrtho und GL_DEPTH_TEST. Oder ist der Z-Buffer bei glOrtho linear?

zeckensack
2003-09-30, 16:16:50
Dee,
sicher, daß du überhaupt einen Z-Buffer bekommst? Die Auswahl des 'passenden' Formats funktioniert unter Win32 und X grundlegend anders. Teste mal zum Spaß diesen Schnipsel:GLuint z_bits=0;
glGetIntegerv(GL_DEPTH_BITS,&z_bits);

Wenn auf einem der beiden Systeme 0 dabei herauskommt, dann liegt der Fehler in der Initialisierung des GL context ;)

Außerdem immer zwischendurch mal glGetError aufrufen. Anfangen solltest du mit einmal pro Frame, wenn Fehler auftauchen, dann versuch das Problem schrittweise zu umzingeln :)

Dann sollte man noch erwähnen, daß 'Init'-Funktionen, die GL-Aufrufe benutzen Null und nichtig sind, wenn sie vor der Erzeugung des GL context ausgeführt werden. Beliebter Fehler, gerade in Zusammenhang mit C++ und globalen Objekten (Konstruktoraufrufe).

zeckensack
2003-09-30, 16:24:56
Original geschrieben von Matti
Ist das bei glOrtho nicht auch so? Dee verwendet ja glOrtho und GL_DEPTH_TEST. Nein. glOrtho erzeugt immer nur eine Skalierung und Translation. Man bekommt dabei eine lineare Z-Verteilung heraus, wobei Start- und Endpunkt frei wählbar sind. W ist nach der Transformation immer 1, also kann die Perspektivkorrektur auch nichts verbiegen (weil sie ja quasi nicht stattfindet).

Spec sez:If l is equal to r, b is equal to t, or n
is equal to f, the error INVALID VALUE results.
Den Rest kann man sich, wie gesagt, aussuchen :)

Bei 'Perspektiv-Matrizen' führt eine near plane bei 0 theoretisch dazu, daß alle transformierten Vertices w=0 haben. In Folge dessen muß die Perspektivkorrektur für jeden Vertex durch Null dividieren :devil:

Deswegen ist das nicht gestattet. Spec sez:If either n or f is
less than or equal to zero, l is equal to r, b is equal to t, or n is equal to f, the error INVALID VALUE results.

Matti
2003-09-30, 16:31:13
thx
da bin ich schon über 7700 Tage alt und man lernt trotzdem nicht aus ;)

Dee
2003-09-30, 20:07:37
Hey, Ihr seid gut, Leute! :)

Also der Tiefentest funktioniert nun. Lag wohl tatsächlich an dem fehlenden GL_DEPTH_BUFFER_BIT in der paintGL(). Im Übrigen war bei mir z_bits=16 unter Linux. ;)

Bei glOrtho wird die vordere Cliiping-Plane tatsächlich mit einem negativem Vorzeichen benutzt. Brachte mich auch etwas durcheinander, da ich erst glFrustum hatte und es da nur positiv ist... Aber in der OpenGL-Referenz kann man das ja nachlesen!

Nun zu meinen anderen Problemen. Ich hab mal alles relevante auf einer extra Seite zusammengestellt: http://www.stud.uni-giessen.de/~su2754/opengl/ogl.htm

Oben sind Zip-Files mit allen Dateien, darunter die beiden Quelldateien, wo der Code drinsteht und dann noch die "exe"-Dateien, wenn jemand unter Windows / Linux nur das Ergebnis sehen will. (Bei dem Windows-Teil muß man über die Schaltfläche erst die Lichteffekte einschalten!)

Zuerst zu den oberen drei Bildern: Links ist das Windows Bild, bei glFrontFace(GL_CCW) und glCullFace(GL_FRONT) gesetzt ist. Daneben das Linux Bild direkt nach dem Start und ganz rechts das Linux Bild, sobald das Fenster neu gezeichnet wurde, also nach Resize oder wenn ein anderes Fenster drüber war. Man sieht den Unterschied und die Frage ist, wieso....
Und darunter die Bilder zeigen die Eigenarten, wenn ich glFrontFace und glCullFace ändere. Stell ich es so ein, wie bei Windows, sieht es nicht wirklich gut aus. Erst CCW und BACK bringen das richtige Resultat.
Die Reihenfolge der Vertices ist aber mit Copy and Paste übernommen wurden... (Hab es bei Linux nur noch in Listejn eingearbeitet, aber da bestand das Problem schon!)

Danke auch für die Links, Xmas. Ich schätze, ich muß dann wohl doch gluLookAt benutzen, sonst rotier ich mich noch dumm und dämlich, wenn ich das nur über die Modellmatrix machen will. :(

So, ich hoffe, Ihr könnt mir noch mehr Tips geben. Ist echt sein super Forum! :)

Gruß, Dee

PS: Sowas wie ein Kontext braucht man unter Linux glücklicherweise nicht! ... Wie man sieht! ;)

Dee
2003-10-02, 10:01:20
Na, jetzt mag keiner mehr???

Dee

Matti
2003-10-02, 14:45:09
Original geschrieben von Dee
Zuerst zu den oberen drei Bildern: Links ist das Windows Bild, bei glFrontFace(GL_CCW) und glCullFace(GL_FRONT) gesetzt ist. Daneben das Linux Bild direkt nach dem Start und ganz rechts das Linux Bild, sobald das Fenster neu gezeichnet wurde, also nach Resize oder wenn ein anderes Fenster drüber war. Man sieht den Unterschied und die Frage ist, wieso....

...da wurde wahrscheinlich GL_LIGHTING deaktiviert. Guck mal in deinen Quellcode, ob irgendwo glDisable(GL_LIGHTING) steht. Wenn nicht, ist vielleicht der OpenGL-Treiber fehlerhaft.

Dee
2003-10-02, 23:22:41
Nee, also hell ist ja alles. Wenn ich probehalber GL-LIGHTING ausschalte, dann wird es ja nur dunkel. Aber im gesamten Quellcode wird das auch nirgends deaktiviert... Und es ging seltsamerweise auch mal.... *grübel*

Dennoch danke für die Antwort! Wahrscheinlich kommt aber nichts mehr. Ist ja auch net so wichtig, derzeit. Wenn wieder was ist (Fragen hab ich genug! *g*), dann meld ich mich hier.... :)

Gruß, Dee

Matti
2003-10-03, 13:43:28
wundert mich aber, daß alles dunkel wird, wenn Lighting aus ist. Normalerweise wird dann die Farbe von glColor3f/glColor4f verwendet. Wie machst du in deinem Programm überhaupt die Farbe: mit glColor oder mit Materialien?

Dee
2003-10-05, 17:14:10
Original geschrieben von Matti
Wie machst du in deinem Programm überhaupt die Farbe: mit glColor oder mit Materialien?
In diesem Beispiel mit beidem. *g* Nein, wenn man GL_MATERIAL anschaltet, dann nimmt er die glColor, und wenn man es auf disabled stellt die Materialdefinitionen. Und es war eben so, daß es so aussah, als würde er mitten drin nur noch die glColor-Befehle nehmen.

Inzwischen arbeite ich aber nicht mehr an diesem Beispiel, sondern habe mich der richtigen Arbeit zugewandt. :)

Gruß, Dee