九月份一篇博都沒更新,這段時間一直在unity的坑里爬不起來,感覺真的很絕望啊,仿佛對生活都失去了信心。
渲染問題並沒有解決,目前方案只是減輕視覺沖突,降低違和感。項目AR產品也做的越來越艱難,開始經常想一個問題,我從哪里來,我該到哪里去。。。
好吧,嘮叨這么多,言歸正傳,今天說說unity的Post-Processing后期處理的景深 Depth Of Field
官方文檔 https://docs.unity3d.com/Manual/PostProcessingOverview.html
先貼完整代碼,下載PostProcessing插件並import,將下面腳本掛在camera上,運行
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.PostProcessing;
public class DepthOfFieldTest : MonoBehaviour {
public Transform nearBlurTarget;
public Transform farBlurTarget;
private PostProcessingProfile profile;
// Use this for initialization
void Start () {
AddPostProcessing ();
BlurEffect();
}
/// <summary>
/// Adds the post processing 后期處理特效.
/// </summary>
public void AddPostProcessing ()
{
PostProcessingBehaviour postProcessingBehaviour = gameObject.AddComponent<PostProcessingBehaviour> ();
this.profile = new PostProcessingProfile ();
// this.profile = Resources.Load ("GreenArchPOST") as PostProcessingProfile;
postProcessingBehaviour.profile = profile;
profile.depthOfField.enabled = false;
profile.antialiasing.enabled = true;
profile.ambientOcclusion.enabled = true;
// AO參數設置,主要是要勾選ambientOnly選項
AmbientOcclusionModel.Settings aoSettings = new AmbientOcclusionModel.Settings () {
intensity = 1f,
radius = 0.3f,
sampleCount = AmbientOcclusionModel.SampleCount.Medium,
downsampling = true,
forceForwardCompatibility = false,
ambientOnly = true,
highPrecision = false
};
profile.ambientOcclusion.settings = aoSettings;
}
/// <summary>
/// Blurs the effect景深模糊效果.
/// </summary>
/// <param name="jo">Jo.</param>
public void BlurEffect()
{
DepthOfFieldModel depthOfField = this.profile.depthOfField;
Vector3 focusPosition = (1.5f * nearBlurTarget.position + farBlurTarget.position) / 2.5f;
Plane cameraPlane = new Plane(gameObject.transform.forward, gameObject.transform.position);
float focusDistance = cameraPlane.GetDistanceToPoint (focusPosition);
float depthOfFeild = Mathf.Abs (cameraPlane.GetDistanceToPoint (farBlurTarget.position) - cameraPlane.GetDistanceToPoint (nearBlurTarget.position));
// 根據公式計算 景深ΔL=ΔL1+ΔL2=(2f^2FδL^2)/(f^4-F^2δ^2L^2)
// 容許彌散圓直徑 δ=0.035mm
float ap = 5.6f * 0.035f / 1000f;
float focusDistancex2 = Mathf.Pow (focusDistance, 2f);
float lengthx2 = ap * focusDistancex2 + ap * focusDistance * Mathf.Sqrt(focusDistancex2 + Mathf.Pow (depthOfFeild, 2f));
float focalLengthByMath = Mathf.Sqrt (lengthx2 / depthOfFeild) * 1000f;
Debug.Log ("清晰點距相機距離:" + focusDistance);
Debug.Log ("景深:" + depthOfFeild);
Debug.Log ("相機焦距 focalLengthByMath (mm):" + focalLengthByMath);
depthOfField.enabled = true;
UnityEngine.PostProcessing.DepthOfFieldModel.Settings depthOfFieldSetting = new UnityEngine.PostProcessing.DepthOfFieldModel.Settings {
focusDistance = focusDistance,
aperture = 5.6f,
focalLength = focalLengthByMath,
useCameraFov = false,
kernelSize = DepthOfFieldModel.KernelSize.Medium
};
depthOfField.settings = depthOfFieldSetting;
}
}
采用PostProcessing攝像機后期處理特效,Depth Of Field模塊,根據前端給的三個參數計算Focus Distance 焦點距離 和 focalLength鏡頭焦距。
1.Focus Distance具體含義是距離攝像機多遠的“距離”拍攝最高清,這個距離是目標點與相機平面的垂直距離,相機平面可以這樣確定,1.與nearPlane平面平行,過相機位置點。所以焦距Focus Distance可以通過以下代碼求得並設置:
//相機輔助平面
Plane cameraPlane = new Plane(camera.transform.forward,camera.transform.position);
//計算目標距離相機的距離,焦點距離 focusDistance
float focusDistance = cameraPlane.GetDistanceToPoint (focusPosition);
2.focalLength 鏡頭焦距,通過景深 nearBlurPosition 和 farBlurPosition計算得到。景深計算方式如下:

看成景深、鏡頭焦距、光圈值的一個方程,將鏡頭焦距作為要求的跟,根據一元二次方程的解:

得到 :

