Unity 景深Depth Of Field

目录

 

介绍

准备

设置

基于Unity Builtin 管线

基于Unity URP

基于Unity HDRP


 

介绍:

景深效果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,安装完成后,你需要:

  1. 在Layer设置中增加一个Layer,可以随便命名,但是建议就叫 PostProcessing” ;然后在你想要设置的Camera中增加Post-process Layer组件;接着设置这个组件的Layer为你刚刚新添加的“PostProcessing” ,确组件的Trigger是你想要的相机;
  2. 创建一个空物体,或者你可以继续在Camera中添加,(只要确保和PostProcessing有关的所有对象都有“PostProcessing” Layer!),在这个物体中添加Post-Process Volume
  3. 创建并保存你的Profile,并在Add effect选项中添加Depth Of Field效果,一般来说Apture小一些Focal Length大一些可以得到一个不错的景深效果,之后你就只需要调整焦距Focus Distance就可以了!
  4. Unity 景深Depth Of Field_第1张图片

    Unity 景深Depth Of Field_第2张图片

    Unity 景深Depth Of Field_第3张图片

    Unity 景深Depth Of Field_第4张图片

    Unity 景深Depth Of Field_第5张图片

     

Unity 景深Depth Of Field_第6张图片

如果你需要动态根据距离来调整的话,需要代码接入来更改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(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

 Unity 景深Depth Of Field_第7张图片Unity 景深Depth Of Field_第8张图片

Unity 景深Depth Of Field_第9张图片

 

动态更改焦距,这里和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(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就更神奇了,由于更高渲染技术的加持,其图像原理看起来很不一样,这里的相机看起来更像显示世界里的相机了,相机直接按如图设置:

Unity 景深Depth Of Field_第10张图片

 Volume和景深效果的添加和URP一样,但是它的参数可以被相机的物理信息直接控制了:

Unity 景深Depth Of Field_第11张图片

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();
        cam.usePhysicalProperties = true;
        cam.GetComponent().physicalParameters.focusDistance = Vector3.Distance(transform.position, target.position);
    }
    private void Start()
    {
        cam = GetComponent();
        cam.usePhysicalProperties = true;
    }
    void Update()
    {
        FocusByRaycast();
    }
    void FocusByTransform(Transform target)
    {
        // change camera focus distance 
        cam.GetComponent().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().physicalParameters.focusDistance = hit.distance;
        }

    }
}

 

 

 

 

 

你可能感兴趣的:(Unity,经验分享,unity,游戏引擎,游戏程序,游戏美术)