# Depth of Field

The 3D webs in the previous post are represented as graphs. Rendering them in 3D presents a few challenges. Depending on what tools you use, you might be able to convert them into meshes. There are several other ways to do it as well.

The following is the outline of the method used to render the webs, as well as the images you see here, that does not involve building meshes. It should work for a wide range of graph structures, and probably other things as well.

Assuming you have:

• A line in 3D, `l=[a, b]`;
• a camera at position, `c`;
• a focus distance from camera, `f`
• a distance function, `dst(a, b)` that yields the distance between `a` and `b`;
• a function, `lerp(a, b, s) = a + s*(b-a)`, which interpolates between `a` and `b`;
• a function, `rnd()`, that yields random numbers between `0` and `1`; and
• a function, `rndSphere(r)`, that returns random points inside a sphere with radius, `r`.

With the previous definitions in mind, you can draw all the lines, `l`, in your graph structure using the following method:

• Select a point, `v = lerp(a, b, rnd())`, on `l`.
• Calculate the distance, `d = dst(v, c)`.
• Find the sample radius, `r = m * pow(abs(f - d), e)`.
• find the new position, `w = v + rndSphere(r)`.
• Project `w` into 2D, and draw a pixel/dot.
• Sample a fixed number of times, or according to the length of `l`. Use a low alpha value, and a high number of samples for a smooth result.

Here `m` is a parameter that adjusts the size of the depth of field sphere (the "Circle of Confusion"), and `e` adjusts the distribution of the samples inside the sampling sphere. Start by setting both to numbers close to `1`, then adjust them and see what happens.

If you try this you will probably notice that there are a lot of other things to tweak as well. At least this should get you started.

One thing to keep in mind is that this method doesn't really require you to work in 3D space. The sampling might as well happen in 2D, and the sampling radius, `r`, described above, could be any number different functions.

Read the next post to see how to add a colour shift effect as well.

1. An extension of the method described in this earlier post.
2. I use the word "render" in a rather lose sense here. I have by no means built a 3D pipeline. Just a few tools that can do 3D to 2D projection, and that (rather inefficiently) draw raster images.
3. All of this assumes world coordinates. How that affects you depends on how you project your 3D points into 2D. Moreover, since my projection function uses orthographic projection, the distance function does not calculate the distance from `p` to `c`. Instead it calculates the distance from `p` to the point where `p` hits the camera plane.