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:
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: