Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

06.07.2006, 09:43

Probleme mit glReadPixels()

Hallo liebe Community

Ich habe ein Problem mit der Funktion glReadPixels(). Und zwar möchte mittels des Aufrufs

C-/C++-Quelltext

1
glReadPixels(winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );
die z-Koordinate für den Bildschirmpunkt (winX,winY) ermitteln, um sie dann in gluUnProject zu nutzen, um den entsprechenden Punkt im Objektraum zu ermitteln.

Das Problem dabei ist, dass mir glReadPixels() keinen richtigen Wert zurückgibt, sondern stets den Wert, den ich vorher übergeben habe. Also ein undefinierter Wert ergibt wieder einen undefinierten, 1 bleibt 1 usw... Und das für sämtliche x-y-Kombinationen. Woran kann das liegen? Kann es sein, dass nichts in den z-Buffer geschrieben wird? Das geht doch nicht oder?

MfG
Neron

Steven77

Alter Hase

Beiträge: 515

Wohnort: Münster - Gievenbeach

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

06.07.2006, 11:04

Ist der Tiefentest denn aktiviert? Arbeitest Du mit 'nem Tiefen-Buffer?

3

06.07.2006, 11:10

Ich aktiviere den Tiefenbuffer mit

C-/C++-Quelltext

1
2
glEnable( GL_DEPTH_TEST );
glDepthFunc( GL_LEQUAL );

C-/C++-Quelltext

1
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
rufe ich auch auf, so wie es sein sollte...

Steven77

Alter Hase

Beiträge: 515

Wohnort: Münster - Gievenbeach

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

4

06.07.2006, 11:14

Welchen Wertebereich nimmst Du für winX und winY?

5

06.07.2006, 11:46

Ich greife die Koordinaten auf dem OpenGL-Fenster ab, dort wo ich hinklicke:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
void COpenGLControl::OnLButtonDown(UINT nFlags, CPoint point) 
{
    // get the point in world coordinates

    if ( m_bShow_lattice )
    {
        world_point = WinPosTo3DPos( point.x, point.y );
    }

    CWnd::OnLButtonDown(nFlags, point);
}


Und dann folgt

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
sVertex COpenGLControl::WinPosTo3DPos(float winX, float winY, int a)
{
    GLint viewport[4];
    GLdouble modelMatrix[16];
    GLdouble projMatrix[16];
    GLdouble objX;
    GLdouble objY;
    GLdouble objZ;
    GLdouble winZ;

    glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix ); 
    glGetDoublev(GL_PROJECTION_MATRIX, projMatrix ); 
    glGetIntegerv(GL_VIEWPORT, viewport ); 
    float winY_new = viewport[3] - winY; // In OpenGL steigt Y von unten (0) nach oben


    // Auslesen des Tiefenpuffers an der Position (X/Y_new)

    glReadPixels(winX, winY_new, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );

    // Errechnen des Punktes welcher mit den beiden Matrizen multipliziert (X/Y_new/Z) ergibt:

        gluUnProject( (GLdouble)winX, (GLdouble)winY_new, (GLdouble)winZ,
              modelMatrix, projMatrix, viewport, &objX, &objY, &objZ);

    sVertex point;
    point.pos.x = (float)objX;
    point.pos.y = (float)objY;
    point.pos.z = (float)objZ;
    return point;
}

Steven77

Alter Hase

Beiträge: 515

Wohnort: Münster - Gievenbeach

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

6

06.07.2006, 16:03

Benutze mal GLfloat und nicht GLdouble (zumindest für winZ), vielleicht hilft das ja schon.

7

06.07.2006, 16:56

Hab ich auch schon versucht - man sieht ja noch den Cast in der gluUnProject(). Nix geholfen :(

Steven77

Alter Hase

Beiträge: 515

Wohnort: Münster - Gievenbeach

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

8

06.07.2006, 18:21

Hm, keine Ahnung, ich habe deinen Code ja jetzt nicht getestet, aber ich hatte mal eine Funktion geschrieben, die sogar auf gluUnProject verzichtet:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
bool Window2World(const int x,      // X-Koordinate des Fensters

                  const int y,      // Y-Koordinate des Fensters

                  Vector3& vObj)    // World-Koordinaten (out)

{
    Matrix4x4 modelview;    // Model-View-Matrix

    Matrix4x4 projection;   // Projection-Matrix

    GLint viewport[4];      // Viewport-Dimensionen


    Matrix4x4 M;    // Model-View-Matrix * Projection-Matrix

    Matrix4x4 I;    // Invertierte Matrix: I = M^-1


    Vector4 in, out;    // Vektoren für Transformationen


    // Model-View-Matrix und Projection-Matrix ermitteln.

    glGetFloatv( GL_MODELVIEW_MATRIX, (GLfloat*) modelview );
    glGetFloatv( GL_PROJECTION_MATRIX, (GLfloat*) projection );

    // Viewport-Dimensionen ermitteln.

    glGetIntegerv( GL_VIEWPORT, (GLint*) viewport );

    // Homogenen Vektor erzeugen. (Die Z-Komponente

    // lesen wir aus dem Tiefen-Buffer).

    in.x = GLfloat(x);
    in.y = GLfloat(viewport[3] - y);
    glReadPixels( x, viewport[3] - y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &in.z );
    in.w = 1.0f;

    // Falls die Tiefe "Unendlichkeit" bedeutet,

    // liegt der Punkt nicht innerhalb des

    // gültigen Bereichs des View-Frustums.

    if (in.z == 1.0f)
        return false;

    // Fensterkoordinaten in den Bereich [0;1]

    // transformieren (Viewport-Koordinaten).

    in.x = (in.x - GLfloat(viewport[0])) / GLfloat(viewport[2]);
    in.y = (in.y - GLfloat(viewport[1])) / GLfloat(viewport[3]);
    // Die Z-Komponente hat bereits einen

    // Wert im Bereich [0;1].


    // Koordinaten in den Bereich [-1;+1]

    // transformieren (normalisierte

    // Gerätekoordinaten).

    in.x = (in.x * 2.0f) - 1.0f;
    in.y = (in.y * 2.0f) - 1.0f;
    in.z = (in.z * 2.0f) - 1.0f;

    // Model-View-Matrix mit der Projection-Matrix

    // multiplizieren und invertieren.

    MatrixMul( modelview, projection, M );
    if (!MatrixInv( M, I ))
        return false;

    // Homogenen Vektor mit der invertierten

    // Transformationsmatrix multiplizieren.

    VectorTransform( I, in, out );

    // Gültigkeits-Check.

    if (out.w == 0.0f)
        return false;

    // Aus resultierendem "Strahl" einen "Punkt" machen,

    // indem durch die w-Komponente dividiert wird.

    vObj.x = out.x / out.w;
    vObj.y = out.y / out.w;
    vObj.z = out.z / out.w;

    return true;
}

Die verwendeten Klassen sollten eigentlich recht trivial sein (und basieren alle auf GLfloat, kein GLdouble).
Vielleicht hilft's dir ja, ansonsten kann ich dir auch mal den ganzen Code schicken...

9

07.07.2006, 09:17

Hallo Steven77

Vielen Dank für die Mühe, nur leider wird auch diese Funktion mir nicht helfen. Das Problem ist nicht die Funktion an sich, sondern der Aufruf von glReadPixels(). Es scheint, als stünden keine vernünftigen Werte im z-Buffer. Wann immer ich also mit

C-/C++-Quelltext

1
glReadPixels(winX, winY, 1,1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );
den Tiefenbuffer auslese, kommt kein vernünftiger Wert heraus. Heute morgen habe ich mal

C-/C++-Quelltext

1
glReadPixels(winX, winY, 2, 2, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );
versucht und statt einem undefinierten Wert wurde wenigstens ein Wert zwischen 0.006.. und 0.008.. zurückgeliefert. Aber das hilft mir natürlich auch nicht weiter, da ich ja eigentlich die z-Koordinate meines Objekts haben möchte.

Muss ich glReadPixels() vielleicht vorher konfigurieren? Ich hab gelesen, dass es da einige Funktionen vorweg gibt, aber Beispiel zum Auslesen des z-Buffers hab ich stets ohne Vorkonfiguration gefunden

MfG
Neron

Werbeanzeige