Probleme mit Path Tracing

F.b

Lieutenant
Registriert
Feb. 2008
Beiträge
514
Hi,
nachdem mein Raytracer ein "Upgrade" auf globale Beleuchtung mittels Path Tracing erfahren hat, hab ich Probleme mit vereinzelt sehr hellen Pixeln. Beide Bilder wurden jeweils mit 50 Samples/Pixel gerendert:
Bild 1
Bild 2
Das Problem tritt verstärkt auf, wenn spiegelnde Objekte in der Szene vorhanden sind. Ich dachte, es könnte evtl. daran liegen, dass wenn ein Punkt nicht direkt beleuchtet wird und mit späteren Strahlen eine Lichtquelle trifft, die zurückgegebene Farbe mit der Lichtintensität multipliziert wird. Nur wüsste ich nicht, wie sich das vermeiden ließe. Habt ihr 'ne Idee?
Der Tracing-Code:
Code:
public ColorRGB trace(Ray ray,int depth,double oldr,boolean shadow, boolean soft, boolean rekur, boolean global, boolean seen) {
		if(depth >= maxdepth)
			return new ColorRGB(0,0,0);
		
		Point3D in = getNearestIntersection(ray); // Naheliegendster Schnittpunkt
		
		if(in.pr == null)
			return background;
		
		Primitive hit = in.pr;
		
		double diffus = hit.getMat().diff;
		double reflective = hit.getMat().refl;
		double refractive = hit.getMat().refr;
		
		ColorRGB gesamt = new ColorRGB(0,0,0);
		ColorRGB direkt = new ColorRGB(0,0,0);
		ColorRGB indirekt = new ColorRGB(0,0,0);
		ColorRGB refrac = new ColorRGB(0,0,0);
		ColorRGB reflec = new ColorRGB(0,0,0);
		ColorRGB objekt = new ColorRGB(in.pr.getMat().c);
		
		if(hit.isLight()) {
			if(hit.l.spot) { // Wenn die Lichtquelle ein Spotlight ist
				Vector3D nor = hit.getNormal(in); // Normale an der getroffenen Stelle
				nor.normalize();
				if(nor.dotProduct(hit.l.normale) > hit.l.angle) { // Wenn sich Treffpunkt innerhalb des Lichtkegels befindet
					objekt = new ColorRGB(hit.l.c);
					if(seen == false) { // Wenn das vorherige Objekt schon direkt beleuchtet wurde
						objekt.multi(hit.l.inten);
						return objekt;
					}
					else {
						return objekt;
					}
				}
			}
			else {
				if(seen == false) { // Wenn das vorherige Objekt schon direkt beleuchtet wurde
					objekt.multi(hit.l.inten);
					return objekt;
				}
				else {
					return objekt;
				}
			}
		}
		
		Vector3D normale = hit.getNormal(in);
		normale.normalize();
		
		direkt.add(objekt);
		direkt.multi(in.pr.getMat().amb);
		
		Light licht = null;
		
		// Direkte Beleuchtung
		for(int i = 0; i < l.size(); i++) {
			licht = l.elementAt(i);
			if(hit.isLight())
				if(hit.l.equals(licht))
					continue;
			if(soft)
				licht.pos = licht.ls.getRandomLight();
			if(!hit.shadowed(in, v, licht) || !shadow) {
				seen = true;
				direkt.add(hit.shade(ray, in, licht));
			}
		}
		
		double ru = Math.random(); // Russisches Roulette
		
		if(diffus > 0 && ru < diffus && global) { // Indirekte Beleuchtung
			Ray diffRay = getRandomRay(in,normale);
			Main2.rays++;
			indirekt.add(trace(diffRay,depth+1,oldr,shadow,soft,rekur,global,seen));
			indirekt.multWithColor(objekt);
		}
		
		if(refractive > 0 && (ru > diffus & ru < diffus+refractive) && rekur) { // Brechung
			double rindex = hit.getMat().brind;
			if(in.inside) {
				rindex = oldr;
				oldr = hit.getMat().brind;
				normale.mult(-1);
			}
			if(hit.getMat().fresnel) {
				Material neM = getFresnel(oldr,rindex,ray,normale);
				refractive = neM.refr;
				reflective = neM.refl;
			}
			Ray refrRay = getRefractedRay(oldr,rindex,normale,in,ray);
			if(refrRay != null) {
				Main2.rays++;
				refrac.add(trace(refrRay,depth+1,oldr,shadow,soft,rekur,global,false));
				refrac.multWithColor(in.pr.getMat().c);
				refrac.multi(refractive);
			}
		}
		
		if(reflective > 0 && ru > diffus+refractive && rekur) { // Reflexion
			Ray reflRay = getReflectedRay(ray,normale,in);
			if(in.pr.getMat().sharp > 0) { // Diffuse Reflexion
				reflRay = getRandomReflectedRay(reflRay,in.pr.getMat().sharp);
			}
			Main2.rays++;
			reflec.add(trace(reflRay,depth+1,oldr,shadow,soft,rekur,global,false));
			reflec.multi(reflective);
		}
		
		gesamt.add(direkt);
		gesamt.add(indirekt);
		gesamt.add(refrac);
		gesamt.add(reflec);
		
		return gesamt;
	}
 
Zuletzt bearbeitet:
Das versstärkte auftauchen der hellen Pixel dürfte mögicherweise wirklich an den Spiegeln liegen, da diese das Licht ja - kenn mich nicht aus - weiterwerfen oder zumindest weitere Berechnungen erforderlich machen.

Die hellen punkte könnten theoretisch auf Gleitkommaprobleme zurückzuführen sein. Aber das dürfte man herausfinden können wenn man andere raytracer projekte studiert. Ich seh aber kein wirkliches Problem damit in deinem Code. Höchstens das irgendein float/double nen fehler von 0.00001 weiterpropagiert.
 
Das mit dem 0.000001 hab ich bereits gefixt, das hat aber nur schwarze statt helle Pixel verursacht. Das Problem mit den anderen Raytracer-Projekten ist, dass es wirklich schwer ist, Code davon im Internet zu finden, meißt sind es nur PDF-Dokumente, in welchen das Grundprinzip erklärt wird.
EDIT: vielleicht sollte ich hinzufügen, dass mein Path Tracer explizite direkte Beleuchtung verwendet.
 
Zuletzt bearbeitet:
Zurück
Oben