OpenGL: Textureprojection / Eye Coords



  • Hi!
    Ich bin gerade dabei, Textureprojektion(Z. B. Scheinwerfer) in meine 3D Engine einzuarbeiten...

    http://developer.nvidia.com/object/Projective_Texture_Mapping.html

    Ich stelle mir das in etwa so vor, das ich in die Texturematrix mit glTranslatef und glRotatef die Position nd Blickwinkel des Projektors sowie mit gluPerspective die Projektion des Projektors wie bei einer Kamera einstellen kann. OpenGL berechnet dann daraus die UV Koordinaten für die Projektionstextur ohne einen zusätzlichen Renderpass.

    Um die Sache jetzt aber verstehen zu können, muss ich wissen, wie die Texturkoordinaten berechnet werden(zumal mein erster Versuch gänzlich fehlgeschlagen ist).

    Es gibt ja 2 Varianten. Einmal über GL_OBJECT_LINEAR und einmal über GL_EYE_LINEAR. Für das erste muss man irgendwie die Planes immer neu berechnen, deswegen ist GL_EYE_LINEAR besser sage ich mal 🙂

    Also Texturkoordinatengenerierung anstellen:

    glEnable(GL_TEXTURE_GEN_S)
    glEnable(GL_TEXTURE_GEN_T)
    glEnable(GL_TEXTURE_GEN_R)
    glEnable(GL_TEXTURE_GEN_Q)
    

    Generierungsmodus aller Koordinaten auf GL_EYE_LINEAR stellen:

    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)
    glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)
    glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)
    glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)
    

    Und weiter weiß ich nicht 🙂

    Bei GL_EYE_LINEAR wird die Koordinate g so berechnet:
    g = P1' * Xe + P2' * Ye + P3' * Ze + P4' * We

    P1 bis P4 sei der Vektor, den man für die entsprechende Koordinate X übergibt:
    glTexGenfv(GL_X, GL_EYE_PLANE, [P1, P2, P3, P4])

    (P1' P2' P3' P4') = (P1 P2 P3 P4)*M-1
    Wobei M = ModelViewMatrix

    (Xe Ye Ze We) sollen die Eye Coords des Vertex sein. Hier frage ich mich, wann man die Eye Koordinaten erhält. Muss man die Objektkoordinaten mit der ModelViewMatrix oder mit ModelViewMatrix UND der ProjectMatrix multiplizieren.

    Wenn das 2tens zutrifft, sind dann Xe und Ye eigentlich die Bildschirmkoordinaten?

    Was sind eigentlich homogene Koordinaten?

    mfg olli

    Edit: Ok, so langsam habe ich es kapiert.

    - Objekt Koordinaten x View Matrix der Kamera = Eye Koordinaten
    - Eye Koordinaten x inverse View Matrix = Objekt Koordinaten
    - Objekt Koordinaten x Bias Matrix sorgt dafür das die Koordinaten im Bereich 0.0 .. 1.0 sind
    - Neue Objekt Koordinaten x Projektor View Matrix = Eye Koordinaten des Projektors

    Wie daraus jetzt die Tetxurkoordinaten berechnet werden, weiß ich noch nicht.

    mfg olli



  • v' = (mat_LichtView * mat_LichtProj * mat_Bias) * v
    
    mat_LichtView ist die "Kamera" Matrix des Lichts
    mat_LichtProj Projektionsmatrix des Lichts
    mat_Bias =
    0.5  0    0  0
    0   -0.5  0  0
    0    0    1  0
    0.5  0.5  1  1
    

    So einfach ist das grundsätzlich, wie das mit OGL einzustellen ist kann ich Dir aber absolut nicht sagen. Vielleicht mal selbst mit nem Vertexshader versuchen? Da weiß man wenigstens was passiert.

    Ach ja, die Texturkoordinaten müssen dann noch durch ihre homogene Komponente w geteilt werden, aber das macht die Graka normalerweise automatisch.



  • Hi!

    Danke! Zumindest weiß ich jetzt, das die BiasMatrix doch zum Schluss multipliziert werden muss. Diese NVIDIA Doku machst ja genau andersherum.

    Wenn ich jetzt für die Texturkoordinaten S, T, R und Q die Texturgenerierungsmethoden GL_OBJECT_LINEAR wähle ergibt ja für jede Koordinate g folgende Generierungsformel:

    g = P1*Xo + P2*Yo + P3*Zo + P4*Wo

    Xo .. Wo = Objekt Koordinaten
    P1 .. P4 = Parameter Punkte die ich mit GL_OBJECT_PLANE übergebe

    Also mache ich folgendes:

    glEnable(GL_TEXTURE_GEN_S)
    glEnable(GL_TEXTURE_GEN_T)
    glEnable(GL_TEXTURE_GEN_R)
    glEnable(GL_TEXTURE_GEN_Q)
    
    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR)
    glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR)
    glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR)
    glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR)
    
    glTexGenfv(GL_S, GL_OBJECT_PLANE, [1.0, 0.0, 0.0, 0.0])
    glTexGenfv(GL_T, GL_OBJECT_PLANE, [0.0, 1.0, 0.0, 0.0])
    glTexGenfv(GL_R, GL_OBJECT_PLANE, [0.0, 0.0, 1.0, 0.0])
    glTexGenfv(GL_Q, GL_OBJECT_PLANE, [0.0, 0.0, 0.0, 1.0])
    

    Was hat das zur Folge?

    S = Xo
    R = Yo
    R = Zo
    Q = Wo

    Dann werden die generierten Texturkoordinaten mit Texturmatrix T multipliziert:
    (S' T' R' Q') = (S T R Q) x T

    (S' T' R' Q') sind dann praktisch die Clip Koordinaten der Vertices.

    glMatrixMode(GL_TEXTURE)
    
    ' Model View Matrix
    glLoadMatrixf(Self.Projector.LocalInvMatrix)
    glMultMatrixf(Entity.LocalMatrix)
    
    ' Projector Projection Matrix
    glMultMatrixf(Self.ProjMatrix)
    
    ' BiasMatrix
    glMultMatrixf(TTexture.Bias)
    

    Ich mache doch hiermit auch nix anderes, als wie bei einer normalen Kamera!

    In Modelview lade ich erst die inverse Transformations Matrix der Kamera und multipliziere sie dann mit der Transformations Matrix des Meshs.

    In Projection kommt dann die Projketionsmatrix der Kamera.

    OpenGL multipliziert ModelViewMatrix M mit ProjectionMatrix P und es kommt MVP heraus. Als Shaderporgrammierer weiß ich, das ich die Objektkoordinaten der Vertices mit der MVP Matrix zu multiplizieren habe, das dann daraus Clip Koordinaten entstehen.

    Die Clip Koordinaten Xc, Yc, Zc und Wc werden dann zu den Normalized Device Koordinaten, in dem
    Xd = Xc/Wc
    Yd = Yc/Wc
    Zd = Zd/Wc
    durchgeführt wird.

    Das macht meines Erachtens auch OpenGL mit den Texturkoordinaten wegen der perspektivischen korrekten Texturierung. Also:
    S'' = S'/Q'
    T'' = T'/Q'
    R'' = R'/Q'

    Es entstehen nur somit Koordinaten im Intervall [-1, +1], um das zu verhindern muss man erst mit 0.5 multiplizieren(-> [-0.5, +0.5]) und dann noch 0.5 addieren -> [0.0, 1.0]. Und schon hat man die perfekten Texturkoordinaten.

    Lasse ich die BiasMatrix weg, scheint es fast zu funktionieren. Problem ist, er reagiert überhaupt nicht auf die Entfernung des Projektors. Ich kann ihn entfernen wie ich will, die projektzierte Textur bleibt immer gleichgroß, wobei sie ja größer werden müsste, je weiter ich den Projektor entferne.

    mfg olli



  • Vertex schrieb:

    Zumindest weiß ich jetzt, das die BiasMatrix doch zum Schluss multipliziert werden muss. Diese NVIDIA Doku machst ja genau andersherum.

    Halt! Das von NVIDIA wird schon stimmen, ich arbeite nämlich mit DX und da sind die Matrizen im Vergleich zu OGL transponiert, d.h. die Multiplikationsreihenfolge dreht sich genau um.

    Zu Deinen OGL Problemen kann ich nichts sagen da ich damit noch kein einziges Dreieck angezeigt habe. Aber Du erwähnst, dass Du Shader verwendest. Dann könntest Du die Projektion doch ganz einfach selbst ausrechnen oder nicht? Es ist einfach nur eine Matrixmultiplikation wie ich oben geschrieben habe.


Anmelden zum Antworten