TL;DR -- who has discovered, in the past, a backward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.
Edit: Seems like James Kajiya is likely the person who discovered this algorithm first.
The post:
I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.
Here the caustics form a rainbow-like pattern because of chromatic aberration. Fog has been implemented in the 5th figure.
The full source is at: https://github.com/sjhalayka/cornell_box_textured
In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen
The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.
So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known backward-only caustics algorithms?
Thanks for your time and expertise.
The relevant code is:
vec3 hitPos = o + d * rayPayload.distance;
// If partially transparent
if(rayPayload.opacity != 1.0)
{
// Incoming ray
if(dot(d, rayPayload.normal) <= 0.0)
{
o = hitPos.xyz - rayPayload.normal * 0.01;
d = refract(d, rayPayload.normal, eta);
}
else // Outgoing ray
{
vec3 temp_dir = refract(d, -rayPayload.normal, 1.0/eta);
if(temp_dir != vec3(0.0))
{
o = hitPos.xyz + rayPayload.normal * 0.01;
d = temp_dir;
}
else
{
// Total internal reflection
o = hitPos.xyz - rayPayload.normal * 0.01;
d = reflect(d, -rayPayload.normal);
}
}
}
else // Fully opaque
{
o = hitPos + rayPayload.normal*0.01;
vec3 d_cos = cos_weighted(rayPayload.normal, prng_state);
d = mix(d_cos, reflect(d, rayPayload.normal), rayPayload.reflector);
}