400% Raytracing Speed-Up by Re-Projection (Image Warping)

Started by
11 comments, last by spacerat 9 years, 11 months ago

Intro I have been working a while on this technology and since real-time raytracing is getting faster like with the Brigade Raytracer e.g., I believe this can be an important contribution to this area, as it might bring raytracing one step closer to being usable for video games.

Update : I made the Demo public available here: SVO Image Warping Demo Download

Algorithm: The technology exploits temporal coherence between two consecutive rendered images to speed up ray-casting. The idea is to store the x- y- and z-coordinate for each pixel in the scene in a coordinate-buffer and re-project it into the following screen using the differential view matrix. The resulting image will look as below.
The method then gathers empty 2x2 pixel blocks on the screen and stores them into an indexbuffer for raycasting the holes. Raycasting single pixels too inefficient. Small holes remaining after the hole-filling pass are closed by a simple image filter. To improve the overall quality, the method updates the screen in tiles (8x4) by raycasting an entire tile and overwriting the cache. Doing so, the entire cache is refreshed after 32 frames. Further, a triple buffer system is used. That means two image caches which are copied to alternately and one buffer that is written to. This is done since it often happens that a pixel is overwritten in one frame, but becomes visible already in the next frame. Therefore, before the hole filling starts, the two cache buffers are projected to the main image buffer.
Results: Most of the pixels can be re-used this way as only a fraction of the original needs to be raycated, The speed up is significant and up to 5x the original speed, depending on the scene. The implementation is applied to voxel octree raycasting using open cl, but it can eventhough be used for conventional triangle based raycasting.
Limitations: The method also comes with limitations of course. So the speed up depends on the motion in the scene obviously, and the method is only suitable for primary rays and pixel properties that remain constant over multiple frames, such as static ambient lighting. Further, during fast motions, the silhouettes of geometry close to the camera tends to loose precision and geometry in the background will not move as smooth as if the scene is fully raytraced each time. There, future work might include creating suitable image filters to avoid these effects.
How to overcome the Limitations:
Ideas to solve noisy silhouettes near the camera while fast motion:

1. suppress unwanted pixels with a filter by analyzing the depth values in a small window around each pixel. In experiments it removed some artifacts but not all - also had quite an impact on the performance.

2. (not fully explored yet) Assign a speed value to each pixel and use that to filter out unwanted pixels

3. create a quad-tree-like triangle mesh in screenspace from the raycasted result. the idea is to get a smoother frame-to-frame coherence with less pixel noise for far pixels and let the zbuffer do the job of overlapping pixels. Its sufficient to convert one tile from the raycasted result to a mesh per frame. Problem of this method : The mesh tiles dont fit properly together as they are raycasted at different time steps. Using raycasting to fill in holes was not very simple which is why I stopped exploring this method further
http://www.farpeek.com/papers/IIW/IIW-EG2012.pdf fig 5b

** Untested Ideas **

4. compute silhouettes based on the depth discontinuity and remove pixels crossing them
5. somehow do a reverse trace in screenspace between two frames and test for intersection
6. use splats to rasterize voxels close to the camera so speckles will be covered
You can find the full text here, including paper references.
Clipboard01.png
[media]https:
[/media]
Advertisement

Interesting idea, I also use coherence for accelerating diffuse sound ray tracing and get a 10x improvement by averaging the ray contributions over several frames.

Do you have any ideas for how to improve the visual quality?

Sound raytracing for realistic echoing ? Thats also interesting.

For the quality, the upper image is just in 256 colors, so doesnt look that good.

I just used it for testing. The general method also can be applied to 32 bit colors of course.

When in motion, the reprojection version looks not as smooth as the raycasted version - so more research could be done like re-projecting to a higher resolution frame buffer that is downsampled for the final rendering e.g. Also edges with fast motion will loose some accuracy. There additional research may improve the result too, such as by using image filters.

There's a bit of research on this technique under the name "real-time reverse reprojecion cache". It's even been used in Battlefield 3 (rasterized, not Ray-traced though!)
[edit]i should've read your blog first and seen that you'd mentioned the above name.

[edit2] Here's the BF3 presentation where they use it to improve the quality of their SSAO calculations: http://dice.se/wp-content/uploads/GDC12_Stable_SSAO_In_BF3_With_STF.pdf

Yes, I know that paper. To what I understood, they just re-use the shading. Related is also a EG paper a while ago, which does iterative image warping ( http://www.farpeek.com/papers/IIW/IIW-EG2012.pdf ) However, they seem to need a stereo image pair to compute the following image.

The advantage of the raycasting method is, that it can reuse color and position, and further that raycasting allows to selectively raycast missing pixels, which is impossible with rasterization.

Very neat, though I've found that ideas along these lines break down completely when it comes to the important secondary rays, IE incoherent bounces rays for GI, ambient occlusion, and reflections. Still thanks for this; there are use cases for primary raycasting, EG virtualized geometry. Hope you can find some way clever way to get high quality motion.

Yes, this technology is in general for speeding up primary rays. For secondary rays it depends - for static light sources, you can store the shadow information along with the pixel, then you can re-use it in the following frame as well.

If its a reflection or refraction, then you could do a quick neighbor search in the previous frame if its possible to reuse anything - but most probably this technology wont suit well for that case.

From your brief description this sounds very much like the temporal antialiasing techniques that are commonly used with rasterization. For reprojecting camera movement you really only need depth per pixel, since that's enough to reconstruct position with high precision. However it's better if you store per-pixel velocity so that you can handle object movement as well (although keep in mind you need to store multiple layers if you want to handle transparency). Another major issue that you have when doing this for antialiasing is that often your reprojection will fail for various reasons. The pixel you're looking for may have been "covered up" the last frame, or the camera may have cut to a comepletely different scene, or there might be something rendered that you didn't track in your position/depth/velocity buffer. Those cases require careful filtering that will exclude non-relevant samples, which generally means taking drop in quality for those pixels for at least that one frame. In your case I would imagine that you have to do the same thing, since spiking to 5x the render time for even a single frame would be very bad.

Yes, its related to temporal antialiasing techniques. However there, the geometry is not reused and needs to be rendered again. For the coordinates I also tried different ways but it turned out that using relative coordinates (such as the zbuffer) tend to accumulate the error over multiple frames, and the image is not consistent anymore then.

Transparency is not yet handled and might need special treatment indeed. Its just for opaque surfaces.

To still cache the pixels efficiently even lots of them get covered-up / overwritten, I am using a multi buffer cache. That means the result of a screen is alternately stored in either cache, while both caches are projected to the screen at the beginning before filling the holes by raycasting. That can keep the pixels efficiently, as pixels that are covered up in one frame might already be visible again in the next frame. In general the caching works well. Also its a relaxed caching theme, where not every empty pixel get filled by a ray. The method uses an image filter for filling small holes and only fills holes that are 2x2 pixels large (the threshold can be defined) by raycasting.

If the camera changes to a different view, then obviously the cache cannot be used and the first frame will render slower.

Nice, sounds cool!

This topic is closed to new replies.

Advertisement