# Correct lighting with photon mapping (solved, now full of picture)

This topic is 4896 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Right now all of the lights in my ray tracer are just simple spotlights with 90 degree cutoff angles that I arrange into a square to form a sort of area light. When tracing photons I use the Russian roulette technique described in Realistic Image Synthesis Using Photon Mapping. From each light (which I have positioned just below the ceiling) I choose a random vector, if the vector is within the cutoff I trace it through the scene. The photon is absorbed at the first diffuse surface it hits (unless the surface is a mix of diffuse and something else, then Russian roulette comes in). I have noticed a few problems with this: Two of them I believe to be caused by the same thing. As seen in this screenshot, the walls seem like they are too hard (no color bleeding), and the ceiling does not recieve any lighting at all. I think this is from a lack of what I believe is called diffuse interreflection. After searching the internet I have been unable to find a source that has the correct way to achieve this effect. I have considered doing something simple like having a small chance for the photon to bounce off of diffuse surfaces in some random direction (assuming lambertian surfaces), but I would like to see if anyone knows the correct way first. If this is the way it is usually done, what percentage (for walls of a cornell box) do you use to determine if it is absorbed or not? The second problem is that the screenshots from the aformentioned book all have a visible square light at the top of the scene. He has a screenshot of a ray traced (no photon mapping) scene with this light and hard shadows so I assume this is just a white polygon that he added to the scene afterwards since the shadows would be softer if he had actually used an area light. I'd like to make sure that this is the way to do this before I go and do something silly like raster a polygon in a raytraced scene. As usual, thanks in advance for your help. (edit: missed a ") [Edited by - Fibonacci One on August 27, 2005 2:05:03 AM]

##### Share on other sites

http://www.ypoart.com/tutorials/Photon-Mapping.htm

##### Share on other sites
photons don't necessarily get absorbed when they hit a diffuse surface, if this is the case how can you expect any color bleading? photons are always stored when they hit a diffuse surface and the decision to reflect them further or stop them(absorb) is done with russian roulete. russian roulete is not based on a "vector" russian roulete is an important sampling technique that is based on the average reflection value. it always helps to remember what exactly the photon map represents. it represents "incoming" illumination, therefore a photon is ALWAYS stored on a diffuse surface, and the decisison to reflect it is based on russian roulette. if I don't makes sense I can give you some sample code for what to do when a photon hits a diffuse surface. I think the problem here is you're thinking the photon map represents outgoing when in fact it represents incoming illumination, if you got the book read up on the radiance enstimate chapter, this is the most important, if you get it you understand the rest of the book.

##### Share on other sites
Quote:
 Original post by timwStuff
I'll reread the radiance estimate chapter while you reread my post. I'd also suggest you reread the section of the book on Russian Roulette. The idea is the choose between absorbtion, reflectance, refractance, ect... not to absorb AND maybe reflect. That would either introduce additional photons if the reflected photon was full power or not be russian roulette at all.

Thanks for the link codeGEN, I'll check it out.

##### Share on other sites
Quote:
Original post by Fibonacci One
Quote:
 Original post by timwStuff
I'll reread the radiance estimate chapter while you reread my post. I'd also suggest you reread the section of the book on Russian Roulette. The idea is the choose between absorbtion, reflectance, refractance, ect... not to absorb AND maybe reflect. That would either introduce additional photons if the reflected photon was full power or not be russian roulette at all.

##### Share on other sites
Quote:
 Original post by SneftelYes, additional photons ARE introduced.

After rereading that section a few times I still cannot believe this is how you use Russian Roulette to get the correct answer. Even this psudocode given in the book implies that it's one or the other and not one and maybe another.
p = d                 // d is the probability of reflectione = random()if (e < p)   reflect photon with power (flux)pelse   photon is absorbed

Either way, the correct use of Russian Roulette is not why I created this post; correct diffuse interreflection is. It's funny that the section of the book on Russian Roulette actually answered my question about when to diffusely reflect, but it this still leaves another question.

When you are tracing a photon through the scene, it starts out with some percentage of the color of the light it originated from. I have assumed (and we all know the expression about assumptions) that whenever a photon hits a surface that it's color (or whatever you wish to call it) is multiplied by the color of the surface unless it is specularly reflected. This seems to give the correct result, but that means that the ceiling of my screenshot would not have much white on it. It would instead be nearly all red, blue, and green. I expect it to have small traces of these colors from the aforementioned topics, but I know for certain that with a white light on a white ceiling should give me a mostly white ceiling. Can someone explain to me how I'm supposed to do my lighting to get an effect similiar to what's found in HWJ's screenshots?

Thanks.

##### Share on other sites
storing a photon is NOT absorption. I assure you I know the photon mapping concept well, I even took the class of the guy that invented the method at ucsd. photons represent incoming illumination. here is a simple examply with monocromatic photon of power 100 with a specular reflection to make it simple.

suppose we have specular reflection with reflection coefficent .5. and suppose we have 100 incoming photons 1 watt each. we can do one of two things.(I believe this same example is in the book). either a, we can, every time a photon hits, reduce it's power by .5 and trace another photon, or b chose a random number between 0,1 and if it's less then .5 we reflect with full power. either way we reflect 50 wats of power. now, EVERY time a photon hits a diffuse surface we store it, and the decisison to reflect it or not is based on russian roulette. as I said the photon map represents INCOMING illumination. suppose you built the map properly and you want to calculate the diffuse reflection(ie radiosity), you simply call irradiance_estimate() funciton. NOTE THE NAME IRRADIENCE(incoming flux area density), it is not named RADISOITY or radient EXITANCE. then you take that result, (which reperesents INCOMING illumination) and multiply it by the diffuse reflection BRDF, which is p/PI where p is the diffuse reflection coefficent.

[Edited by - timw on August 24, 2005 5:16:48 PM]

##### Share on other sites
Quote:
 Right now all of the lights in my ray tracer are just simple spotlights with 90 degree cutoff angles that I arrange into a square to form a sort of area light. .... From each light (which I have positioned just below the ceiling) I choose a random vector, if the vector is within the cutoff I trace it through the scene.

This is little off topic, but why not chose a random point on the square to emit each photon from instead of using multiple spotlights?

On the topic of rendering the actual light: Assuming the light isn't effected by it's own reflected light I think drawing a white polygon after the scene is rendered would be "pixel correct". As long as you took into account the poly's normal to change the brightness for the directional effect.

Of course, everything I know about photon mapping I learned from this thread so everything I said could be completely wrong.

##### Share on other sites
ya the photon mapping can handle any type of light, the easiest is the point light, and it's probably the one you should impliment first because you can easily verify your results. you simply termintate the photon on the first surface interaction, this will give you the irradience from direct lighting only, and for a point light there is a simple formula for the irradiance power*Dot(n,w)/(4*PI*r^2)

you can compare your results by directly implimenting this formula with the results obtainted by photon mapping and if the images look very similiar then it's a good indication you're taking the power into consideration in the right way. to trace photons from a point light it's so easy, just pick a random direction and trace. diffuse area lights are simple also, just pick a random position on the rectangle, and pick a direction that is weighed by cos. (acos(sqrt(random1)), 2*PI*random2) this will give you a direction with a reflection proablity proportional to the cos of the angle between the normal and the reflection vector. this is also the same formula you use to trace diffusly reflective photons. a diffuse area light like your talking about is equivilant to a diffusely reflective surface, with irradience = to the radiosity of the light with a diffuse reflection value of 1, if that makes any sense. but you gotta make sure that when you calculate the directon of the emmited photon from a diffuse area light you take into consideration the cos probaility by the above formula, you can't just pick a random direction about the hemisphere like a point light, if you did that, you'd have to multiply the photon power by n^dir. and some photons would have little power which would suck.

anyway, here is the formula to compute a diffuse reflection direction vector given a surface normal. also how do you guys get the nice windows for your code posts? I can't figure it.. anyway I hope this function help, when picking direction for diffuse reflection or picking direction emmiting photons for a diffuse area light..

Vector3 *getRandDiffuse(Vector3 *pVector, Vector3 *vNormal,
int iStratTheta = 1, int iStratPhi = 1, int i = 1, int j = 1);

#define PI2 6.283185307179586476925286766559

//generate a random diffuse direction given a normal to surface
Vector3 *getRandDiffuse(Vector3 *pVector, Vector3 *vNormal,
int iStratTheta, int iStratPhi, int i, int j) {
Vector3 vBasis1, vBasis2;
if(abs(vNormal->x) > abs(vNormal->y)) {
//use y
vBasis1.Set(0, 1, 0);
}
else {
//use x
vBasis1.Set(1, 0, 0);
}

//find comp basis1 perpendicular to normal and use that as basis1
vBasis1 = vBasis1 - ((*vNormal)^vBasis1)*(*vNormal);
vBasis2 = (*vNormal)*vBasis1;

vBasis1.Normalize();
vBasis2.Normalize();

//for stratification uncomment and comment above
float fTheta = asin(sqrt((j - frand())/(float)iStratTheta));
float fPhi = PI2*(i - frand())/(float)iStratPhi;

*pVector = sin(fTheta)*sin(fPhi)*vBasis1 + cos(fTheta)*(*vNormal) + cos(fPhi)*sin(fTheta)*vBasis2;

pVector->Normalize();

return pVector;
}

this function will also stratify samples but if you dont need that functionality just call it with the defualt paramaters in the prototype.

Tim

##### Share on other sites
Sorry for the slow responce... I've been busy moving into a new apartment. Timw, you can write source code by using the [ source ] and [ /source ] tags (Without the spaces).

So I've implemented all of the changes we've discussed and it's looking pretty good. I don't really need stratification since I plan on using quite a few photons for all of the scenes I'm going to make. Since I don't need it, I've made some assumptions about changes I can make to the function you wrote. I got rid of all of the "i -" and "j -" since 1 - a random number between 0 and 1 is just another random number. This leaves me with this:

Vector m1 = Vector(1.0f, 0.0f, 0.0f);if (abs(n.vec[0]) > abs(n.vec[1])){	m1.vec[0] = 0.0f;	m1.vec[1] = 1.0f;}	m1 = m1 - n.Dot(m1)*n;Vector m2 = n.Cross(m1);m1.Normalize();m2.Normalize();float theta = asin(sqrt((float)frand()));float phi = PI2 * frand();Vector dir = sin(theta)*sin(phi)*m1 + cos(theta)*n + cos(phi)*sin(theta)*m2;dir.Normalize();return dir;

The problem is that this still does seem to leave room for photons to go directly from the light to the ceiling. How do I light my ceiling without adding more lights?

Thanks.

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 15
• 9
• 11
• 9
• 9
• ### Forum Statistics

• Total Topics
634135
• Total Posts
3015752
×