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(); _frustumJitter = GetComponent(); } 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(); } if (_frustumJitter == null) { _frustumJitter = GetComponent(); } } private void OnPreRender() { if (_camera == null) { _camera = GetComponent(); } if (_frustumJitter == null) { _frustumJitter = GetComponent(); } 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(); } if (_frustumJitter == null) { _frustumJitter = GetComponent(); } 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 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]); } } } }