Edit: I've pinpointed the problem. If I change:
local_colour *= (rayPayload.color.r*mask.r + rayPayload.color.g*mask.g + rayPayload.color.b*mask.b);
into
local_colour += (rayPayload.color.r*mask.r + rayPayload.color.g*mask.g + rayPayload.color.b*mask.b);
... then I get caustics, but not vibrant colour. Any path tracing experts care to enlighten me as to what I'm doing wrong? :)
The problem:
My code to do path tracing is:
float trace_path2(out vec3 final_pos, const int steps, const vec3 origin, const vec3 direction, const float hue, float eta)
{
const RayPayload r = rayPayload;
vec3 hitPos = vec3(0.0);
float ret_colour = 0;
vec3 o = origin;
vec3 d = direction;
int count = 0;
float energy = 100.0;
float local_colour = energy;
float total = 0;
for(int i = 0; i < steps; i++)
{
const float tmin = 0.001;
const float tmax = 10000.0;
traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, o.xyz, tmin, d.xyz, tmax, 0);
const vec3 mask = hsv2rgb(vec3(hue, 1.0, 1.0));
total += mask.r;
total += mask.g;
total += mask.b;
local_colour *= (rayPayload.color.r*mask.r + rayPayload.color.g*mask.g + rayPayload.color.b*mask.b);
if(rayPayload.distance == -1)
break;
hitPos = o + d * rayPayload.distance;
if(rayPayload.color.r == 1.0 && rayPayload.color.g == 1.0 && rayPayload.color.b == 1.0)
ret_colour += local_colour;
vec3 o_reflect = hitPos + rayPayload.normal * 0.01;
vec3 d_reflect = reflect(d, rayPayload.normal);
vec3 temp_o = o_reflect;
vec3 temp_d = d_reflect;
if(rayPayload.reflector < 1.0) // if less than fully reflective, do scattering
{
vec3 o_scatter = hitPos + rayPayload.normal * 0.01;
vec3 d_scatter = cosWeightedRandomHemisphereDirection(rayPayload.normal, prng_state);
temp_o = mix(temp_o, o_scatter, 1.0 - rayPayload.reflector);
temp_d = mix(temp_d, d_scatter, 1.0 - rayPayload.reflector);
}
return rayPayload.opacity;
if(rayPayload.opacity < 1.0) // if partially transparent, do refraction
{
vec3 o_transparent = vec3(0.0);
vec3 d_transparent = vec3(0.0);
// Incoming
if(dot(d, rayPayload.normal) <= 0.0)
{
o_transparent = hitPos.xyz - rayPayload.normal * 0.01f;
d_transparent = refract(d, rayPayload.normal, eta);
}
else // Outgoing
{
vec3 temp_dir = refract(d, -rayPayload.normal, 1.0 / eta);
if(temp_dir != vec3(0.0))
{
o_transparent = hitPos.xyz + rayPayload.normal * 0.01f;
d_transparent = temp_dir;
}
else
{
// total internal reflection
o_transparent = hitPos.xyz - rayPayload.normal * 0.01f;
d_transparent = reflect(d, -rayPayload.normal);
}
}
temp_o = mix(temp_o, o_transparent, 1.0 - rayPayload.opacity);
temp_d = mix(temp_d, d_transparent, 1.0 - rayPayload.opacity);
}
o = temp_o;
d = normalize(temp_d);
}
final_pos = hitPos;
rayPayload = r;
return ret_colour / total;
}
When I make the statement return rayPayload.opacity;
it returns the following image, which is what I expect:
However, if you comment out that return statement, the if statement on the next line is never run, even though it's obviously not 1.0 in some parts of the image. It's the strangest problem.
The full code is at: https://github.com/sjhalayka/cornell_box_textured
Basically, I have reflection caustics working, but I cannot get refraction caustics to work yet (in the new version 2.0 of my path tracer).
Any big errors that I'm not seeing here?
Thanks for your time.
debugPrintfEXT
(see LunarG paper about it). You have to be careful to limit the output - I print only when pressing a key and only for the center pixel. This limits the output to something I can actually read through and analyze. Also, depending on the bug checkout NVidia NSight. $\endgroup$