Files
2026-03-04 10:03:45 +08:00

174 lines
5.7 KiB
C#

using UnityEngine;
namespace Artngame.SKYMASTER
{
[RequireComponent(typeof(VelocityBuffer))]
public class CloudTemporalAntiAliasing : EffectBase
{
public enum Neighborhood
{
MinMax3x3 = 0,
MinMax3x3Rounded = 1,
MinMax4TapVarying = 2
}
public float blendAlpha;
private static RenderBuffer[] mrt = new RenderBuffer[2];
private Camera _camera;
private VelocityBuffer _velocityBuffer;
public Shader reprojectionShader;
private Material reprojectionMaterial;
private RenderTexture[,] reprojectionBuffer;
private int[] reprojectionIndex = new int[2] { -1, -1 };
public Neighborhood neighborhood = Neighborhood.MinMax3x3Rounded;
public bool unjitterColorSamples = true;
public bool unjitterNeighborhood;
public bool unjitterReprojection;
public bool useYCoCg;
public bool useClipping = true;
public bool useDilation = true;
public bool useMotionBlur;
public bool useOptimizations = true;
[Range(0f, 1f)]
public float feedbackMin = 0.88f;
[Range(0f, 1f)]
public float feedbackMax = 0.97f;
public float motionBlurStrength = 1f;
public bool motionBlurIgnoreFF;
public void SetCamera(Camera camera)
{
_camera = camera;
}
private void Reset()
{
_velocityBuffer = GetComponent<VelocityBuffer>();
reprojectionShader = Shader.Find("Playdead/Post/TemporalReprojection");
}
private void Clear()
{
EnsureArray(ref reprojectionIndex, 2, 0);
reprojectionIndex[0] = -1;
reprojectionIndex[1] = -1;
}
private void Awake()
{
Reset();
Clear();
}
private void Resolve(RenderTexture source, RenderTexture destination)
{
EnsureArray(ref reprojectionBuffer, 2, 2);
EnsureArray(ref reprojectionIndex, 2, -1);
EnsureMaterial(ref reprojectionMaterial, reprojectionShader);
if (reprojectionMaterial == null)
{
Graphics.Blit(source, destination);
return;
}
int num = ((_camera.stereoActiveEye == Camera.MonoOrStereoscopicEye.Right) ? 1 : 0);
int width = source.width;
int height = source.height;
if (EnsureRenderTarget(ref reprojectionBuffer[num, 0], width, height, RenderTextureFormat.ARGB32, FilterMode.Bilinear, 0, source.antiAliasing))
{
Clear();
}
if (EnsureRenderTarget(ref reprojectionBuffer[num, 1], width, height, RenderTextureFormat.ARGB32, FilterMode.Bilinear, 0, source.antiAliasing))
{
Clear();
}
bool flag = !_camera.stereoEnabled;
EnsureKeyword(reprojectionMaterial, "CAMERA_PERSPECTIVE", !_camera.orthographic);
EnsureKeyword(reprojectionMaterial, "CAMERA_ORTHOGRAPHIC", _camera.orthographic);
EnsureKeyword(reprojectionMaterial, "MINMAX_3X3", neighborhood == Neighborhood.MinMax3x3);
EnsureKeyword(reprojectionMaterial, "MINMAX_3X3_ROUNDED", neighborhood == Neighborhood.MinMax3x3Rounded);
EnsureKeyword(reprojectionMaterial, "MINMAX_4TAP_VARYING", neighborhood == Neighborhood.MinMax4TapVarying);
EnsureKeyword(reprojectionMaterial, "UNJITTER_COLORSAMPLES", unjitterColorSamples);
EnsureKeyword(reprojectionMaterial, "UNJITTER_NEIGHBORHOOD", unjitterNeighborhood);
EnsureKeyword(reprojectionMaterial, "UNJITTER_REPROJECTION", unjitterReprojection);
EnsureKeyword(reprojectionMaterial, "USE_YCOCG", useYCoCg);
EnsureKeyword(reprojectionMaterial, "USE_CLIPPING", useClipping);
EnsureKeyword(reprojectionMaterial, "USE_DILATION", useDilation);
EnsureKeyword(reprojectionMaterial, "USE_MOTION_BLUR", useMotionBlur && flag);
EnsureKeyword(reprojectionMaterial, "USE_MOTION_BLUR_NEIGHBORMAX", _velocityBuffer.activeVelocityNeighborMax != null);
EnsureKeyword(reprojectionMaterial, "USE_OPTIMIZATIONS", useOptimizations);
if (reprojectionIndex[num] == -1)
{
reprojectionIndex[num] = 0;
reprojectionBuffer[num, reprojectionIndex[num]].DiscardContents();
Graphics.Blit(source, reprojectionBuffer[num, reprojectionIndex[num]]);
}
int num2 = reprojectionIndex[num];
int num3 = (reprojectionIndex[num] + 1) % 2;
Vector4 zero = Vector4.zero;
reprojectionMaterial.SetVector("_JitterUV", zero);
reprojectionMaterial.SetTexture("_VelocityBuffer", _velocityBuffer.activeVelocityBuffer);
reprojectionMaterial.SetTexture("_VelocityNeighborMax", _velocityBuffer.activeVelocityNeighborMax);
reprojectionMaterial.SetTexture("_MainTex", source);
reprojectionMaterial.SetTexture("_PrevTex", reprojectionBuffer[num, num2]);
reprojectionMaterial.SetFloat("_FeedbackMin", feedbackMin);
reprojectionMaterial.SetFloat("_FeedbackMax", feedbackMax);
reprojectionMaterial.SetFloat("_MotionScale", motionBlurStrength * (motionBlurIgnoreFF ? Mathf.Min(1f, 1f / _velocityBuffer.timeScale) : 1f));
reprojectionMaterial.SetFloat("blendAlpha", blendAlpha);
mrt[0] = reprojectionBuffer[num, num3].colorBuffer;
mrt[1] = destination.colorBuffer;
Graphics.SetRenderTarget(mrt, source.depthBuffer);
reprojectionMaterial.SetPass(0);
reprojectionBuffer[num, num3].DiscardContents();
DrawFullscreenQuad();
reprojectionIndex[num] = num3;
}
public void TemporalAntiAliasing(RenderTexture source, RenderTexture destination)
{
if (Application.isPlaying)
{
if (destination != null && source.antiAliasing == destination.antiAliasing)
{
Resolve(source, destination);
return;
}
RenderTexture temporary = RenderTexture.GetTemporary(source.width, source.height, 0, source.format, RenderTextureReadWrite.Default, source.antiAliasing);
Resolve(source, temporary);
Graphics.Blit(temporary, destination);
RenderTexture.ReleaseTemporary(temporary);
}
}
private void OnApplicationQuit()
{
if (reprojectionBuffer != null)
{
ReleaseRenderTarget(ref reprojectionBuffer[0, 0]);
ReleaseRenderTarget(ref reprojectionBuffer[0, 1]);
ReleaseRenderTarget(ref reprojectionBuffer[1, 0]);
ReleaseRenderTarget(ref reprojectionBuffer[1, 1]);
}
}
}
}