So I just completed a naive path tracer that uses explicit direct light sampling. Problem is the path tracer isn't converging. It's like a raytracer, showing a single image on each pass. More info on how am I doing this is provided below. I am using OpenCL 1.1.
__kernel void render(__write_only image2d_t outputImage, __read_only image2d_t inputImage, int reset)
{
float total_color; // initalized to black
for(int i = 0; i < samples_x; i++)
{
for(int j = 0; j < samples_y; j++)
{
float4 direct_color, indirect_color; initialized black.
Shoot ray through pixel.
HitInfo new_info, old_info;
If( !intersects(ray, old_info) )
{
total_color += Background_color
continue;
}
else
{
direct_color = computeDirectLighting(old_info);
float4 color_arr[BOUNCES];
float cosine_falloff[BOUNCES];
for(int i = 0; i < BOUNCES; i++)
{
new_ray = sampleHemisphere();
if( !intersects(new_ray, new_info) )
{
color_arr[i] = sky_color;
cosine_falloff[i] = max(dot(old_info.normal, new_ray.dir), 0.0f);
break;
}
else if ( intersects light source)
{
i--;
continue;
(Sample again)
}
color_arr[i] = computeDirectLighting(new_info);
cosine_falloff[i] = max(dot(old_info.normal, new_ray.dir), 0.0f);
old_info = new_info;
}
for(i = color_arr.length() - 1; i >= 0; i--)
{
indirect_color += color_arr[i];
indirect_color *= cosine_falloff[i];
}
}
total_color += direct_color + indirect_color;
}
}
}
color /= (samples_x * samples_y);
if ( reset == 1 )
{
write_imagef(outputImage, pixel, color);
}
else
{
float4 prev_color = read_imagef(outputImage, sampler, pixel);
color += prev_color;
color /= 2.0f;
write_imagef(outputImage, pixel, color);
}
}
So this is the main outline. When the kernel runs the first time, reset = 1
. Thus it writes the color directly into the output image. At each iteration, the buffers of outputImage
and inputImage
get swapped. After iteration 1, reset = 0
.
This means at iteration 2, the kernel reads from the image it wrote to, in iteration 1. It then averages the new color and the previous color.
I thought taking 64 samples 2 times, and averaging them would be analogous to taking 128 samples once. If this is true then my image should converge, but it isn't. It shows only this image constantly.
EDIT:-
I think I should clear how I am calculating GI. After the first intersection. I send 1 ray directly to the light source (explicit direct light sampling). Then uniformly sample the hemisphere w.r.t area, and send another ray in this sampled direction. If the new ray hits light source, we sample again. This goes on bounces times
. Each bounce the program stores the direct color due to explicit direct light sampling at each hit point. The indirect color is the sum of all these direct colors. Added a simple algo of what I did to the code snippet.
The cosine_falloff
array holds all the weakening factors that should be multiplied to the respective indirect colors brought by secondary GI rays.