4
$\begingroup$

Start with a precalculated "ray cloud" - the starting point and direction of a large number of rays, most of which will not contribute to the image. The image plane's position and orientation are then specified, and the task is to search the ray cloud for rays that intersect the image plane without occlusion by other objects, and output the resulting pixel values. No ray reflections would be required, as all of the work has already been done in generating the ray cloud. The only step left is to convert the rays to an image. This means that a single ray cloud can be used to generate images from arbitrary view angles.

How could I go about accelerating this process using a GPU? The decision for each ray of whether it intersects the image plane is parallelisable as these decisions are independent, but each requires access to the objects in the scene as some rays will reach some potential image planes but not others. The final step of sampling the relevant rays across the pixels of the image requires each ray to contribute to a number of the surrounding pixels. Is this also parallelisable using a GPU?


To clarify, RichieSams' understanding is correct:

  • Start with a set of rays pointing in arbitrary directions.
  • Find which of these rays intersect with the image plane, taking into account occlusion.
  • Calculate the colour of each pixel based on the rays that hit the image plane.

Ideally I would like to be able to accelerate this process sufficiently to move around a scene in real time, given a precomputed ray cloud over the whole scene.

$\endgroup$
  • 1
    $\begingroup$ I'm going to give you a straightforward answer: GPU are turing complete. what do you conclude from this ? second answer: lux render luxrender.net/wiki/SLG $\endgroup$ – v.oddou Dec 14 '15 at 5:13
  • 1
    $\begingroup$ The best way to do this is probably using atomic operations for the scattered accumulation operations (when multiple rays may hit the same point), but you could render your entire "ray cloud" as points and do the intersection and occlusion calculations in a vertex shader, use a passthrough pixel shader and let the HW blender do the accumulation. $\endgroup$ – Daniel M Gessel Feb 15 '16 at 13:55
3
$\begingroup$

I'm not quite sure I fully understand the problem, this is what I think you're asking:

  • You start with a set of rays pointing a all sorts of directions
  • You want to know which of these rays intersect with the image plane, taking into account occlusion.
  • I'm going to assume these rays carry some kind of color information along with them. IE. when they hit the image plane, they will accumulate color.


With that goal in mind, I would do the following:

  1. Create 2 image buffers
    1. For accumulated color
    2. To keep track of the number of hits
  2. Clear the accumulation buffer to black, and the hitCount buffer to all zeros
  3. Create a kernel per ray
    1. Use classic ray tracing math to find the nearest intersection
      • Here you can do anything from a simple 'iterate through all the object in the scene' to something like BVHs, or kd-trees.
    2. If the closest intersection is the image plane, use the WorldView matrix for the image plane to transform the intersection point from world coordinates to view space coordinates.
    3. Use the x, y coordinates of the image space intersection point to get the pixel coordinates of the image buffer
    4. Add the color of the ray to the corresponding pixel in the accumulation buffer
    5. Increment the value of the corresponding pixel in the hitCount buffer
      • For 4 and 5 you could also use a filter in order to apply the color to multiple pixels, rather than just one. In that case, you would add a value less than 1 to the hitCount buffer
  4. On the CPU, or in another pass per pixel:
    1. Divide the accumulated color buffer by the hitCount buffer


I don't see any problem with doing these steps on the GPU. Any of the compute languages should handle it fine. You might get some divergence in the actual ray tracing code, but it should be ok. The biggest potential problem is that you have to store the entire scene in VRAM.

$\endgroup$
2
$\begingroup$

It sounds like the tricky part is that last step where each ray affects neighboring pixels. I would consider an approach where you do the first steps as normal (parallelized as on the CPU) without the last step, and then you do that last bit in a new pass. I'm not sure exactly how your ray contributions work so it's tough to say, but it seems like you should be able to use the results from the first part as input and then do your operation in a second pass.

Blur is done in a similar manner. The blur is done in one dimension, and then the output of that pass is used as the input of the second pass to blur the other dimension. The result is that the value of some pixel ends up contributing to neighboring pixels, so it's similar to your problem.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.