Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

dynamic depth of field?

Discussion in 'Editor & General Support' started by Daimon, Aug 29, 2010.

  1. Daimon

    Daimon

    Joined:
    Jul 20, 2010
    Posts:
    32
    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...
     
    Last edited: Nov 6, 2010
  2. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    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
     
  3. Daimon

    Daimon

    Joined:
    Jul 20, 2010
    Posts:
    32
    yeah i have unity pro and the shader, but how do make that the depth is changing whereever the fps player is pointing at ?
     
  4. bigkahuna

    bigkahuna

    Joined:
    Apr 30, 2006
    Posts:
    5,434
    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).
     
  5. Daimon

    Daimon

    Joined:
    Jul 20, 2010
    Posts:
    32
    thanks! im trying that now.

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

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    You can pass whatever vector you like to the Physics.Raycast call. If you want the global down vector, use this:-
    Code (csharp):
    1. var downVec = -Vector3.up;
    ...and for the character's local down direction, use:-
    Code (csharp):
    1. var downVec = -transform.up;
    Then, pass this into the raycast call:-
    Code (csharp):
    1.  if (Physics.Raycast(rayStartPoint, downVec, hit)) {
    2.    ...
    3. }
     
  7. Daimon

    Daimon

    Joined:
    Jul 20, 2010
    Posts:
    32
    thanks !

    i will post my progress soon.
     
  8. musichopper

    musichopper

    Joined:
    Jul 22, 2009
    Posts:
    55
    I did this a while ago. It looks great. Here ya go:

    Code (csharp):
    1.  
    2. //Script by Musichopper to make realistic DOF
    3. var targetFocusRange : float=10.0;
    4. var targetFocusDistance : float =1.0;
    5. var mainCamera : Camera;
    6. private var dof : DepthOfFieldEffect;
    7. private var hit : RaycastHit;
    8. private var start : Transform;
    9. private var distanceOfObject:float;
    10.  
    11. function Start(){
    12.     start=transform;
    13.     dof = GetComponent(DepthOfFieldEffect);
    14. }
    15.  
    16. function LateUpdate () {
    17. var fwd = transform.TransformDirection (Vector3.forward);
    18.    
    19.             if (Physics.Raycast (start.position, fwd, hit, 200)) {
    20.                 distanceOfObject = hit.distance;
    21.                 targetFocusRange=distanceOfObject/.4;
    22.                 targetFocusDistance=distanceOfObject-(distanceOfObject/4);
    23.                 if(distanceOfObject<3){
    24.                     targetFocusRange=distanceOfObject;
    25.                     targetFocusDistance=distanceOfObject-.5;
    26.                         if(distanceOfObject<.7){
    27.                             targetFocusRange=.5;
    28.                             targetFocusDistance=.4;
    29.                         }
    30.                 }
    31.                 dof.focalRange = targetFocusRange;
    32.                 dof.focalDistance = targetFocusDistance;
    33.             }
    34.    
    35. }
    36.  
    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.
     
  9. Daimon

    Daimon

    Joined:
    Jul 20, 2010
    Posts:
    32
    thanks !
    i noticed that you also get that effect from the unity 3 bootcamp demo (if you aim)
     
  10. cwisbg

    cwisbg

    Joined:
    Jul 27, 2011
    Posts:
    88
    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??
     
  11. M4R5

    M4R5

    Joined:
    Apr 11, 2013
    Posts:
    33
    ^-- Same problem here with whatever the latest version of Unity is (4.1.something I think)
     
  12. Crazy Robot

    Crazy Robot

    Joined:
    Apr 18, 2009
    Posts:
    921
    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.

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class DynamicDOF : MonoBehaviour {
    5.  
    6.     public Transform Origin;
    7.     public Transform target;
    8.     public DepthOfField34 DOF34;
    9.    
    10.     void Update () {
    11.    
    12.         Ray ray = new Ray(Origin.position, Origin.forward);
    13.         RaycastHit hit = new RaycastHit ();
    14.        
    15.         if (Physics.Raycast (ray, out hit, Mathf.Infinity))
    16.         {
    17.             DOF34.objectFocus = target;
    18.             target.transform.position = hit.point;
    19.         }
    20.         else
    21.         {
    22.         DOF34.objectFocus = null;
    23.         }
    24.        
    25.     }
    26. }
     
    Last edited: Sep 10, 2013
  13. smx

    smx

    Joined:
    Oct 23, 2013
    Posts:
    10
    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.
     
  14. Crazy Robot

    Crazy Robot

    Joined:
    Apr 18, 2009
    Posts:
    921
    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?
     
  15. smx

    smx

    Joined:
    Oct 23, 2013
    Posts:
    10
    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?
     
  16. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Vector3.Lerp the focus target to a new raycast hit.
     
  17. smx

    smx

    Joined:
    Oct 23, 2013
    Posts:
    10
    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;" ?
     
  18. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    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.
    http://docs.unity3d.com/Documentation/ScriptReference/Vector3.SmoothDamp.html
     
  19. smx

    smx

    Joined:
    Oct 23, 2013
    Posts:
    10
    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.
     
  20. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    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.
     
  21. Mad Grendel

    Mad Grendel

    Joined:
    Jun 12, 2014
    Posts:
    13
    Holy crap this works perfect so far, thanks for saving me a lot of time figuring this out!! I had the idea but props to you for coding it. I had to change a few things to make if work with the DepthOfFieldScatter image effect and it is beautiful!

    Here's my version:

    Code (JavaScript):
    1. #pragma strict
    2.  
    3. //Script by Musichopper to make realistic DOF
    4. // modified by MadGrendel @ Google+
    5. var targetFocusRange : float=10.0;
    6. var targetFocusDistance : float =1.0;
    7. var mainCamera : Camera;
    8. private var dof : DepthOfFieldScatter;
    9. private var hit : RaycastHit;
    10. private var start : Transform;
    11. private var distanceOfObject:float;
    12. function Start(){
    13.     start=transform;
    14.     dof = GetComponent(DepthOfFieldScatter);
    15. }
    16. function LateUpdate () {
    17. var fwd = transform.TransformDirection (Vector3.forward);
    18.  
    19.             if (Physics.Raycast (start.position, fwd, hit, 200)) {
    20.                 distanceOfObject = hit.distance;
    21.                 targetFocusRange=distanceOfObject/.4;
    22.                 targetFocusDistance=distanceOfObject-(distanceOfObject/4);
    23.                 if(distanceOfObject<3){
    24.                     targetFocusRange=distanceOfObject;
    25.                     targetFocusDistance=distanceOfObject-.5;
    26.                         if(distanceOfObject<.7){
    27.                             targetFocusRange=.5;
    28.                             targetFocusDistance=.4;
    29.                         }
    30.                 }
    31.                 dof.focalSize = targetFocusRange;
    32.                 dof.focalLength = targetFocusDistance;
    33.             }
    34.  
    35. }
     
  22. TemplarGFX

    TemplarGFX

    Joined:
    Aug 21, 2014
    Posts:
    103
    Can someone help me please. None of these scripts will work for me as the line

    Code (csharp):
    1. private var dof : DepthOfFieldScatter;
    Wont compile. DepthOfFieldScatter is not an available class/type (or whatever)

    If I remove this word, and press D (to get the list of available options) none of the DOF scripts are listed.

    I have Image Effects imported and added Depth Of Field (DX11, scatter etc) to my camera so the DOF is definitely there, available and working.

    How come I cannot use these scripts? I am obviously missing something
     
  23. Mad Grendel

    Mad Grendel

    Joined:
    Jun 12, 2014
    Posts:
    13
    I have this script and the DepthOfFieldScatter Image Effect attached to the Main Camera. Is that what you did as well? That's weird that the code won't compile I'm definitely using it just fine. Wait are you using a JavaScript or C# script? This is for JavaScript.
     
  24. TemplarGFX

    TemplarGFX

    Joined:
    Aug 21, 2014
    Posts:
    103
    C# I converted the code manually to C# but for some reason MonoDevelop couldn't see DepthOfFieldScatter (It was in scene). Ive had this issue with built-ins too (like quaternion which wouldn't show up until I went to it manually).

    I ended up coming up with my own method as follows :

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class DynamicDOF : MonoBehaviour {
    6.  public Transform origin;
    7.  public GameObject target;
    8.  
    9.  
    10.  // Update is called once per frame
    11.  void Update () {
    12.  Ray ray = new Ray (origin.transform.position, origin.transform.forward);
    13.  RaycastHit hit = new RaycastHit ();
    14.  if (Physics.Raycast (ray, out hit, Mathf.Infinity)) {
    15.  target.transform.position = hit.point;
    16.  }
    17.  }
    18. }
    Origin is set to the Camera (or FPS controller) and Target is an empty object to be set as the focal point in DepthOfFieldScatter.

    Im going to flesh this out to have smoother transitions between close and far focus points
     
    salex1 likes this.
  25. Mad Grendel

    Mad Grendel

    Joined:
    Jun 12, 2014
    Posts:
    13
    Sounds good keep us posted.
     
  26. Ben_the_Lad

    Ben_the_Lad

    Joined:
    Jan 19, 2014
    Posts:
    2
    Hello, people!

    I'm playing with DoF for the first time and would really like to adjust the focalLength of DoF, based on my RaycastHit info's .distance variable. The idea being that whatever I'm looking at, the focal distance moves to it.

    I have a camera controller script which helps my offset FPS gun aim at whatever's in the center of the screen. In that script, I send a recast and get back hit info:

    void Aiming()
    {
    // Stores Camera's transform
    Transform camera = Camera.main.transform;

    // Stores hit data from Raycast

    RaycastHit hit;

    // Raycast parameters to pass to if statement

    Ray aim = new Ray(transform.position, camera.forward);

    // Returns Raycast's hit data and assigns its coordinates to target
    if(Physics.Raycast(aim, out hit, rayLen))
    {
    target = hit.point;
    targetDist = hit.distance;
    }
    else
    {
    target = transform.position + camera.forward.normalized * rayLen;
    }
    }

    targetDist has been added to send the length of the ray to the DoF Script.

    I've tried to access the script a couple of ways:
    1. Camera.main.GetComponent(DepthOfField).focalLength = targetDist;
    2. DepthOfField.focalLength = targetDist;
    ...But I'm obviously doing something wrong, as this doesn't work. :) Option 1 gives me "type or namespace not found" and option 2 gives me "DepthOfField does not exist in current context".

    I'm not a great coder, so it's entirely possible I'm missing something stupid. Bear with me as I learn, please. :)

    How can I access DepthOfField's focalLength variable?
     
  27. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Declare:
    public UnityStandardAssets.ImageEffects.DepthOfField dof;


    Awake:
    dof = GetComponent<UnityStandardAssets.ImageEffects.DepthOfField>();

    Namespace is UnityStandardAssets.ImageEffects
     
  28. Ben_the_Lad

    Ben_the_Lad

    Joined:
    Jan 19, 2014
    Posts:
    2
    Aha! This works beautifully, and really beefs up the feel of looking around!

    In my mad keyboard spamming to get this working, I had tried declaring it a couple ways, but I've never used anything from UnityStandardAssets so didn't understand the protocol. This explains much.

    Thank you, hippocoder!