随便说说 post-processing

九月份一篇博都没更新,这段时间一直在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计算得到。景深计算方式如下:

景深计算.jpg

看成景深、镜头焦距、光圈值的一个方程,将镜头焦距作为要求的跟,根据一元二次方程的解:

image.png

得到 :

image.png

posted @ 2017-09-15 15:50  lipper_p  Views(3910)  Comments(0Edit  收藏  举报