How to snap a camera focus (DOF) to a moving object

Ever needed to render DOF with a focal point on an animated object? Can be a tricky bussiness if you try to do it by hand. Here is an easy way to make it happen automatically.

I will show two methods, one really simple with some caveats, and another one which is a bit more complex to setup but works more accurately.

The simple method

First, let’s prepare some simple scene to test things out. Mine looks like this:

A few spheres, a camera and a null that serves as a focal point. This can as well be any object or a point in space.

Now select a camera and type a following expression into a Focus Distance parameter field:

vlength(vtorigin(".", "../cam_focus")) 

This will compute a distance between the camera and an object called cam_focus. And that’s basically it for the first method.

Real simple solution, but the major caveat here is if you move the focal point up or down, or sideways, it also adds to the computed distance (as you can see at the following gif) – that is obviously not how it works in reality. So this method is only good as far as the focal point is more less in the center of the camera view.

The accurate method

The second method works more like real camera where DOF is only affected by the depth along the viewing direction.

For this scenario I’ve got a similar test scene setup, only this time the focus is onto an animated object rather than manually controlled null.

Start by diving into a camera object where you should see 3 nodes: file SOP, transform SOP and add SOP.

Inside camera object, merge in the object you want to focus onto. Plug it into an Attribute VOP.

The important stuff happens inside the Attribute VOP:

Let me elaborate on the setup here.

First we take the position and transform it from world space to camera space with Trasform VOP. This transform makes the coordinate space aligned with a camera view.

After that we can isolate a Z axis (depth) with Get Vector Component VOP. The Absolute VOP makes sure the numbers are positive values.

The last step here is to export resulting value as a focus attribute, using Bind Export VOP. focus is a arbitrary name so it can be anything you want.

That’s it for VOPs. Go one level up.

The next step is to merge this new data with the original camera object network, using Attribute Copy SOP. Before doing that I promoted the focus attribute from points to detail using Attribute Promote SOP (this step is not necessary but it’s a tiny bit easier to deal with later).

The network now looks like this:

Go one level up to the obj level. The final step is to inject the focus attribute into the Focus distance parameter on the camera object. To do that I’ll use a detail VEX function:

detail('.', 'focus', 0)

If you play the animation now you should see the Focus distance value changing as the target object is moving away from the camera.

The resulting render shows the red sphere is always in focus:

Download the hip file here.

One thought on “How to snap a camera focus (DOF) to a moving object

Leave a comment