Pinhole camera


Pinhole camera

I modeled the pinhole camera by creating a real object that is an infinite plane, with a pinhole with given point and radius. The rest of the engine is unchanged. Every object has a shape and material associated with it. The shape determines whether the photon has intersected the object, and the material determines the bouncing.

I did four experiments: (with motion blur, without motion blur) x (with occluder, without occluder). The reason I added an extra occluder to the specification is I believe the direct photons from the source to the sensor will account for ~95% of the energy of the scene. Not only that, the area density of the direct photons is roughly ~25 times the one from the secondary photons (generated from bounces off the sphere). The back of the envelope calculations are here. This means the sphere should be too dim for us to see anything. So I simply placed an occluding sphere in front of the light.


Results

Occluder, no motion blur. (9.5 hours of rendering time: ~263 billion photons)
Occluder, motion blur. (3 hours of rendering time: ~65 billion photons) billion photons)
No occluder, no motion blur. (~10 minutes of rendering time: ~3.5 billion photons)
No occluder, motion blur. (2 hours of rendering time: ~45 billion photons)

Discussion

Maybe I screwed something up, but it seems like only one in 128000 photons should hit the sensor from the red sphere. By eyeballing the projected visible area of sphere, I arrive at roughly 192 by 128 pixels. Since I shot 263 billion photons, there should be around 2 million photons hitting the sensor. Putting the numbers together, I get an average of 84 photons per sensor pixel. That's not much at all. Am I doing something completely absurd?


Tone Mapping

I decided to implement the simplest possible tonemapping technique: f(x) = x / (x+1). This is what I get for the unblocked, no motion blur:


Code changes to previous assignment

My previous sphere sampling was generating weird banding artifacts noticeable when the pinhole was very small (<0.01). I imagine this was because I was sampling from grazing angles too much, so when the projected area of the light source on the screen was much bigger than the real area, I would get more incident photons than would be right. Now I generate the direction of the photon on a cosine distribution over the hemisphere. This eliminated the artifacts.


Parallelization

My code now runs in any number of independent threads, each with its own random number generator and data structures, so that there's no locking at all. Each thread writes to its own sensor. Since light transport is linear, the result is simply the sum of the individual sensors.

I also extended this by running a few shell scripts to execute the processes on different machines. This gets me a fair amount of free parallelism. All experiments in this project were done on 20 processors (5 dual dual-core Opterons). I was getting an average of 6.35 million photons a second combined on them. This is pretty pitiful, but hey, I'm not that good of a coder :)


Final Scene

I got fed up that my images didn't look interesting, so I changed the plane that contains a pinhole to be white, and added a back wall right behind the spherical light. I still kept the occluding sphere to prevent direct light to hit the sensor. The result (fifteen hours, or too many photons to mention) is as follows. I can actually make out the blurring due to the pinhole camera now. I'll try to have importance sampling by the end of the day.