Unity 景深Depth Of Field
景深效果Depth Of Field是摄影界的老常客了,在游戏中也非常多见,它能够大幅提升游戏画面体验和真实度,使得物体看起来更有细节。GTA5中的景深效果Unity 当然提供了景深支持:本文我将介绍最简单直接的实现方法,不需要任何复杂的物理学只是,直截了当的就能出效果。
目录
介绍:
景深效果Depth Of Field是摄影界的老常客了,在游戏中也非常多见,它能够大幅提升游戏画面体验和真实度,使得物体看起来更有细节。
GTA5中的景深效果
Unity 当然提供了景深支持: Creative Core: Post-processing - Unity Learn
本文我将介绍最简单直接的实现方法,不需要任何复杂的物理学只是,直截了当的就能出效果。
准备
本节将分别介绍Built-in Render,URP,HDRP中的基础景深效果。所有的管线景深都需要用到PostProcessing功能。
首先,三种管线都需要先把简单的前置设置部署好:Built-in Render需要额外安装package,另外两个不用,在package manager中搜索安装 Post Processing,这个插件早晚会用,它提供了全方位的画质颜色和视觉提升。
设置
-
基于Unity Builtin 管线
更多参考:Post Process Volumes - Unity Learn
基于Unity Builtin 管线, 需要额外安装 PostProcessing package,安装完成后,你需要:
- 在Layer设置中增加一个Layer,可以随便命名,但是建议就叫 “PostProcessing” ;然后在你想要设置的Camera中增加Post-process Layer组件;接着设置这个组件的Layer为你刚刚新添加的“PostProcessing” ,确组件的Trigger是你想要的相机;
- 创建一个空物体,或者你可以继续在Camera中添加,(只要确保和PostProcessing有关的所有对象都有“PostProcessing” Layer!),在这个物体中添加Post-Process Volume
- 创建并保存你的Profile,并在Add effect选项中添加Depth Of Field效果,一般来说Apture小一些,Focal Length大一些可以得到一个不错的景深效果,之后你就只需要调整焦距Focus Distance就可以了!
-
如果你需要动态根据距离来调整的话,需要代码接入来更改volume的 Focus Distance,可以动过简单计算相机和焦点物体的距离来更改;另一种方案是通过屏幕中心发射一道射线来判断距离,这里介绍简单的:
using UnityEngine;
using UnityEngine.Rendering.PostProcessing;
public class cameraDist : MonoBehaviour
{
[SerializeField] PostProcessVolume postProcessVolume;
[SerializeField] DepthOfField df;
[SerializeField] Transform player,mainCamera;
void Start()
{
postProcessVolume.sharedProfile.TryGetSettings<DepthOfField>(out df);
}
}
void Update()
{
df.focusDistance.value = Vector3.Distance(player.position, mainCamera.position);
}
-
基于Unity URP
基于Unity URP, PostProcessing 已经默认包含,而且不需要设置Layer。其它设置和Buit-in基本一致,但是确保在相机设置中启用Post Processing功能! 然后直接在相机中添加Volume组件就可以了,其它步骤基本不变,景深设置中可选用Bokeh
动态更改焦距,这里和Built-in类似,只是引用的API不一样,此外,这里使用简单的射线检测,从相机发出一条射线,射到谁就用谁到相机的距离,但这个方法不适用在复杂场景和运动条件下
using UnityEngine;
public class cameraDist : MonoBehaviour
{
[SerializeField] private UnityEngine.Rendering.Volume postProcessVolume;
[SerializeField] private UnityEngine.Rendering.Universal.DepthOfField dof;
void Start()
{
postProcessVolume.profile.TryGet<UnityEngine.Rendering.Universal.DepthOfField>(out dof);
}
}
void Update()
{
RaycastHit hit;
if (Physics.Raycast(mainCamera.transform.position, mainCamera.transform.forward, out hit, Mathf.Infinity))
{
dof.focusDistance.value = hit.distance;
}
}
-
基于Unity HDRP
HDRP就更神奇了,由于更高渲染技术的加持,其图像原理看起来很不一样,这里的相机看起来更像显示世界里的相机了,相机直接按如图设置:
Volume和景深效果的添加和URP一样,但是它的参数可以被相机的物理信息直接控制了:
hHDRP的动态对焦,脚本这时候就需要直接更改相机属性就行了,但是注意,相机必须设置为物理相机!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
public class CameraFocus : MonoBehaviour
{
public Transform target;
[SerializeField] Camera cam;
// Update is called once per frame
private void OnValidate()
{
cam = GetComponent<Camera>();
cam.usePhysicalProperties = true;
cam.GetComponent<HDAdditionalCameraData>().physicalParameters.focusDistance = Vector3.Distance(transform.position, target.position);
}
private void Start()
{
cam = GetComponent<Camera>();
cam.usePhysicalProperties = true;
}
void Update()
{
FocusByRaycast();
}
void FocusByTransform(Transform target)
{
// change camera focus distance
cam.GetComponent<HDAdditionalCameraData>().physicalParameters.focusDistance = Vector3.Distance(transform.position, target.position);
}
void FocusByRaycast()
{
//raycast to target hit distance
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.forward, out hit))
{
// change camera focus distance
cam.GetComponent<HDAdditionalCameraData>().physicalParameters.focusDistance = hit.distance;
}
}
}
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)