隨便說說 post-processing

九月份一篇博都沒更新,這段時間一直在unity的坑裏爬不起來,感受真的很絕望啊,彷彿對生活都失去了信心。html

渲染問題並無解決,目前方案只是減輕視覺衝突,下降違和感。項目AR產品也作的愈來愈艱難,開始常常想一個問題,我從哪裏來,我該到哪裏去。。。前端

好吧,嘮叨這麼多,言歸正傳,今天說說unity的Post-Processing後期處理的景深 Depth Of Fieldpost

官方文檔 https://docs.unity3d.com/Manual/PostProcessingOverview.htmlthis

先貼完整代碼,下載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鏡頭焦距。3d

1.Focus Distance具體含義是距離攝像機多遠的「距離」拍攝最高清,這個距離是目標點與相機平面的垂直距離,相機平面能夠這樣肯定,1.與nearPlane平面平行,過相機位置點。因此焦距Focus Distance能夠經過如下代碼求得並設置:orm

//相機輔助平面htm

Plane cameraPlane = new Plane(camera.transform.forward,camera.transform.position);blog

//計算目標距離相機的距離,焦點距離 focusDistanceci

float focusDistance = cameraPlane.GetDistanceToPoint (focusPosition);

 

2.focalLength 鏡頭焦距,經過景深 nearBlurPosition 和 farBlurPosition計算獲得。景深計算方式以下:

景深計算.jpg

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

image.png

獲得 :

image.png

相關文章
相關標籤/搜索