Problem mit Phong beim Raytracing
-
Hallo C/C++ Community,
ich schreibe einfach mal hier rein, da sich das wohl am besten für mein Problem anbietet. Ich programmiere unter C mit (OpenGL benutze ich dabei eigentlich nur zum Pixel färben des Bildschirms) ein Raytracing-Programm und benutze dafür den Phong Algorithmus mit Halfway-Vektor zum Erzeugen der Farben.
Allerdings beobachte ich dort das Phänomen, dass beim Entfernen meiner Kugeln von der Lichtquelle das Specular-Light immer stärker (und damit quasi größer) wird. Dies sieht für mich irgendwie nach einem falschen Vektor(-berechnung) aus, doch ich habe einfach nichts finden können und schon so ziemlich alle Vektoren mal normalisiert und mal nicht...
Ob mir da wohl jemand helfen kann? Ich füge einfach mal betreffenden Code bei:
struct color localLight(float g[3], float n[3], float ka, float kd, float ks, float ns, float eye[3]) { int i; float tmp, tmp2; float tmp3[3], l[3], v[3], h[3], r[3]; struct color ambient = addCol(clearCol, clearCol); struct color diffuse = addCol(clearCol, clearCol); struct color specular = addCol(clearCol, clearCol); struct color result = addCol(clearCol, clearCol); struct color id, is; // Ambient light ambient.red = ka * 0.25; ambient.green = ka * 0.25; ambient.blue = ka * 0.25; // Diffuse intensity is.red = 1; is.green = 1; is.blue = 1; // Diffuse intensity id = light1.color; // Diffuse light vectorDifference3f(l, light1.origin, g); getUnitVector3f(n, n); getUnitVector3f(l, l); tmp = dotProduct3f(n, l); diffuse.red = kd * id.red * tmp; diffuse.green = kd * id.green * tmp; diffuse.blue = kd * id.blue * tmp; // Specular light scalarProduct3f(tmp3, n, 2*dotProduct3f(n, l)); vectorDifference3f(r, tmp3, l); getUnitVector3f(r, r); vectorDifference3f(v, eye, g); getUnitVector3f(v, v); vectorAddition3f(h, l, v); // Halfway Variante getUnitVector3f(h, h); // Halfway Variante tmp2 = dotProduct3f(n, h); // Halfway Variante if (tmp>0 && tmp2>0) tmp2 = pow(tmp2, ns); else tmp2 = 0; specular.red = ks * is.red * tmp2; specular.green = ks * is.green * tmp2; specular.blue = ks * is.blue * tmp2; result = addCol(ambient, diffuse); result = addCol(result, specular); return result; }
g ist der Schnittpunkt mit dem Objekt, der übergeben wird
n ist die Normale des Objekts an dieser Stelle (berechnet mit vectorDifference3f(n, g, sphere.origin);)
eye die Camera-Position
ka, kd und ks die Koeffizienten für ambient, diffuse und specular Licht. Dort werden übrigens natürlich nur floats 0≤k≤1 übergeben; und ns = 10
getUnitVector3f(a, b) berechnet mir a = Einheitsvektor(b) - und ja, korrekt
addCol addiert zwei Farben (Farben sind einfach struct mit 3 floats)
scalarProduct3f(a, b, c) speichert das Skalarprodukt von Vektor b mit Skalar c in a
dotProduct3f(a, b) gibt Punktprodukt zurück von a und b
VectorAddition3f(a, b, c) speichert Addition von b und c in a (analog VectorDifference3f)Ach ja: Ich habe eine Lichtquelle (light1, enthält float[3] origin als Ursprung und eine color) sowie eine Kugel sphere mit float radius und float[3] origin als Ursprung.
Hm, vielleicht sieht ja jemand irgendwas...
ciao,
Christian
-
Es ist traditionell nicht so einfach, in fremdem Code einen logischen Fehler zun finden, aber hier scheint mir etwas komisch zu sein (bitte nicht hauen, falls es nicht massgebend sein sollte):
scalarProduct3f(tmp3, n, 2*dotProduct3f(n, l)); vectorDifference3f(r, tmp3, l);
Dies entspricht in meinem Code (ebenfalls specular lighting im Raytracer) einem Aufruf
vector<>::reflect(v, l)
, alsov - 2 * dot(v, n) * n
; deiner Beschreibung nach ergibtvectorDifference3f(r, tmp3, l)
aber2 * dot(v, n) * n - v
, ein kleiner, aber dennoch bemerkenswerter Unterschied. Der korrekte Aufruf wäre also:vectorDifference3f(r, l, tmp3);
Aber ich kann mich auch irren, es war ein langer Tag und ich hatte die Schweinegrippe
MfG
-
/rant/ schrieb:
Aber ich kann mich auch irren, es war ein langer Tag und ich hatte die Schweinegrippe
gute besserung und steck uns hier nicht an
@topic
wenn es entfernungsabhaengig anders wird, dann vergisst du wohl die vectoren die du mit verschiedenen positionen ausrechnest zu normalisieren.schau dir nochmal ein tutorial (oder was auch immer deine quelle war) an, da sollte oefter mal ein normalize sein.
-
Okay, sorry bin gerade erst zurückgekommen, deswegen bisher net geantwortet.
Also es lag daran, dass meine Funktion für Einheitsvektoren bei Aufruf getUnitVector3f(array, array); mit array als ein und derselben Variable für Quell- und Zielarray direkt jeden Index des Ziels nacheinander geschrieben hat ohne erst alles zwischenzuspeichern und dann in die Variable zu schreiben. Trotzdem danke für's antworten, war ein dummer Fehler... aber braucht einfach wieder lange um so etwas zu finden. Naja, so lernt man's wenigstens auf die "harten Tour"ciao