Files
2026-02-21 16:45:37 +08:00

453 lines
15 KiB
C#

using UnityEngine;
namespace UnityStandardAssets.ImageEffects
{
[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
[AddComponentMenu("Image Effects/Camera/Depth of Field (deprecated)")]
public class DepthOfFieldDeprecated : PostEffectsBase
{
public enum Dof34QualitySetting
{
OnlyBackground = 1,
BackgroundAndForeground = 2
}
public enum DofResolution
{
High = 2,
Medium = 3,
Low = 4
}
public enum DofBlurriness
{
Low = 1,
High = 2,
VeryHigh = 4
}
public enum BokehDestination
{
Background = 1,
Foreground = 2,
BackgroundAndForeground = 3
}
private static int SMOOTH_DOWNSAMPLE_PASS = 6;
private static float BOKEH_EXTRA_BLUR = 2f;
public Dof34QualitySetting quality = Dof34QualitySetting.OnlyBackground;
public DofResolution resolution = DofResolution.Low;
public bool simpleTweakMode = true;
public float focalPoint = 1f;
public float smoothness = 0.5f;
public float focalZDistance;
public float focalZStartCurve = 1f;
public float focalZEndCurve = 1f;
private float focalStartCurve = 2f;
private float focalEndCurve = 2f;
private float focalDistance01 = 0.1f;
public Transform objectFocus;
public float focalSize;
public DofBlurriness bluriness = DofBlurriness.High;
public float maxBlurSpread = 1.75f;
public float foregroundBlurExtrude = 1.15f;
public Shader dofBlurShader;
private Material dofBlurMaterial;
public Shader dofShader;
private Material dofMaterial;
public bool visualize;
public BokehDestination bokehDestination = BokehDestination.Background;
private float widthOverHeight = 1.25f;
private float oneOverBaseSize = 0.001953125f;
public bool bokeh;
public bool bokehSupport = true;
public Shader bokehShader;
public Texture2D bokehTexture;
public float bokehScale = 2.4f;
public float bokehIntensity = 0.15f;
public float bokehThresholdContrast = 0.1f;
public float bokehThresholdLuminance = 0.55f;
public int bokehDownsample = 1;
private Material bokehMaterial;
private Camera _camera;
private RenderTexture foregroundTexture;
private RenderTexture mediumRezWorkTexture;
private RenderTexture finalDefocus;
private RenderTexture lowRezWorkTexture;
private RenderTexture bokehSource;
private RenderTexture bokehSource2;
private void CreateMaterials()
{
dofBlurMaterial = CheckShaderAndCreateMaterial(dofBlurShader, dofBlurMaterial);
dofMaterial = CheckShaderAndCreateMaterial(dofShader, dofMaterial);
bokehSupport = bokehShader.isSupported;
if (bokeh && bokehSupport && (bool)bokehShader)
{
bokehMaterial = CheckShaderAndCreateMaterial(bokehShader, bokehMaterial);
}
}
public override bool CheckResources()
{
CheckSupport(true);
dofBlurMaterial = CheckShaderAndCreateMaterial(dofBlurShader, dofBlurMaterial);
dofMaterial = CheckShaderAndCreateMaterial(dofShader, dofMaterial);
bokehSupport = bokehShader.isSupported;
if (bokeh && bokehSupport && (bool)bokehShader)
{
bokehMaterial = CheckShaderAndCreateMaterial(bokehShader, bokehMaterial);
}
if (!isSupported)
{
ReportAutoDisable();
}
return isSupported;
}
private void OnDisable()
{
Quads.Cleanup();
}
private void OnEnable()
{
_camera = GetComponent<Camera>();
_camera.depthTextureMode |= DepthTextureMode.Depth;
}
private float FocalDistance01(float worldDist)
{
return _camera.WorldToViewportPoint((worldDist - _camera.nearClipPlane) * _camera.transform.forward + _camera.transform.position).z / (_camera.farClipPlane - _camera.nearClipPlane);
}
private int GetDividerBasedOnQuality()
{
int result = 1;
if (resolution == DofResolution.Medium)
{
result = 2;
}
else if (resolution == DofResolution.Low)
{
result = 2;
}
return result;
}
private int GetLowResolutionDividerBasedOnQuality(int baseDivider)
{
int num = baseDivider;
if (resolution == DofResolution.High)
{
num *= 2;
}
if (resolution == DofResolution.Low)
{
num *= 2;
}
return num;
}
private void OnRenderImage(RenderTexture source, RenderTexture destination)
{
if (!CheckResources())
{
Graphics.Blit(source, destination);
return;
}
if (smoothness < 0.1f)
{
smoothness = 0.1f;
}
bokeh = bokeh && bokehSupport;
float num = ((!bokeh) ? 1f : BOKEH_EXTRA_BLUR);
bool flag = quality > Dof34QualitySetting.OnlyBackground;
float num2 = focalSize / (_camera.farClipPlane - _camera.nearClipPlane);
if (simpleTweakMode)
{
focalDistance01 = ((!objectFocus) ? FocalDistance01(focalPoint) : (_camera.WorldToViewportPoint(objectFocus.position).z / _camera.farClipPlane));
focalStartCurve = focalDistance01 * smoothness;
focalEndCurve = focalStartCurve;
flag = flag && focalPoint > _camera.nearClipPlane + Mathf.Epsilon;
}
else
{
if ((bool)objectFocus)
{
Vector3 vector = _camera.WorldToViewportPoint(objectFocus.position);
vector.z /= _camera.farClipPlane;
focalDistance01 = vector.z;
}
else
{
focalDistance01 = FocalDistance01(focalZDistance);
}
focalStartCurve = focalZStartCurve;
focalEndCurve = focalZEndCurve;
flag = flag && focalPoint > _camera.nearClipPlane + Mathf.Epsilon;
}
widthOverHeight = 1f * (float)source.width / (1f * (float)source.height);
oneOverBaseSize = 0.001953125f;
dofMaterial.SetFloat("_ForegroundBlurExtrude", foregroundBlurExtrude);
dofMaterial.SetVector("_CurveParams", new Vector4((!simpleTweakMode) ? focalStartCurve : (1f / focalStartCurve), (!simpleTweakMode) ? focalEndCurve : (1f / focalEndCurve), num2 * 0.5f, focalDistance01));
dofMaterial.SetVector("_InvRenderTargetSize", new Vector4(1f / (1f * (float)source.width), 1f / (1f * (float)source.height), 0f, 0f));
int dividerBasedOnQuality = GetDividerBasedOnQuality();
int lowResolutionDividerBasedOnQuality = GetLowResolutionDividerBasedOnQuality(dividerBasedOnQuality);
AllocateTextures(flag, source, dividerBasedOnQuality, lowResolutionDividerBasedOnQuality);
Graphics.Blit(source, source, dofMaterial, 3);
Downsample(source, mediumRezWorkTexture);
Blur(mediumRezWorkTexture, mediumRezWorkTexture, DofBlurriness.Low, 4, maxBlurSpread);
if (bokeh && (BokehDestination.Foreground & bokehDestination) != 0)
{
dofMaterial.SetVector("_Threshhold", new Vector4(bokehThresholdContrast, bokehThresholdLuminance, 0.95f, 0f));
Graphics.Blit(mediumRezWorkTexture, bokehSource2, dofMaterial, 11);
Graphics.Blit(mediumRezWorkTexture, lowRezWorkTexture);
Blur(lowRezWorkTexture, lowRezWorkTexture, bluriness, 0, maxBlurSpread * num);
}
else
{
Downsample(mediumRezWorkTexture, lowRezWorkTexture);
Blur(lowRezWorkTexture, lowRezWorkTexture, bluriness, 0, maxBlurSpread);
}
dofBlurMaterial.SetTexture("_TapLow", lowRezWorkTexture);
dofBlurMaterial.SetTexture("_TapMedium", mediumRezWorkTexture);
Graphics.Blit(null, finalDefocus, dofBlurMaterial, 3);
if (bokeh && (BokehDestination.Foreground & bokehDestination) != 0)
{
AddBokeh(bokehSource2, bokehSource, finalDefocus);
}
dofMaterial.SetTexture("_TapLowBackground", finalDefocus);
dofMaterial.SetTexture("_TapMedium", mediumRezWorkTexture);
Graphics.Blit(source, (!flag) ? destination : foregroundTexture, dofMaterial, visualize ? 2 : 0);
if (flag)
{
Graphics.Blit(foregroundTexture, source, dofMaterial, 5);
Downsample(source, mediumRezWorkTexture);
BlurFg(mediumRezWorkTexture, mediumRezWorkTexture, DofBlurriness.Low, 2, maxBlurSpread);
if (bokeh && (BokehDestination.Foreground & bokehDestination) != 0)
{
dofMaterial.SetVector("_Threshhold", new Vector4(bokehThresholdContrast * 0.5f, bokehThresholdLuminance, 0f, 0f));
Graphics.Blit(mediumRezWorkTexture, bokehSource2, dofMaterial, 11);
Graphics.Blit(mediumRezWorkTexture, lowRezWorkTexture);
BlurFg(lowRezWorkTexture, lowRezWorkTexture, bluriness, 1, maxBlurSpread * num);
}
else
{
BlurFg(mediumRezWorkTexture, lowRezWorkTexture, bluriness, 1, maxBlurSpread);
}
Graphics.Blit(lowRezWorkTexture, finalDefocus);
dofMaterial.SetTexture("_TapLowForeground", finalDefocus);
Graphics.Blit(source, destination, dofMaterial, visualize ? 1 : 4);
if (bokeh && (BokehDestination.Foreground & bokehDestination) != 0)
{
AddBokeh(bokehSource2, bokehSource, destination);
}
}
ReleaseTextures();
}
private void Blur(RenderTexture from, RenderTexture to, DofBlurriness iterations, int blurPass, float spread)
{
RenderTexture temporary = RenderTexture.GetTemporary(to.width, to.height);
if (iterations > DofBlurriness.Low)
{
BlurHex(from, to, blurPass, spread, temporary);
if (iterations > DofBlurriness.High)
{
dofBlurMaterial.SetVector("offsets", new Vector4(0f, spread * oneOverBaseSize, 0f, 0f));
Graphics.Blit(to, temporary, dofBlurMaterial, blurPass);
dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, 0f, 0f, 0f));
Graphics.Blit(temporary, to, dofBlurMaterial, blurPass);
}
}
else
{
dofBlurMaterial.SetVector("offsets", new Vector4(0f, spread * oneOverBaseSize, 0f, 0f));
Graphics.Blit(from, temporary, dofBlurMaterial, blurPass);
dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, 0f, 0f, 0f));
Graphics.Blit(temporary, to, dofBlurMaterial, blurPass);
}
RenderTexture.ReleaseTemporary(temporary);
}
private void BlurFg(RenderTexture from, RenderTexture to, DofBlurriness iterations, int blurPass, float spread)
{
dofBlurMaterial.SetTexture("_TapHigh", from);
RenderTexture temporary = RenderTexture.GetTemporary(to.width, to.height);
if (iterations > DofBlurriness.Low)
{
BlurHex(from, to, blurPass, spread, temporary);
if (iterations > DofBlurriness.High)
{
dofBlurMaterial.SetVector("offsets", new Vector4(0f, spread * oneOverBaseSize, 0f, 0f));
Graphics.Blit(to, temporary, dofBlurMaterial, blurPass);
dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, 0f, 0f, 0f));
Graphics.Blit(temporary, to, dofBlurMaterial, blurPass);
}
}
else
{
dofBlurMaterial.SetVector("offsets", new Vector4(0f, spread * oneOverBaseSize, 0f, 0f));
Graphics.Blit(from, temporary, dofBlurMaterial, blurPass);
dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, 0f, 0f, 0f));
Graphics.Blit(temporary, to, dofBlurMaterial, blurPass);
}
RenderTexture.ReleaseTemporary(temporary);
}
private void BlurHex(RenderTexture from, RenderTexture to, int blurPass, float spread, RenderTexture tmp)
{
dofBlurMaterial.SetVector("offsets", new Vector4(0f, spread * oneOverBaseSize, 0f, 0f));
Graphics.Blit(from, tmp, dofBlurMaterial, blurPass);
dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, 0f, 0f, 0f));
Graphics.Blit(tmp, to, dofBlurMaterial, blurPass);
dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, spread * oneOverBaseSize, 0f, 0f));
Graphics.Blit(to, tmp, dofBlurMaterial, blurPass);
dofBlurMaterial.SetVector("offsets", new Vector4(spread / widthOverHeight * oneOverBaseSize, (0f - spread) * oneOverBaseSize, 0f, 0f));
Graphics.Blit(tmp, to, dofBlurMaterial, blurPass);
}
private void Downsample(RenderTexture from, RenderTexture to)
{
dofMaterial.SetVector("_InvRenderTargetSize", new Vector4(1f / (1f * (float)to.width), 1f / (1f * (float)to.height), 0f, 0f));
Graphics.Blit(from, to, dofMaterial, SMOOTH_DOWNSAMPLE_PASS);
}
private void AddBokeh(RenderTexture bokehInfo, RenderTexture tempTex, RenderTexture finalTarget)
{
if (!bokehMaterial)
{
return;
}
Mesh[] meshes = Quads.GetMeshes(tempTex.width, tempTex.height);
RenderTexture.active = tempTex;
GL.Clear(false, true, new Color(0f, 0f, 0f, 0f));
GL.PushMatrix();
GL.LoadIdentity();
bokehInfo.filterMode = FilterMode.Point;
float num = (float)bokehInfo.width * 1f / ((float)bokehInfo.height * 1f);
float num2 = 2f / (1f * (float)bokehInfo.width);
num2 += bokehScale * maxBlurSpread * BOKEH_EXTRA_BLUR * oneOverBaseSize;
bokehMaterial.SetTexture("_Source", bokehInfo);
bokehMaterial.SetTexture("_MainTex", bokehTexture);
bokehMaterial.SetVector("_ArScale", new Vector4(num2, num2 * num, 0.5f, 0.5f * num));
bokehMaterial.SetFloat("_Intensity", bokehIntensity);
bokehMaterial.SetPass(0);
Mesh[] array = meshes;
foreach (Mesh mesh in array)
{
if ((bool)mesh)
{
Graphics.DrawMeshNow(mesh, Matrix4x4.identity);
}
}
GL.PopMatrix();
Graphics.Blit(tempTex, finalTarget, dofMaterial, 8);
bokehInfo.filterMode = FilterMode.Bilinear;
}
private void ReleaseTextures()
{
if ((bool)foregroundTexture)
{
RenderTexture.ReleaseTemporary(foregroundTexture);
}
if ((bool)finalDefocus)
{
RenderTexture.ReleaseTemporary(finalDefocus);
}
if ((bool)mediumRezWorkTexture)
{
RenderTexture.ReleaseTemporary(mediumRezWorkTexture);
}
if ((bool)lowRezWorkTexture)
{
RenderTexture.ReleaseTemporary(lowRezWorkTexture);
}
if ((bool)bokehSource)
{
RenderTexture.ReleaseTemporary(bokehSource);
}
if ((bool)bokehSource2)
{
RenderTexture.ReleaseTemporary(bokehSource2);
}
}
private void AllocateTextures(bool blurForeground, RenderTexture source, int divider, int lowTexDivider)
{
foregroundTexture = null;
if (blurForeground)
{
foregroundTexture = RenderTexture.GetTemporary(source.width, source.height, 0);
}
mediumRezWorkTexture = RenderTexture.GetTemporary(source.width / divider, source.height / divider, 0);
finalDefocus = RenderTexture.GetTemporary(source.width / divider, source.height / divider, 0);
lowRezWorkTexture = RenderTexture.GetTemporary(source.width / lowTexDivider, source.height / lowTexDivider, 0);
bokehSource = null;
bokehSource2 = null;
if (bokeh)
{
bokehSource = RenderTexture.GetTemporary(source.width / (lowTexDivider * bokehDownsample), source.height / (lowTexDivider * bokehDownsample), 0, RenderTextureFormat.ARGBHalf);
bokehSource2 = RenderTexture.GetTemporary(source.width / (lowTexDivider * bokehDownsample), source.height / (lowTexDivider * bokehDownsample), 0, RenderTextureFormat.ARGBHalf);
bokehSource.filterMode = FilterMode.Bilinear;
bokehSource2.filterMode = FilterMode.Bilinear;
RenderTexture.active = bokehSource2;
GL.Clear(false, true, new Color(0f, 0f, 0f, 0f));
}
source.filterMode = FilterMode.Bilinear;
finalDefocus.filterMode = FilterMode.Bilinear;
mediumRezWorkTexture.filterMode = FilterMode.Bilinear;
lowRezWorkTexture.filterMode = FilterMode.Bilinear;
if ((bool)foregroundTexture)
{
foregroundTexture.filterMode = FilterMode.Bilinear;
}
}
}
}