Raytracer - Bildebene richtig einstellen



  • Hallo...

    Ich habe mir eine Grafikengine geschrieben, welcher OpenGL und ein Raytracer zur Ausgabe nutzt.

    Mein Problem ist, das die Bilder, welche über OpenGL gerendert werden von der Perspektive etwas anders aussehen, als wenn ich sie mit dem Raytracer rendere.

    Wenn ich einen einzelnen Punkt in 3D-Koordinaten habe, dann werden die Pixelkoordinaten bei OpenGL durch die Modelviewmatrix, Projektionsmatrix und die Viewporttransformation bestimmt.

    Beim Raytracer hängt die letztendliche Bildschirmposition des Punktes von der Bildebene und dem Sichtpunkt(Augpunkt) ab.

    Wie kann ich die Position des Augpunktes beim Raytracer aus den OpenGL-Angaben berechnen?

    Bei OpenGL schreibe ich:

    gluPerspective(45.0f, (float)WindowWidth / (float)WindoHeight, 0.1f, 3000.0f);

    Beim Raytracer berechne ich die Primärstrahlen so:

    kameraAbstand = 2.58f;//Wurde durch probieren ermittelt
    for (int y = 0; y < bildHeight; y++)//x,y laufen durch die Farbpuffer der
    for (int x = 0; x < bildWidth; x++)//Bildebene
    {
    Strahl strahl = new Strahl();//Primärstrahl
    strahl.start = new Vektor(0, 0, -2.41f + kameraAbstand);
    Vektor bildEbenenPunkt = new Vektor(+(x * 2.0f / bildPuffer.Length - 1.0f),
    -(y * 2.0f / bildPuffer[0].Length - 1.0f),
    -2.41f);
    strahl.richtung = bildEbenenPunkt - strahl.start;
    }
    //bildPuffer.Length ... Bildbreite
    //bildPuffer[0].Length ...Bildhöhe

    Hat jemand ein Tipp von euch wie ich den korrekten Wert für die Variable "kameraAbstand" berechne?
    Außerdem: Ist das richtig, das ich die x und y-Werte des Richtungsvektor vom Primärstrahl("strahl.richtung") auf Werte zwischen -1 und +1 Mappe? => Weil hierdurch wird ja schließlich auch der Kameraöffnungswinkel bestimmt.

    Bitte helft mir, ich bin noch recht neu auf dem Gebiet der Grafikprogrammierung 😞



  • kameraAbstand = 2.58f;//Wurde durch probieren ermittelt
    

    und ist falsch. Nach meiner Berechnung müssen es 1.2 sein

    gradRad=45.0*pi/180.0
    kameraAbstand=1.0/(2*tan(gradRad/2))
    

    //edit was ist eigentlich -2.41 für ein komischer Wert?
    //edit2 ahh dein Bilschirm ist nicht auf Breite 1 normiert sondern 2, dann kommt als Ergebnis 2.4 raus. das kommt durch dein Mappen auf -1 +1

    gradRad=45.0*pi/180.0
    kameraAbstand=1.0/tan(gradRad/2)
    


  • Mensch Otze, das war genau der richtige Tipp.

    Die Berechnung für den Kameraabstand stimmt jetzt. Ich muste nur noch das Mapping der X- und Y-Koordinaten anpassen.

    Y wird von -0.5 bis +0.5 gemappt.
    X wird abhängig vom Verhältniss zwischen Fensterbreite und Fensterhöhe gemappt.

    Der richtige Code sieht nun so aus:

    double gradRad = (45.0 * Math.PI / 180.0
    kameraAbstand = (float)(1.0 / (2*Math.Tan(gradRad / 2)));
    
    float f = (float)bildPuffer.Length / (float)bildPuffer[0].Length;
    
    for (int y=von;y<bis;y++)
      for (int x = 0; x < bildPuffer.Length; x++)
      {
         Strahl strahl = new Strahl();
         strahl.start = new Vektor(0, 0, kameraAbstand);
    
         Vektor bildEbenenPunkt = new Vektor(
              +(x / (float)bildPuffer.Length * f - f/2),
              -(y / (float)bildPuffer[0].Length - 0.5f), 
              0);
         strahl.richtung = bildEbenenPunkt - strahl.start;
      }
    

    Danke nochmal für deine Hilfe Otze 👍



  • Du duerftest am Ende trotzdem immer das Problem haben, das an near und far plane geclipped wird, was ein Raytracer normalerweise nicht macht.



  • Das near und far-Clipping ist beim Raytracer kein Problem. Kann man entweder bei der Schnittpunkteabfrage machen oder man übergibt den Raytracer nur die Dreiecke, welche im OpenGL-Sichtbereich liegen.

    Das stört mich jetzt also eher weniger.



  • Achso, ich hatte das so verstanden: Wie mache ich meine OGL Ausgabe, das sie dem Raytracer entspricht?



  • Nene, eher andersrum. Ich Render erst mit OpenGL und positioniere die Kamera und dann raytrace ich. Da bin ich eher froh, wenn ich die Einschränkung mit den Clipping nicht habe.

    Aber noch ne andere Sache. Ich habe gerade herrausgefunden, das man das Raytracing auch über die GPU rendern kann. Da gibts zum einen den Weg über

    1. OpenCL + OpenGL
    2. DirectX 11 + Direct Compute

    Laut diesem Video hier: http://www.youtube.com/user/anooprthomas#p/u/4/2fS9o4pH2Vw

    ist Weg 1 etwas schneller.
    Hat jemand von euch sowas schonmal gemacht oder paar Links, wo ich mir OpenCL oder Direct Compute mal näher ansehen kann. Scheint ein guter Ansatz für schnelles Raytracing zu sein.



  • Ich hab solchen aehnlichen Sachen in HEB gemacht. Ich glaube nicht das DX oder OGL prinzipiell dabei schneller ist, einer der Shader wird einfach langsamer sein. Ich habe meine Raytracer immer direkt per Shader implementiert und optimiert.



  • Wieso nimmst du nicht gleich Optix? http://www.nvidia.com/object/optix.html
    Das ist ein NVidia Raytracer Framework, basierend auf CUDA.



  • @this->that: Na also, sowas hab ich doch gesucht.


Anmelden zum Antworten