Metropolis Light Transport

Hi all,

I have rewritten my renderer from scratch because the old code was too ugly to add anything useful on top of it . The new design is mainly based on pbrt , I’m also being inspired by other open source ray tracers like Picogen and LuxRender .

It now uses a sah based kd tree with a building  complexity of O (nlog(n)^2) to make the geometry intersection tests faster , I also made it multithreaded thanks to the simplicity of openmp.

Unfortunately even with these improvements my ray tracer struggles in scenes with strong indirect illumination , so I added metropolis light transport as proposed by Kelemen et a.l. , the result is impressive despite the fact that my implementation is unstable :

And another render showing the glossy dielectric material ( image rendered with path tracing + explicit direct light connection )

Some new renders

I haven’t  made much progress  on my investigation of BDPT and this is  because of a lot of factors including the university , the pressure from the real world ,  lazyness…  But I managed to implement a better scene parser and a blender scene-export script .Here’s a couple of test renders i did during the last two months  (all of these images are rendered with path tracing except the first two)  , i hope you like them :)

Bidirectional Path Tracing part 2

After 4 months of hard working, finally my bidirectional path tracer is starting to take shape.My big error is that  i’m weighting my paths all wrong ,so specular surfaces appear a little bit darker and sometimes even brighter.

There is still a lot of improvement to be made,for example i can use a better heuristic to combine the paths (Balance heuristic,power heuristic…) ,but for now i’m going to stick with my current implementation and probabily move to another topic ,may be acceleration structures or BRDFs or even Fractal Flames…I don’t know

Bidirectional Path Tracing

Hi,

I didn’t posted since a while and i thought may be i should write something about my progress…

My current project is a Monte Carlo bidirectional path tracer aiming to be robust and fast  as much as it can be.One of its main  goals is to familiarize myself with Monte Carlo Methods and how we can apply various variance reduction  techniques to better solve the rendering equation.Obviously,the first step that i did is to implement the Light Tracing Algorithm which is very good at handling paths of the type L***DE,the second step is to find a way to combine a Light Path with an Eye Path and this is where all my nightmares began.To do so , I have two options:

-A uniform weighting scheme which treats all the paths as if they are “equal” .A major drawback of this technique is that the estimand can  have high variance and as a consequence all of the advantages of the light tracing step will be buried under the ground.

-With variable weights (as described in [1]) ,it weights  the paths based on their importance (i.e. important paths have weights closer to 1 and vice versa).

My implementation only supports uniform weighting scheme to combine the two paths ,and as it can be seen below in the images ,a naive BDPT can perform slightly better than a PT  for diffuse  scenes.

And here is another image which compares Light Tracing (left) to Path Tracing (right):

[1] Optimally Combining Sampling Techniques for Monte Carlo Rendering, Eric Veach Leonidas J. Guibas

Depth of field+some simple fractals

I have been working slowly these days probably due to the hot temperature in Tunisia,anyway i have just implemented DOF and i thought  that i can share my progress,nothing out of the extraordinary, it’s just a simple scene but I’m willing to expand the ray tracer by adding an xml-parser probably, but nothing is for sure…

I think depth of field is not well explained in most of cg papers that’s why I’ll shortly describe the algorithm to calculate it:

  • First ,we need to specify how farther our focal plane is from the camera origin (this is called the focal distance)
  • Second ,we calculate our ray direction as we normally do
  • Third,we calculate our point in focus for that given pixel (point=ray.origin+ray.direction*focal_distance)
  • Fourth,we calculate a random point on the lens and displace the ray origin by the coordinates of this point
  • Finally ,the new ray direction is ( point-ray.origin).normalize()

Sorry for the excessive use of the word “calculate” :D

Here’s my results:

Cornell Box+DOFOutdoor+DOF

Thanks to lyc ,I’m now interested in fractals ,I wrote a program to render the Mandelbrot set and the Julia set ,it’s  quite an easy task ,what impress me though is that how such simple formulas (Zn+1=Zn*Zn+C where Zn+1,Zn and C are complex numbers) can generate very beautiful shapes.

The first image represents the Mandelbrot set, the second and the third ones are the Julia set with different values of C.

Mandelbrot set

Julia set 1Julia set 2

Preetham’s skylight model

Hi folks,

I’ve been experimenting  lately with the Preetham’s daylight model,i only implemented the skylight part ,at first it sounds really complicated ,a lot of formulas and numbers plus the color conversion (from xyY to XYZ to RGB) .But in the end , it is really not that complicated and it gives a good sense of realism to the scene ,even though i struggled to implement it correctly.Below are two images representing the sky at sunset and at daytime.

Sunset

DayLight

As you can notice , I’ve added a procedural texture (checkerboard) which is quite simple to implement.Here’s my code to generate such a texture.

Color3f getColor(HitRecord *record)
{
float s=2.0;//the size of the square
int x=(int)floor(record->pHit.x/s);
int y=(int)floor(record->pHit.y/s);
int z=(int)floor(record->pHit.z/s);
if ((x+y+z)%2==0)
return m_c1;//the white color
else
return m_c2;//black color
}

This paper “Day light sky color”  helped me a lot to implement the Preetham’s skylight model , basically it provides all the necessary data to go from xyY to RGB color space plus the basic steps to get the sky color, so it’s a good read.

Explicit Direct Lighting added

I’ve been playing with my ray tracer this morning , fixed a lot of bugs and optimized the bvh a little then I thought may be I  should add explicit direct lighting because quite frankly naive path tracing is so sloooowww especially with an old computer like  mine(p4 ht 3ghz).The result is pretty amazing, now I can render everything i want in a decent time.

To see the difference , here’s a scene (138 902 traingles) rendered with naive path tracing (1 samples/pixel)  in 15 seconds (some little details are lost due to jpg compression):

Bunnies naive path tracing

and here’s the same scene after adding explicit direct lighting:

Bunnies+Explicit Direct Lighting

Finally my BVH is working!

First thing first , I would like to say Bravo for everyone who has implemented a bvh  so Bravo Ray Tracing  guys :) ,its so easy to think about it but when it comes to coding you get two confused  especially for the first time, for me it was like I’m comitting a suicide (may be this is because I’m too newbie :D )but after so many tries I succeded , well not 100% , it still some issues left (memory leak,messy code…)but afterall it works pretty fine and as a matter of fact I was amazed by the speed gain.No more blablabla , here is some benchmarking (rendered with my naive ray tracer):

Dragon (203 000 triangles):

Image resolution:1000*1000,number of sample for AA: 10 (random sampling),render time:38 minutes

Dragon Stanford

Suzanne (4000 triangles):

Image resolution:500*500,number of sample for AA: 10 (random sampling),render time:1min30s

Suzanne 10spp

Bunny(16000 triangles):

Image resolution:500*500,number of sample for AA: 10 (random sampling),render time:2 minutes

BVH test1 1m30s 16k

the same scene but it is path traced with 1000spp (render time:2hours)

Cornell-box bunny bvh test 1000spp 2h

Ajax Bust

Need for Speed

I’ve been working on my path tracer since a month ,I actually finish it recently now it can produce some good images but what remains now is SPEED ,so to check whether  everything is working or not I rendered a scene containing suzanne ,a plane and sphere (the light):

Naive Path Tracing Suzanne

The render time is really shocking for a such a simple scene (approximately 11h35min using 1000spp).This is actually made me think seriously about acceleration structures for ray  tracing .

Next thing to implement  is Bounding Volume Hierarchies :) .

By the way here’s some more images rendered by my ray tracer:

Naive Path Tracing My Gorgeous balls 100sppNaive Path Tracing Light made me alive 1000sppNaive Path Tracing Cornell Spheres 1000spp

Naive Path Tracing Touching Spheres 1000spp

Why my path tracer is messing up my pixels ?

It was a hard night for me yesterday ,I was coding like maniac, searching for the reasons that made my path tracer render looks so ugly!I did fixed a bug related to the luminaries(objects below a luminaire ,like the ceiling, receives much light when they are supposed to be in shadow (thanks to neos for pointing this out))…

But now , I had a much more serious problem , It is how to pick a random direction on the unit hemisphere centered at the normal of the intersected point.At first ,I didn’t bother at searching for a good approach ,I just used the classic method which is :

-Pick two random number between 0 and 1 (say n1 and n2)

-theta=2*PI*n1

-phi=0.5*PI*n2

And then the random direction is :

x=cos(theta)*sin(phi)

y=sin(theta)*sin(phi)

z=cos(phi)

But this method turns out to be not efficient as I thought , a “strange” shadow in the back of the sphere has appeared , take a look:

Cornel-Box Path Tracing 9 samples

So I looked over the internet to find another method for hemispherical sampling and I end up with this one:

pick two random numbers (e1 ,e2) the spherical angles (theta and phi) are then given by :

theta=2.0*PI*e1,phi=arccos(sq rt(e2)).

The shadow thing is somehow fixed but another bug has appeared , check it out:

Cornel-Box Path Tracing 9 samples test 6

I know that it is less probably that someone is visiting my blog right now but if you passed by and have a solution , please let me know!

Thanks

Edit:

After some searching , I found out that my problem was that I’m not actually constructing a coordinate system such as the unit hemisphere is centered around the normal at the intersected point so the good way is to sample the hemisphere using a pdf  then creating the random direction by multiplying each component of the random direction (on the unit hemisphere) by the axis u,v,w respectively with w  set to be the normal at the intersected point (must be normalized) , u=CrossProduct(t,w)/length(CrossProduct(t,w)) , t is a vector equal to w except that the smallest absolute value component of t  (x,y or z) is set to 1 and finally v=CrossProduct(w,u).

Now the  Cornell Box looks much more better:

Cornel-Box Path Tracing 9 samples test 7 100spp-28m

Thanks for reading!

Follow

Get every new post delivered to your Inbox.