Raytracer



  • Hallo zusammen!
    Zur Abwechslung hab ich mal ne wieder ein wahrscheinlich simples Problem.

    Ich hab im Netz ein Grundgerüst für einen simplen raytracer gefunden und will versuchen den auszuimplementieren. Bisher gibt es nur eine Szene mit Kugeln und die Schnittberechnung scheint zu funktionieren. Allerdings sitze ich gerade am diffusen Lichtanteil und bekomme sehr seltsame Effekte:

    http://img266.imageshack.us/my.php?image=raytracingye7.gif

    Berechnung des diffusen Anteils:

    Vector lightIn = hit.operator -(lights[0]->P);
    lightIn.normalize();
    N.normalize();
    color = material->color * (RADTODEG(lightIn.dot(N));
    

    Wobei N die Normale ist, und hit der Schnittpunkt des Strahls mit der Oberfläche der Kugel.

    Die Normale in einem Punkt der Kugeloberfläche berechne ich durch:
    Oberflächenpunkt - Kugelmittelpunkt.

    Vielleicht kennt ja jemand diesen Effekt (siehe Link) und kann mir sagen, wie sowas zu Stande kommt?

    Grüße
    mtx



  • was soll die RADTODEG-Umwandlung?



  • o.k. stimmt, das hat wohl nix da zu suchen.
    Das macht die Sache schon mal deutlich besser 😃

    Sieht aber immernoch seltsam aus:

    http://img440.imageshack.us/my.php?image=raytracing2dt7.gif

    Hab den Code folgendermaßen verändert:

    Vector lightIn = hit.operator -(lights[0]->P);
    lightIn.normalize();
    N.normalize();
    
    double diff_res =lightIn.dot(N);
    color = material->ambient * material->color;		//ambient part		
    color += material->diffuse * material->color * diff_res;	//diffuse part
    


  • mtx schrieb:

    Sieht aber immernoch seltsam aus:

    http://img440.imageshack.us/my.php?image=raytracing2dt7.gif

    Hab den Code folgendermaßen verändert:

    Vector lightIn = hit.operator -(lights[0]->P);
    lightIn.normalize();
    N.normalize();
    
    double diff_res =lightIn.dot(N);
    

    Je nachdem wie rum dein Normalenvektor orientiert ist, ist lightIn falsch herum gerichtet. Du musst lights[0]->P - hit schreiben, um einen Vektor vom Objekt zur Lichtquelle zu erhalten. Zum anderen solltest du testen, ob diff_res ueberhaupt im Bereich [0,1] liegt. Ansonsten rechnest du mit negativen Farben, was bei dir zu einem Ueberlauf zu fuehren scheint.

    btw: Es gibt hier [cpp]-Tags, die fuer C++-Code besser geeeignet sind als [code].



  • Mensch! Zwei Volltreffer, alle Achtung 🙂
    Vielen Dank!

    Oha, die cpp-Tags sind mir noch gar nicht aufgefallen. Die werd ich dann beim nächsten mal benutzen, auch für den Hinweis: Danke!


  • Mod

    Christoph schrieb:

    Zum anderen solltest du testen, ob diff_res ueberhaupt im Bereich [0,1] liegt. Ansonsten rechnest du mit negativen Farben, was bei dir zu einem Ueberlauf zu fuehren scheint.

    alternativ kann man *0.5f+0.5 rechnen,sodass diff_res rundherum um die kugel ein shading erstellt. das schaut gerade auf der licht abgewendeten seite dann besser aus als nur die einfarbige version beim test.
    (verwendet man z.b. in halflife2).



  • hm, das verstehe ich nicht.
    Der Wertebereich wäre dann doch [0.5, 1] und damit wäre doch die ganze Szene "überbeleuchtet" oder?



  • mtx schrieb:

    hm, das verstehe ich nicht.
    Der Wertebereich wäre dann doch [0.5, 1] und damit wäre doch die ganze Szene "überbeleuchtet" oder?

    Nö, du verschiebst [-1,1] nach [0,1], anstatt einfach alle Werte < 0 zu clampen.
    Der Vorteil ist wohl (hab das auch gerade zum 1. Mal gelesen, ergibt aber Sinn), dass ab einem Winkel von >= 90° (also der vom Licht abgewandten Seite) nicht schlagartig die diffuse Beleuchtung 0 ist, sondern sich die Schattering über das ganze [0,180°] Intervall erstreckt. Beim Clampen hast du also den Mittelwert von 0.5 bei 60° (cos^-1(0.5)) und bei der *0.5+0.5 Methode ist der Mittelwert genau bei 90°. Nähert auch die indirekte Beleuchtung der realen Welt (im Sinne der Optik) besser an als der ambiente Term.



  • oh, *gg* stimmt. War irgendwie der Meinung, dass das ursprüngliche Wertebereich [0,1] ist, aber [-1,1] ist natürlich richtig. Danke dir.


Anmelden zum Antworten