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

275 lines
8.4 KiB
C#

using System.Collections.Generic;
using UnityEngine;
namespace Artngame.SKYMASTER
{
[ExecuteInEditMode]
[RequireComponent(typeof(Camera), typeof(FrustumJitter))]
public class VelocityBuffer : EffectBase
{
public enum NeighborMaxSupport
{
TileSize10 = 0,
TileSize20 = 1,
TileSize40 = 2
}
private const RenderTextureFormat velocityFormat = RenderTextureFormat.RGFloat;
private Camera _camera;
private FrustumJitter _frustumJitter;
public Shader velocityShader;
private Material velocityMaterial;
private RenderTexture[] velocityBuffer;
private RenderTexture[] velocityNeighborMax;
private bool[] paramInitialized;
private Vector4[] paramProjectionExtents;
private Matrix4x4[] paramCurrV;
private Matrix4x4[] paramCurrVP;
private Matrix4x4[] paramPrevVP;
private Matrix4x4[] paramPrevVP_NoFlip;
private int activeEyeIndex = -1;
public bool neighborMaxGen;
public NeighborMaxSupport neighborMaxSupport = NeighborMaxSupport.TileSize20;
private float timeScaleNextFrame;
public RenderTexture activeVelocityBuffer
{
get
{
if (activeEyeIndex == -1)
{
return null;
}
return velocityBuffer[activeEyeIndex];
}
}
public RenderTexture activeVelocityNeighborMax
{
get
{
if (activeEyeIndex == -1)
{
return null;
}
return velocityNeighborMax[activeEyeIndex];
}
}
public float timeScale { get; private set; }
private void Reset()
{
_camera = GetComponent<Camera>();
_frustumJitter = GetComponent<FrustumJitter>();
}
private void Clear()
{
EnsureArray(ref paramInitialized, 2, initialValue: false);
paramInitialized[0] = false;
paramInitialized[1] = false;
}
private void Awake()
{
Reset();
Clear();
}
private void Start()
{
timeScaleNextFrame = Time.timeScale;
if (_camera == null)
{
_camera = GetComponent<Camera>();
}
if (_frustumJitter == null)
{
_frustumJitter = GetComponent<FrustumJitter>();
}
}
private void OnPreRender()
{
if (_camera == null)
{
_camera = GetComponent<Camera>();
}
if (_frustumJitter == null)
{
_frustumJitter = GetComponent<FrustumJitter>();
}
EnsureDepthTexture(_camera);
}
private void OnPostRender()
{
EnsureArray(ref velocityBuffer, 2);
EnsureArray(ref velocityNeighborMax, 2);
EnsureArray(ref paramInitialized, 2, initialValue: false);
EnsureArray(ref paramProjectionExtents, 2);
EnsureArray(ref paramCurrV, 2);
EnsureArray(ref paramCurrVP, 2);
EnsureArray(ref paramPrevVP, 2);
EnsureArray(ref paramPrevVP_NoFlip, 2);
EnsureMaterial(ref velocityMaterial, velocityShader);
if (velocityMaterial == null)
{
return;
}
timeScale = timeScaleNextFrame;
timeScaleNextFrame = ((Time.timeScale == 0f) ? timeScaleNextFrame : Time.timeScale);
if (_camera == null)
{
_camera = GetComponent<Camera>();
}
if (_frustumJitter == null)
{
_frustumJitter = GetComponent<FrustumJitter>();
}
int num = ((_camera.stereoActiveEye == Camera.MonoOrStereoscopicEye.Right) ? 1 : 0);
int pixelWidth = _camera.pixelWidth;
int pixelHeight = _camera.pixelHeight;
if (EnsureRenderTarget(ref velocityBuffer[num], pixelWidth, pixelHeight, RenderTextureFormat.RGFloat, FilterMode.Point, 16))
{
Clear();
}
EnsureKeyword(velocityMaterial, "CAMERA_PERSPECTIVE", !_camera.orthographic);
EnsureKeyword(velocityMaterial, "CAMERA_ORTHOGRAPHIC", _camera.orthographic);
EnsureKeyword(velocityMaterial, "TILESIZE_10", neighborMaxSupport == NeighborMaxSupport.TileSize10);
EnsureKeyword(velocityMaterial, "TILESIZE_20", neighborMaxSupport == NeighborMaxSupport.TileSize20);
EnsureKeyword(velocityMaterial, "TILESIZE_40", neighborMaxSupport == NeighborMaxSupport.TileSize40);
if (_camera.stereoEnabled)
{
for (int i = 0; i != 2; i++)
{
Camera.StereoscopicEye eye = (Camera.StereoscopicEye)i;
Matrix4x4 stereoViewMatrix = _camera.GetStereoViewMatrix(eye);
Matrix4x4 gPUProjectionMatrix = GL.GetGPUProjectionMatrix(_camera.GetStereoProjectionMatrix(eye), renderIntoTexture: true);
Matrix4x4 gPUProjectionMatrix2 = GL.GetGPUProjectionMatrix(_camera.GetStereoProjectionMatrix(eye), renderIntoTexture: false);
Matrix4x4 matrix4x = (paramInitialized[i] ? paramCurrV[i] : stereoViewMatrix);
paramInitialized[i] = true;
paramProjectionExtents[i] = _camera.GetProjectionExtents(eye);
paramCurrV[i] = stereoViewMatrix;
paramCurrVP[i] = gPUProjectionMatrix * stereoViewMatrix;
paramPrevVP[i] = gPUProjectionMatrix * matrix4x;
paramPrevVP_NoFlip[i] = gPUProjectionMatrix2 * matrix4x;
}
}
else
{
Matrix4x4 worldToCameraMatrix = _camera.worldToCameraMatrix;
Matrix4x4 gPUProjectionMatrix3 = GL.GetGPUProjectionMatrix(_camera.projectionMatrix, renderIntoTexture: true);
Matrix4x4 gPUProjectionMatrix4 = GL.GetGPUProjectionMatrix(_camera.projectionMatrix, renderIntoTexture: false);
Matrix4x4 matrix4x2 = (paramInitialized[0] ? paramCurrV[0] : worldToCameraMatrix);
paramInitialized[0] = true;
paramProjectionExtents[0] = (_frustumJitter.enabled ? _camera.GetProjectionExtents(_frustumJitter.activeSample.x, _frustumJitter.activeSample.y) : _camera.GetProjectionExtents());
paramCurrV[0] = worldToCameraMatrix;
paramCurrVP[0] = gPUProjectionMatrix3 * worldToCameraMatrix;
paramPrevVP[0] = gPUProjectionMatrix3 * matrix4x2;
paramPrevVP_NoFlip[0] = gPUProjectionMatrix4 * matrix4x2;
}
RenderTexture active = RenderTexture.active;
RenderTexture.active = velocityBuffer[num];
GL.Clear(clearDepth: true, clearColor: true, Color.black);
velocityMaterial.SetVectorArray("_ProjectionExtents", paramProjectionExtents);
velocityMaterial.SetMatrixArray("_CurrV", paramCurrV);
velocityMaterial.SetMatrixArray("_CurrVP", paramCurrVP);
velocityMaterial.SetMatrixArray("_PrevVP", paramPrevVP);
velocityMaterial.SetMatrixArray("_PrevVP_NoFlip", paramPrevVP_NoFlip);
velocityMaterial.SetPass(0);
DrawFullscreenQuad();
List<VelocityBufferTag> activeObjects = VelocityBufferTag.activeObjects;
int j = 0;
for (int count = activeObjects.Count; j != count; j++)
{
VelocityBufferTag velocityBufferTag = activeObjects[j];
if (velocityBufferTag != null && velocityBufferTag.rendering && velocityBufferTag.mesh != null)
{
velocityMaterial.SetMatrix("_CurrM", velocityBufferTag.localToWorldCurr);
velocityMaterial.SetMatrix("_PrevM", velocityBufferTag.localToWorldPrev);
velocityMaterial.SetPass((!velocityBufferTag.meshSmrActive) ? 1 : 2);
for (int k = 0; k != velocityBufferTag.mesh.subMeshCount; k++)
{
Graphics.DrawMeshNow(velocityBufferTag.mesh, Matrix4x4.identity, k);
}
}
}
if (neighborMaxGen)
{
int num2 = 1;
switch (neighborMaxSupport)
{
case NeighborMaxSupport.TileSize10:
num2 = 10;
break;
case NeighborMaxSupport.TileSize20:
num2 = 20;
break;
case NeighborMaxSupport.TileSize40:
num2 = 40;
break;
}
int num3 = pixelWidth / num2;
int num4 = pixelHeight / num2;
EnsureRenderTarget(ref velocityNeighborMax[num], num3, num4, RenderTextureFormat.RGFloat, FilterMode.Bilinear);
RenderTexture renderTexture = (RenderTexture.active = RenderTexture.GetTemporary(num3, num4, 0, RenderTextureFormat.RGFloat));
velocityMaterial.SetTexture("_VelocityTex", velocityBuffer[num]);
velocityMaterial.SetVector("_VelocityTex_TexelSize", new Vector4(1f / (float)pixelWidth, 1f / (float)pixelHeight, 0f, 0f));
velocityMaterial.SetPass(3);
DrawFullscreenQuad();
RenderTexture.active = velocityNeighborMax[num];
velocityMaterial.SetTexture("_VelocityTex", renderTexture);
velocityMaterial.SetVector("_VelocityTex_TexelSize", new Vector4(1f / (float)num3, 1f / (float)num4, 0f, 0f));
velocityMaterial.SetPass(4);
DrawFullscreenQuad();
RenderTexture.ReleaseTemporary(renderTexture);
}
else
{
ReleaseRenderTarget(ref velocityNeighborMax[0]);
ReleaseRenderTarget(ref velocityNeighborMax[1]);
}
RenderTexture.active = active;
activeEyeIndex = num;
}
private void OnApplicationQuit()
{
if (velocityBuffer != null)
{
if (velocityBuffer.Length != 0)
{
ReleaseRenderTarget(ref velocityBuffer[0]);
}
if (velocityBuffer.Length > 1)
{
ReleaseRenderTarget(ref velocityBuffer[1]);
}
}
if (velocityNeighborMax != null)
{
ReleaseRenderTarget(ref velocityNeighborMax[0]);
ReleaseRenderTarget(ref velocityNeighborMax[1]);
}
}
}
}