dynamic depth of field?

hey there,
im trying to get a “dynamic” depth of field,
that changes when the crosshair in the middle of the screen is pointing at a far object or a near object.
any ideas ? i dont even know how to start…

I would start with the depth of field replacement shader on the website in the shader replacements.

for DoF, just to mention that, you must own Unity Pro
no way to do it reasonably without it

yeah i have unity pro and the shader, but how do make that the depth is changing whereever the fps player is pointing at ?

I would use a Raycast and then find RaycastHit.distance to find the distance and use that to set the focal distance for the FOV effect. Someone posted something like this a while back (probably several years ago).

thanks! im trying that now.

edit:
any way to change that a raycast is pointing downwards
the y axis ?

You can pass whatever vector you like to the Physics.Raycast call. If you want the global down vector, use this:-

var downVec = -Vector3.up;

…and for the character’s local down direction, use:-

var downVec = -transform.up;

Then, pass this into the raycast call:-

 if (Physics.Raycast(rayStartPoint, downVec, hit)) {
   ...
}

thanks !

i will post my progress soon.

I did this a while ago. It looks great. Here ya go:

//Script by Musichopper to make realistic DOF
var targetFocusRange : float=10.0;
var targetFocusDistance : float =1.0;
var mainCamera : Camera;
private var dof : DepthOfFieldEffect;
private var hit : RaycastHit;
private var start : Transform;
private var distanceOfObject:float;

function Start(){
	start=transform;
	dof = GetComponent(DepthOfFieldEffect);
}

function LateUpdate () {
var fwd = transform.TransformDirection (Vector3.forward);
	
			if (Physics.Raycast (start.position, fwd, hit, 200)) {
				distanceOfObject = hit.distance;
				targetFocusRange=distanceOfObject/.4;
				targetFocusDistance=distanceOfObject-(distanceOfObject/4);
				if(distanceOfObject<3){
					targetFocusRange=distanceOfObject;
					targetFocusDistance=distanceOfObject-.5;
						if(distanceOfObject<.7){
							targetFocusRange=.5;
							targetFocusDistance=.4;
						}
				}
				dof.focalRange = targetFocusRange;
				dof.focalDistance = targetFocusDistance;
			}
	
}

I am using it in a game I have been working on. It does seem to slow things down a bit because of the DOF itself but I feel it is worth it. I have VERY low settings for the DOF itself!

Just drop this into the main camera as well as the DOF effect script. One thing I didn’t get to adding to it is correcting the issue of always blurring the skybox because its beyond the raycast and wont be seen as an object.

thanks !
i noticed that you also get that effect from the unity 3 bootcamp demo (if you aim)

Im having a little trouble getting the ^ script working with 3.5

i get errors saying DepthOfFieldEffect cant be found.
when i change this to DepthOfField34 it cant find the attributes in 30 and 31??

^-- Same problem here with whatever the latest version of Unity is (4.1.something I think)

Here is one I wrote, it’s based off of a few different ways I found on the internet.

  1. Attach the DynamicDOF script to your camera.

  2. Attach “Depth Of Field 34”

  3. Assign the “Depth Of Field 34” object to the “DOF34” field on the DynamicDOF script.

  4. If your using a Character Controller or anything with a collider as your origin point (The Player), create an empty gameobject and move it just outside the collider forward. Make it a child of the Controller. Colliders seem to mess up the ray origin if it’s too close to it.

  5. create another empty gameobject and set it as the target in the DynamicDOF script. IMPORTANT: Also assign this new gameobject to the the “Transform” field on the “Depth Of Field 34”.

  6. Move the “Focal distance” to max on the “Depth Of Field 34”. This is to allow the player to focus on the sky if he looks up. If the ray doesn’t hit anything, the “Depth Of Field 34” will focus on this max distance.

  7. I set the “Focal size” to 200, it seems to work well, but you can play with it.

This seems to be the best setup with Terrain. I originally set the “Transform” on the “Depth Of Field 34” to dynamically change to what the raycast hits, but then looking at the terrain, the “Depth Of Field 34” seemed to focus on the center of the terrain, instead of the trees and such. So, now the raycast simply moves the target gameobject to what it hits and the “Depth Of Field 34” always looks at that target.

Let me know if this works for anyone and if you have issues.

using UnityEngine;
using System.Collections;

public class DynamicDOF : MonoBehaviour {

	public Transform Origin;
	public Transform target;
	public DepthOfField34 DOF34;
	
	void Update () {
	
		Ray ray = new Ray(Origin.position, Origin.forward);
		RaycastHit hit = new RaycastHit ();
		
		if (Physics.Raycast (ray, out hit, Mathf.Infinity))
		{
			DOF34.objectFocus = target;
			target.transform.position = hit.point;
		}
		else
		{
		DOF34.objectFocus = null;
		}
		
	}
}

CRAZY ROBOT, your script only works for me IF I set the Camera as “origin” in the custom DynamicDOF script you provided … btw. I am developing for the Oculus Rift.

Hmm… I’m not sure what your setup is. What do you want to set the origin transform as? if you leave it blank it will not work, you need a transform assigned to it.

Can you explain your setup to me?
Are you using a character controller with the camera as a child? If so, did you make another empty gameobject positioned just outside the character controller?

Or are you just using the camera?

Hey Crazy,

I am only using the camera as in fixed. Another thing I want to achieve is the blur to be gradual. I would like to not jump it from blur level based on focus distance to blur level based on focus distance but rather smoothly transform. Do you have any idea on how to make that happen?

Vector3.Lerp the focus target to a new raycast hit.

Thanks for the tip. I am very new to Unity and its scripting. How would I implement Vector3.Lerp here: “target.transform.position = hit.point;” ?

target.transform.position = Vector3.Lerp(target.transform.position, hitPos, 1.0f*Time.deltaTime);
where 1.0f is the speed. hitPos is whatever valid position. I didn’t use hit.point as I don’t know if that’s always valid for you as the above calculation needs to be performed every frame, and not inside the raycast if block.

I’d recommend you use SmoothDamp instead, as the result is softer, nicer. Unity - Scripting API: Vector3.SmoothDamp

Hey hippocoder,

thanks very much. I now put target.transform.position = Vector3.SmoothDamp(target.transform.position, hit.point, ref velocity, 2); instead of target.transform.position = hit.point;. The problem now is, as in the script provided by Crazy Robot, the else statement only says objectfocus = null and I believe I cannot SmoothDamp to null. At least I didn’t figure out how. So atm the blur only begins via transition but won’t end, still just clip.

Thats why I suggested using a variable instead of hit.point. You run the smoothdamp all the time but only change the variables instead of using references.