Welcome to Fractal Forums

Fractal Software => Programming => Topic started by: khyperia on June 02, 2012, 07:00:44 PM




Title: Cheap ambient occlusion approximation
Post by: khyperia on June 02, 2012, 07:00:44 PM
I didn't know if to post this in New Theories and Research, or here, but I decided here.
This has probably been invented before, but I thought of it on my own, and better told and already known about then not told and not known about.

Goal of algorithm: Very cheap ambient occlusion (actually, I don't know if that's the right term), which means at least less than 10 distance estimator calls. This rules out shooting another ray, let alone the multitudes required for the method described at http://en.wikipedia.org/wiki/Ambient_occlusion (http://en.wikipedia.org/wiki/Ambient_occlusion).
The purpose is to decrease render time at the cost of shading accuracy. This is not a replacement for true ambient occlusion or global illumination, just a cheap approximation.

The roots of the idea are in http://www.iquilezles.org/www/material/nvscene2008/rwwtt.pdf (http://www.iquilezles.org/www/material/nvscene2008/rwwtt.pdf) that slideshow, near the bottom, under the title "Rendering with distance fields :: Ambient Occlusion" (ctrl-f it). The algorithm is as follows:
Start at a point 'p' that is almost exactly distance 'distance' away from the fractal (all pixels in a region should be the same distance away), and a normal 'dir' that represents the normalized normal at that point. Being exactly 'distance' away and having an accurate normal are critical to this method.
Then start a ray 'shot' starting from 'p' and going in the direction of the normal. Iterate only a few steps, 5 works well. Higher numbers mean everything is more shaded and more affected by distant objects. Once done, take the distance you could have gone if you were on a perfectly flat plane going straight up- which happens to be (initialDistance * pow(2, stepCount - 1)) if stepCount is the number of steps you took (it should be a constant). Divide total distance actually traveled by this "could have gone" distance, and you have your shading value.
The result is a average quality ambient occlusion test that only takes 3-7 distance estimator calls, depending on how shaded you want it to be.

Why it works: If the surroundings of a point you are testing is wide open, then the ray will go the same distance as if it were in a open plane, resulting in a shade value of 1. However, if there is a wall right in front of it, it will obviously not go as far, resulting in a shade value less than 1.

Some optimized hlsl code-

Code:
float OcclusionTest(float3 p, float3 dir, float delta) // delta is another name for 'distance'
{
float totalDistance = delta; // initialize totalDistance to delta, for we know that it is delta away from the fractal
for (int i = 0; i < AoStepcount; i++) // AoStepcount is about 5 for me
totalDistance += DE(p + dir * totalDistance); // standard simplified raytracing
return totalDistance / (delta * pow(2, AoStepcount)); // modified from formula in proposal, because we initialized totalDistance to delta and not zero
}

Attached is an image where only this method was used to color the Mandelbox.


Title: Re: Cheap ambient occlusion approximation
Post by: eiffie on June 02, 2012, 07:49:23 PM
Thanks for sharing your ideas! This is another good one very similar to rrrola's code (taken from boxplorer)
// Ambient occlusion approximation.
float ambient_occlusion(vec3 p, vec3 n) {//here p is the ray and n the normal
  float ao = 1.0, w = ao_strength/ao_eps;
  float dist = 2.0 * ao_eps;

  for (int i=0; i<5; i++) {
    float D = d(p + n*dist);
    ao -= (dist-D) * w;
    w *= 0.5;
    dist = dist*2.0 - ao_eps;  // 2,3,5,9,17
  }
  return clamp(ao, 0.0, 1.0);
}

It also steps away from the normal for a few steps. Probably this also came from IQ's idea originally??

OK just re-read the paper - credit to Alex Evans for this idea.


Title: Re: Cheap ambient occlusion approximation
Post by: Syntopia on June 03, 2012, 01:16:03 AM
Yes, the IQ/Evans method is the most common way to do AO when sphere tracing (that, and screen space AO). I also use this method, I just sample at fixed offsets along the normal (like rrrola).

Notice, that there is a similar trick for soft shadows: http://www.iquilezles.org/www/articles/rmshadows/rmshadows.htm


Title: Re: Cheap ambient occlusion approximation
Post by: khyperia on June 03, 2012, 01:59:20 AM
Yes, the IQ/Evans method is the most common way to do AO when sphere tracing (that, and screen space AO). I also use this method, I just sample at fixed offsets along the normal (like rrrola).

Notice, that there is a similar trick for soft shadows: http://www.iquilezles.org/www/articles/rmshadows/rmshadows.htm
Did a double take there, my real name is Evan, :tongue1:
I've actually seen that article before, and if I'm not mistaken, it requires another entire ray shot, which is quite a lot if you're going for speed.

Oh, and I don't like SSAO because it requires reading the pixel values of neighboring rays- This introduces the problem of a 100x100 image being different from a 1000x1000 image, because relative distance from one pixel to the next is different. Then again, I really want to do DOF, so I guess I'll have to break that self-rule.