[openGL] Zwei Flächen nah beieinander



  • Naja, irgendwo wirst du ja eine Projektionsmatrix erstellen, entweder per Hand (in Deinem Fall wohl eher unwahrscheinlich) oder durch den Aufruf von glOrtho, glFrustum, gluPerspective, gluOrtho2D etc.

    Dort gibst du unter anderem zNear und zFar an. Die Genauigkeit des Tiefenpuffers ist aber abhängig vom Verhältnis der beiden Werte. Also solltest du dort möglichst nicht sowas wie zNear = 0.0001 und zFar = 10000 verwenden.

    Über den Parameter von glDepthFunc gibt du an, wann Fragmente den Tiefentest (aktiviert mit glEnable(GL_DEPTH_TEST)) bestehen.



  • Danke schonmal! Jetzt kapier ich einiges mehr :).

    Also der Tiefenpuffer wird in meinem Code nicht verändert. Der sollte ja
    standardmäßig angeschaltet sein oder?

    Ich benutze alternativ die perspective und die orthogonal Projektion.

    Perspective hat folgende Parameter:
    60.0, B/H, 0.001, 6.0

    Bei Orthogonal werden ja lediglich die Sichtgrenzen eingegeben.

    Mit welchen Parametern bekomme ich jetzt bei den beiden Projektionen
    die bessere Tiefentreue hin?

    Hier die Projektionsfunktion:
    (OpenGL ist hier ein .net Panel-Objekt)

    // Clear the window for next redraw                
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);				
    
    // Höhe und Breite des Fensters in dem gezeichnet wird
    int w=OpenGL->Width,h=OpenGL->Height;
    glViewport (0,0,w,h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    
    // Kameraposition berechnen
    double a=cos(m_elevation);
    double x=(m_cameradist)*a*sin(m_azimuth);
    double y=(m_cameradist)*a*cos(m_azimuth);
    double z=-m_cameradist*sin(m_elevation);
    
    // In Perspektive oder orthogonal zeichnen
    if (rbtn_perspective->Checked)
    {
    gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 0.001, 6.0);
    }
    else if (rbtn_orthogonal->Checked)
    {
    glOrtho(-m_cameradist*((GLfloat) w/(GLfloat) h)*0.5,	//linke Sichtgrenze
        m_cameradist*((GLfloat) w/(GLfloat) h)*0.5,		//rechte Sichtgrenze
        -m_cameradist*0.5,	//untere Sichtgrenze
        m_cameradist*0.5,	//obere Sichtgrenze
       -40,	//hintere Sichtgrenze
       40);	//vordere Sichtgrenze
    }
    
    // Position und Ausrichtung der Kamera
    gluLookAt(x				//camposx
      , y			//camposy
      , z+0.07		//camposz
      , 0,0,0.07	//viewing centre
      , 0			//"up" directionx
      , 0			//"up" directiony
      , -1);			//"up" directionz
    
    // Licht bewegt sich mit Viewpoint
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    GLfloat light_position1[] = { (float)(x), (float)(y), (float)(z), 0.0 };
    glLightfv(GL_LIGHT0, GL_POSITION, light_position1);
    
    // Drehen nach den entsprechenden Controls
    glRotated(Convert::ToDouble(num_AngleX->Value), 1, 0, 0);
    glRotated(Convert::ToDouble(num_AngleY->Value), 0, 1, 0);
    glRotated(Convert::ToDouble(num_AngleZ->Value), 0, 0, 1);
    
    // Translation des Modells durch die entsprechenden Slider
    glTranslated(((double)Slider_x_AchsenOffset->Value)/100,((double)Slider_y_AchsenOffset->Value)/100, ((double)Slider_z_AchsenOffset->Value)/100);
    
    // Alle Komponenten zeichnen
    for (int i = 0; i < m_Components->Count; i++)
    {
    m_Components[i]->Render();
    }
    
    // Achsen zeichnen
    glDisable(GL_LIGHTING);
    
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    
    glBegin(GL_LINES);
    glColor3d (1,0,0);
    glVertex3d(0,0,0);
    glVertex3d(1,0,0);
    
    glColor3d (0,1,0);
    glVertex3d(0,0,0);
    glVertex3d(0,1,0);
    
    glColor3d (0,0,1);
    glVertex3d(0,0,0);
    glVertex3d(0,0,1);
    glEnd();
    
    glEnable(GL_LIGHTING);
    
    // Neue Zeichnung anzeigen
    SwapBuffers(m_hDC);
    


  • Nein, das depth-testing ist nicht standardmäßig aktiviert.
    Wie gesagt erfolgt dies über glEnable(GL_DEPTH_TEST).

    Du könntest mal probieren, den Wert für zNear von 0.001 auf 0.01 zu ändern. Vlt führt dies ja schon zum Erfolg.



  • Wenn es zur Platzierung von Near und Far Plane kommt dann gibts eine Grundregel: Near so weit weg und Far so nahe dran wie nur möglich um den Depthbuffer optimal zu nutzen. Ich bin mir ziemlich sicher dass es sich bei dem was du beschreibst um z-Fighting handelt...



  • Kannst du mal einen Screenshot posten der diese "Schraffierung" zeigt?



  • So ich hab mal nen Screenshot gemacht:

    http://img88.imageshack.us/img88/4110/schraffierung.jpg

    Man sieht die Perspective Projection. Links etwas weiter entfernt, rechts
    ziemlich nah dran. Die Pfeile hab ich an den Stellen reingezeichnet, wo
    ein neues paar Rechteckecke übereinander gezeichnet wird.
    Interessant ist, dass bei der kurzen Entfernung und perspektivischen Sicht
    die Schraffierung verschwindet.
    Bei beiden Projektionen verschwindet die Schraffierung, wenn man in einem
    Winkel von etwas über 45° auf die Fläche blickt.
    Die Normalenvektoren der übereinanderliegenden Rechtecke zeigen übrigens in
    entgegengesetzte Richtungen.
    UND: die Schraffierung sieht man nur von einer Seite...

    any ideas?
    GL_Depth_Test war übrigens doch eingeschaltet (siehe Z. 48 vom Code). Könnte
    es evtl. noch an den anderen Einstellungen liegen die dort vorgenommen werden?


  • Mod

    Tomatojuice schrieb:

    any ideas?

    dot hat das eindeutig auf den punkt gebracht:

    dot schrieb:

    Ich bin mir ziemlich sicher dass es sich bei dem was du beschreibst um z-Fighting handelt...

    und inter2k3 die frage deren antwort zu deiner loesung fuehren wird.



  • okay, also ich hab jetzt mal ein wenig mit near und far rumgespielt.
    Ich bekomms so hin, dass es nicht mehr flimmert, aber er schneidet schon
    sehr sehr früh den Vordergrund weg.

    Bei Orthogonaler Sicht hab ich ja garkein znear oder zfar. Kennt jemand
    dafür andere Parameter?

    Übrigens wenn ich die GlDepthFunc auf GL_LESS stelle macht die eine Seite
    Probleme, bei GL_LEQUAL die andere.
    Also müsste es doch theoretisch etwas geben, was beides verbindet?



  • Nur mal so eine Frage: Wofür genau hast du eigentlich zwei koplanare Flächen so nah beieinander?



  • Tomatojuice schrieb:

    Bei Orthogonaler Sicht hab ich ja garkein znear oder zfar.

    Doch klar. Der einzig Unterschied ist, dass dein Sichtvolumen ein Quader ist, und kein Frustum.



  • Tomatojuice schrieb:

    Bei Orthogonaler Sicht hab ich ja garkein znear oder zfar.

    Ausschnitt aus deinem code:

    glOrtho(-m_cameradist*((GLfloat) w/(GLfloat) h)*0.5,    //linke Sichtgrenze
        m_cameradist*((GLfloat) w/(GLfloat) h)*0.5,        //rechte Sichtgrenze
        -m_cameradist*0.5,    //untere Sichtgrenze
        m_cameradist*0.5,    //obere Sichtgrenze
       -40,    //hintere Sichtgrenze  <-- zNear
       40);    //vordere Sichtgrenze  <-- zFar
    }
    

    Hier also zNear = -40 und zFar = 40.

    Bei gluOrtho2D wird zNear per default auf -1 gesetzt und zFar auf 1.



  • dot schrieb:

    Nur mal so eine Frage: Wofür genau hast du eigentlich zwei koplanare Flächen so nah beieinander?

    Also, ich möchte einen Hohlzylinder darstellen, auf dem mehrere kleine Objekte
    drauf sind. Da die Objekte auch sehr klein sind, soll die geringe Wandstärke
    vom Zylinder auch dargestellt werden.

    inter2k3 schrieb:

    -40,    //hintere Sichtgrenze  <-- zNear
       40);    //vordere Sichtgrenze  <-- zFar
    

    Thx!
    hehe, wollt mir schon vor den Kopf schlagen, aber in meinem
    Code wars ja noch nicht drin ^^.



  • Zum Hohlzylinder:

    Du wirst wahrscheinlich einen äusseren Zylidnermantel und einen inneren Zylindermantel zeichnen.
    Du bist schon auf die richtige Idee gekommen, nur hast du sie nicht vollständig umgesetzt. Für die Vertices des inneren Mantels gibst du Normalen an, die in die entgegengesetzte Richtung der Normalen des äusseren Mantels zeigen. Soweit ist das richtig.
    Allerdings differenziert OpenGL nicht anhand der Normalen, ob es sich um eine Vorderseite oder eine Rückseite handelt, sodnern durch die Reihenfolge, in der die Vertices angegeben werden. Die Normalen wären beispielsweise für die Beleuchtung relevant.

    Per default werden Vertices einer Vorderseite (front-face) entgegen des Uhrzeigersinns angegeben (GL_CCW <- counter clock-wise).
    So würdest du die Vertices für den äusseren Mantel angeben. Da es sich beim inneren Mantel um die "Rückseite" handelt, gibst du die Vertices hier im Uhrzeigersinn an.

    Mit glCullFace(GL_BACK) legst du fest, dass die Rückseite nicht gerendert werden soll.
    Dann aktivierst du noch das face-culling mit glEnable(GL_CULL_FACE) und das Problem sollte nicht mehr existieren.


  • Mod

    wenn du genau weisst was du zeichnen willst, und was worauf erscheinen soll, dann kannst du den zbuffer ausschalten und einfach in der gewuenschten reihenfolge zeichnen, dann sollte es auch gehen


Anmelden zum Antworten