I'm at a point where I would like to use lifetimes, but so far I have avoided them and used std::sync::Arc a lot. The code base is pretty large right now, so maybe it's best to discuss things on basis of the current docs.
The C++ counterpart has two base classes where several algorithms can derive from to render the same scene various ways:
class Integrator {
public:
// Integrator Interface
virtual ~Integrator();
virtual void Render(const Scene &scene) = 0;
};
...
class SamplerIntegrator : public Integrator {
public:
...
void Render(const Scene &scene);
...
};
I had problems abstracting the Rust structs and traits the same way so currently I have two render functions (that's where the code is multi-threaded):
In C++ several classes derive from SamplerIntegrator
:
$ rg -tcpp "public SamplerIntegrator" ~/git/github/pbrt-v3/src/
/home/jan/git/github/pbrt-v3/src/integrators/path.h
49:class PathIntegrator : public SamplerIntegrator {
/home/jan/git/github/pbrt-v3/src/integrators/whitted.h
49:class WhittedIntegrator : public SamplerIntegrator {
/home/jan/git/github/pbrt-v3/src/integrators/ao.h
48:class AOIntegrator : public SamplerIntegrator {
/home/jan/git/github/pbrt-v3/src/integrators/directlighting.h
52:class DirectLightingIntegrator : public SamplerIntegrator {
/home/jan/git/github/pbrt-v3/src/integrators/volpath.h
49:class VolPathIntegrator : public SamplerIntegrator {
On the Rust side I have implemented three of them so far, AOIntegrator
, PathIntegrator
, and DirectLightingIntegrator
:
$ rg -trust "impl SamplerIntegrator"
src/integrators/ao.rs
40:impl SamplerIntegrator for AOIntegrator {
src/integrators/path.rs
51:impl SamplerIntegrator for PathIntegrator {
src/integrators/directlighting.rs
161:impl SamplerIntegrator for DirectLightingIntegrator {
They all use the first function render(...)
and the trait methods abstract the algorithms, so the main render loop stays the same for all of them ...
The second function render_bdpt(...)
is the one I'm currently working on (for bidirectional path tracing).
So the first problem is that I didn't manage to use traits for all of the integrators (yet) and that the signature for both functions is more complicated (which means that I do not store pointers to the camera and the sampler in the structs implementing the SamplerIntegrator
trait):
pub fn render(
scene: &Scene,
camera: &Box<Camera + Send + Sync>,
sampler: &mut Box<Sampler + Send + Sync>,
integrator: &mut Box<SamplerIntegrator + Send + Sync>,
num_threads: u8,
) {...}
...
pub fn render_bdpt(
scene: &Scene,
camera: &Box<Camera + Send + Sync>,
sampler: &mut Box<Sampler + Send + Sync>,
integrator: &mut Box<BDPTIntegrator>,
num_threads: u8,
) {...}
But let's ignore that for now. I will post another message with my questions ...