I got a comment at work about the characters not matching perfectly with the slightly blurry backgrounds. I thought if some depth of field was at all possible as the backgrounds are not really 3D and might have some blur baked in.
But the thought stayed with me and I decided to give it a shot. In principle it should work, as all my scenes have a very very simple 3D mesh created for the character interaction / occlusion to work.
Enabling depth of field is very easy. It is a simple post process effect I need to add to the Prost process volume.
Focus distance is the area that will be sharp, and focal length determines how blurred out of focus areas get. Simple.
If the blur is not working, you need to also enable the Depth Texture in your scenes main camera. At least when using the URP pipeline.
But at first, I could not get the depth of field to work at all. My character would be blurred, and things that extended into the distance, but my unlit background image would not be blurred no matter what. I googled for hours, trying to figure out how to make the custom HLSL material write to depth buffer, but I was totally out of luck. I also realised that this was the reason why my particles had not blended properly with the location meshes.
It took me a while to figure it out, but the URP screen space ambient occlusion effect overwrite my depth buffer. I found a fix for that, and it is to set the SSAO to use depth only, but for me this option was greyed out for what ever reason. So I just ended up disabling the SSAO effect completely.
My blur setting was super high as I had cranked it all the way up to see what I am working on. I decided to post this to Twitter as it looked fun. People seemed to absolutely love that effect. This is also fun about building in public as the reactions from everyone feed back immediately into the game creation process.
I think I must write an event into the game where the depth of field just goes crazy for a short while. I can not think of anything else though than the character being under the influence of drug os similar, which will bump up the age rating, but what can you do!
To complete the effect, I wanted an auto focus feature, that changed the focal dept h in runtime based on some metric. I had 2 options: keep the focus on the player character, or keep the focus on the mouse pointer.
I ended up going with the mouse pointer. As with point and click user interface, you are actually not playing as the character, you are disconnected from them. You are playing as the mouse pointer. Scanning the screen, looking for stuff to interact with. If the game had direct control (like it highly likely will have when playing with a controller) then the focus for sure will be on the character!
The script is quite simple. Most of the public floats are just for debug purposes for now. The only one that makes a difference is Recovery Rate, which is how slowly the autofocus seeks the mouse pointer position. It makes the focal transition smoother and less jarring.
The position of the mouse is calculated by recasting from the camera to the mouse and getting the distance to the hit 3D collider surface.
AutoFocus.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
public class AutoFocus : MonoBehaviour
{
public bool mouseIsTarget = true;
public float Depth = 5.0f;
public float TargetDepth = 5.0f;
public float recoveryRate = 1.0f;
public Volume postProcessVolume;
DepthOfField tempDof;
DepthOfField dof;
// Start is called before the first frame update
void Start()
{
if (postProcessVolume.profile.TryGet<DepthOfField>(out tempDof))
{
dof = tempDof;
}
}
// Update is called once per frame
void Update()
{
//set depth as focus disatance
TargetDepth = Mathf.MoveTowards(TargetDepth, Depth, recoveryRate * Time.deltaTime);
dof.focusDistance.value = TargetDepth;
RaycastHit hitInfo;
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hitInfo))
{
// Ray hit something in scene
//Debug.Log("Ray hit : " + hitInfo.collider.gameObject.name);
Depth = hitInfo.distance;
}
}
}
I left a very subdued version of the depth of field in the game. It adds something to the look. At the moment, the depth of field is only mostly visible when the focus is on the very foreground. Which is quite nice. Other times the screen is quite sharp trough and trough.
Leave a Reply