After taking a few months away from the forward path tracer, I recently solved my biggest problem, that of flat colouring.
Now it works much better:
Now to add reflections and refractions.
The relevant code is:
float trace_path_forward2(const vec3 eye, const vec3 direction, const float hue, const float eta)
{
const vec3 mask = hsv2rgb(vec3(hue, 1.0, 1.0));
const vec3 light_o = get_random_light_pos(50, eye, direction, hue, eta);
const vec3 light_d = RandomUnitVector(prng_state);
const float energy = 1.0;
int step_count = 0;
vec3 step_locations[max_bounces + 3];
vec3 step_directions[max_bounces + 3];
traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, eye, 0.001, direction, 10000.0, 0);
if(rayPayload.dist == -1)
return 0.0;
const vec3 first_hit_pos = eye + direction * rayPayload.dist;
step_locations[step_count] = light_o;
step_directions[step_count] = light_d;
step_count++;
if(false == is_clear_line_of_sight(first_hit_pos, light_o))
{
vec3 o = light_o;
vec3 d = light_d;
for(int i = 0; i < max_bounces; i++)
{
traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, o, 0.001, d, 10000.0, 0);
if(rayPayload.dist == -1)
return 0.0;
const vec3 hitPos = o + d * rayPayload.dist;
o = hitPos + rayPayload.normal * 0.01;
d = cosWeightedRandomHemisphereDirection(rayPayload.normal, prng_state);
step_locations[step_count] = o;
step_directions[step_count] = d;
step_count++;
if(true == is_clear_line_of_sight(first_hit_pos, step_locations[step_count - 1]))
break;
}
}
step_locations[step_count] = first_hit_pos;
step_directions[step_count] = light_d;
step_count++;
step_locations[step_count] = eye;
step_directions[step_count] = direction;
step_count++;
// Reverse the path
uint start = 0;
uint end = step_count - 1;
while(start < end)
{
vec3 temp = step_locations[start];
step_locations[start] = step_locations[end];
step_locations[end] = temp;
temp = step_directions[start];
step_directions[start] = step_directions[end];
step_directions[end] = temp;
start++;
end--;
}
float ret_colour = 0;
float local_colour = energy;
float total = 0;
for(int i = 0; i < step_count - 1; i++)
{
vec3 step_o = step_locations[i];
vec3 step_d = step_directions[i];
traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, step_o, 0.001, step_d, 10000.0, 0);
local_colour *= (rayPayload.color.r*mask.r + rayPayload.color.g*mask.g + rayPayload.color.b*mask.b);
total += mask.r;
total += mask.g;
total += mask.b;
if(i == step_count - 2 ||
(rayPayload.color.r > 1.0 ||
rayPayload.color.g > 1.0 ||
rayPayload.color.b > 1.0))
{
ret_colour += local_colour;
break;
}
}
return ret_colour / total;
}
Thanks again for all of the help.