-1

what I am trying to do is improving my actual Ray Tracer to create a Distributed Ray Tracer. I have been wandering on internet and all I could found about its implementation was just short stuff like:

-Replace single ray with distribution of rays -Shoot multiple rays distributed over an interval -Shoot multiple rays through each pixel and vary each ray randomly

My question is: What does a "distribution" mean? How can I vary a distribution of rays that go through a pixel? In my normal Ray Tracer I shoot one ray per pixel. For "distribution" of rays I can understand that I should shoot multiple rays instead of only one. But at the same time I shoot the ray through my pixel with coordinates (x,y).

for (int x = 0; x < WINDOW_WIDTH; x++)
{
    for (int y = 0; y < WINDOW_HEIGHT; y++)
    {
        Vec3<float> rayDir = camera->pixelToWorld(x, y) - camera->position;
    }
}

So, how can I "vary each ray randomly" ? Thanks.

Olivier Moindrot
  • 27,908
  • 11
  • 92
  • 91
Tarta
  • 1,729
  • 1
  • 29
  • 63
  • The way I did it (admittedly a long time ago) was to divide the output-pixmap's rows up into N roughly equal-sized sections and hand out each sub-section to one of the N render-workers. That's good enough to start; then once that's working the problem is that some workers will finish faster than others; in that case a worker who has finished can contact a worker who has not finished yet and offer to help him; the still-working worker can then hand (half of the rows he still has yet to finish) over to the requesting worker. Repeat until all rows are rendered, and then reassemble the image. – Jeremy Friesner Jul 16 '15 at 05:19

2 Answers2

1

There are several usages of distributed ray tracing, it can be used for:

(1) antialiasing

(2) depth of field effects

(3) motion blur effects

For (1), the idea is simply to launch in each pixel a bunch of rays instead of a single ray. Each ray will be thrown through the center of the pixel jittered a little bit by random dx and dy (dx and dy will be smaller than the size of the pixel).

For (2), it is slightly more complicated, but it is roughly the same idea: each ray is shot as a line that starts from the observer and that goes through the center of a pixel (possibly jittered if you do (1), but let us now forget about it for now). This time, this is the observer position that you are jittering, you will jitter the position of the observer a little bit in the direction orthogonal to the screen. Again, by averaging the contribution of a number of rays in each pixel, the background will be more "blurred" than the foreground, because the ray will deviate more in the background.

For (3), it is just the same idea, but this time this is the position of the moving objects that are jittered.

Note: there is also (4): complex materials with glossy effects (they require to understand a little bit of material, notion of BRDF = Bidirectional Reflection Distribution Function).

BrunoLevy
  • 2,495
  • 17
  • 30
  • Ok perfect! This gives me already a more clear idea of what I have to do. A couple of questions more if possible: 1) how do I find the size of a pixel? For example my image has a size of 512x512. If I need to jitter a little bit as you said I need the size of my pixel. 2) what's a "good" number of rays that can be shot into the pixel? Just to have an idea. In my mind it can be both 4 or 100 for example.. so.. just to have an idea of what "usually" gives already a good result. Thanks! – Tarta Jul 16 '15 at 12:36
  • 1) If your specify your viewpoint as in: http://www.povray.org/documentation/view/3.7.0/246/, then you got a point (location) and three vectors (lookat, right and up). If location is at the orign, then the image plane is at a distance of tangent(angle) from the orign along the lookat direction, this gives the formula to map a pixel of coordinate (X,Y) into 3D: – BrunoLevy Jul 16 '15 at 12:57
  • (x,y,z) = orign + tangent(angle) * lookat + (X / width - 0.5 + jitterX) * right + (Y / height - 0.5 + jitterY) * up, where jitterX and jitterY are random floating point numbers between 0 and 1. – BrunoLevy Jul 16 '15 at 13:04
  • 2) typically 10 to 100 (but running time will be proportional to that, clearly), use trial and error to tune. – BrunoLevy Jul 16 '15 at 13:05
  • That's clear now! Thanks a lot! – Tarta Jul 16 '15 at 13:38
  • Sorry.. one more thing: the jitter values have to be within the range [-0.5 , 0.5] since with the formula you gave me we aim to the center of the pixel, right? – Tarta Jul 16 '15 at 15:10
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/83511/discussion-between-brunolevy-and-tarta). – BrunoLevy Jul 17 '15 at 07:36
0

There are a lot of different ways to do this and it is somewhat dependent on what you have working in your current ray tracer implementation.

My approach would be to break the problem down into a job-based model. In other words, you create a queue of jobs to be processed by each of your workers, where a worker could be a thread or a separate machine.

All worker nodes are equal, meaning that there is no difference in the types of jobs they can do. This allows you to add as many worker nodes as you want (NOTE: there will be a limit to how many you can add before you start getting negative returns).

Another benefit to this is that you can scale according to your available resources-- maybe for testing you just use a few threads on your local machine, but when you're ready to make "production" images you may want to utilize additional machines. Also, rendering with a single worker thread should work in this setup.

Each worker node is going to need access to the scene, so that's the first chunk of data to send over. Then they just start pulling from the job queue. It is important to note that you need to do this in a safe manner -- only one worker should be allowed to claim a job.

while(active)
{
    fetch next job from job queue
    if no job is available
    {
       sleep(1)
       continue
    }

    process job
}

Something you need to decide is what a "job" entails. Is is a single ray? Is is a single ray and all its subsequent bounces? Is it a batch of rays? This load balancing decision is going to be dependent on your ray tracer. A single ray probably isn't enough work, but it's a good starting point. In fact, you probably should start with just having a single ray per pixel and make one job per ray. This will give you a good baseline to start from once you have it working.

Good luck!