318 lines
13 KiB
C#
318 lines
13 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Runtime;
|
|
using System.Runtime.InteropServices;
|
|
using System.Linq;
|
|
using System;
|
|
using UnityEngine;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
|
|
namespace UnityEngine.Rendering.Universal
|
|
{
|
|
public class SLZGlobals
|
|
{
|
|
|
|
|
|
static SLZGlobals s_Instance;
|
|
// Blue Noise
|
|
private ComputeBuffer BlueNoiseCB;
|
|
private ComputeBuffer HiZDimBuffer;
|
|
private float[] BlueNoiseDim; // width, height, depth, current slice index
|
|
private bool hasSetBNTextures;
|
|
#if UNITY_EDITOR
|
|
private static long framecount = 0;
|
|
private static double timeSinceStartup = 0.0;
|
|
#endif
|
|
//private int HiZDimBufferID = Shader.PropertyToID("HiZDimBuffer");
|
|
private int HiZMipNumID = Shader.PropertyToID("_HiZHighestMip");
|
|
private int HiZDimID = Shader.PropertyToID("_HiZDim");
|
|
private int SSRConstantsID = Shader.PropertyToID("SSRConstants");
|
|
private int CameraOpaqueTextureID = Shader.PropertyToID("_CameraOpaqueTexture");
|
|
private int PrevHiZ0TextureID = Shader.PropertyToID("_PrevHiZ0Texture");
|
|
public int opaqueTexID { get { return CameraOpaqueTextureID; } }
|
|
public int prevHiZTexID { get { return PrevHiZ0TextureID; } }
|
|
|
|
public GlobalKeyword HiZEnabledKW { get; private set; }
|
|
public GlobalKeyword HiZMinMaxKW { get; private set; }
|
|
public GlobalKeyword SSREnabledKW { get; private set; }
|
|
|
|
public SLZPerCameraRTStorage PerCameraOpaque;
|
|
public SLZPerCameraRTStorage PerCameraPrevHiZ;
|
|
|
|
private ComputeBuffer SSRGlobalCB;
|
|
|
|
private double extraSmoothedDT = 0.01111;
|
|
|
|
|
|
private SLZGlobals()
|
|
{
|
|
BlueNoiseCB = new ComputeBuffer(8, sizeof(float), ComputeBufferType.Constant);
|
|
BlueNoiseDim = new float[8];
|
|
hasSetBNTextures = false;
|
|
SSRGlobalCB = new ComputeBuffer(2, 4*sizeof(float), ComputeBufferType.Constant);
|
|
HiZDimBuffer = new ComputeBuffer(15, Marshal.SizeOf<Vector4>());
|
|
SSREnabledKW = GlobalKeyword.Create("_SLZ_SSR_ENABLED");
|
|
HiZEnabledKW = GlobalKeyword.Create("_HIZ_ENABLED");
|
|
HiZMinMaxKW = GlobalKeyword.Create("_HIZ_MIN_MAX_ENABLED");
|
|
PerCameraOpaque = new SLZPerCameraRTStorage();
|
|
PerCameraPrevHiZ = new SLZPerCameraRTStorage();
|
|
|
|
}
|
|
public static SLZGlobals instance
|
|
{
|
|
get
|
|
{
|
|
if (s_Instance == null)
|
|
{
|
|
s_Instance = new SLZGlobals();
|
|
}
|
|
return s_Instance;
|
|
}
|
|
|
|
}
|
|
|
|
public void SetHiZSSRKeyWords(bool enableSSR, bool requireHiZ, bool requireMinMax)
|
|
{
|
|
Shader.SetKeyword(SSREnabledKW, enableSSR);
|
|
Shader.SetKeyword(HiZEnabledKW, requireHiZ);
|
|
Shader.SetKeyword(HiZMinMaxKW, requireMinMax);
|
|
}
|
|
|
|
public void SetHiZGlobal(int numMips, Vector4 dim)
|
|
{
|
|
//HiZDimBuffer.SetData(data);
|
|
//Shader.SetGlobalBuffer(HiZDimBufferID, HiZDimBuffer);
|
|
Shader.SetGlobalInt(HiZMipNumID, numMips);
|
|
Shader.SetGlobalVector(HiZDimID, dim);
|
|
//Shader.SetKeyword(HiZMinMaxKW, minmax);
|
|
}
|
|
|
|
public void SetSSRGlobals(int maxSteps, int minMip, float hitRadius, float temporalWeight, float fov, int screenHeight)
|
|
{
|
|
/*
|
|
* 0 float _SSRHitRadius;
|
|
* 1 float _SSREdgeFade;
|
|
* 2 int _SSRSteps;
|
|
* 3 none
|
|
*/
|
|
Span<float> SSRGlobalArray = stackalloc float[8];
|
|
//SSRGlobalArray[0] = 1.0f / (1.0f + hitRadius);//hitRadius;
|
|
//SSRGlobalArray[1] = -cameraNear / (cameraFar - cameraNear) * (hitRadius * SSRGlobalArray[0]);
|
|
SSRGlobalArray[0] = hitRadius;
|
|
extraSmoothedDT = 0.95 * extraSmoothedDT + 0.05 * Time.smoothDeltaTime;
|
|
float framerateConst = 1.0f / (float)extraSmoothedDT * (1.0f / 90.0f);
|
|
float expConst = Mathf.Exp(-framerateConst);
|
|
float FRTemporal = (Mathf.Exp(-framerateConst * temporalWeight) - expConst) * (1.0f / (1.0f - expConst));
|
|
//Debug.Log(FRTemporal);
|
|
SSRGlobalArray[1] = Mathf.Clamp(1.0f - temporalWeight, 0.0078f, 1.0f); //Mathf.Clamp(FRTemporal, 0.0078f, 1.0f);
|
|
SSRGlobalArray[2] = maxSteps;
|
|
SSRGlobalArray[3] = BitConverter.Int32BitsToSingle(minMip);
|
|
float halfTan = Mathf.Tan(Mathf.Deg2Rad * (fov * 0.5f));
|
|
SSRGlobalArray[4] = halfTan / (0.5f * (float)screenHeight); // rcp(0.5*_ScreenParams.y * UNITY_MATRIX_P._m11)
|
|
SSRGlobalCB.SetData<float>(SSRGlobalArray);
|
|
Shader.SetGlobalConstantBuffer(SSRConstantsID, SSRGlobalCB, 0, 8 * sizeof(float));
|
|
}
|
|
|
|
public void SetSSRGlobalsCmd(ref CommandBuffer cmd, int maxSteps, int minMip, float hitRadius, float temporalWeight, float fov, int screenHeight)
|
|
{
|
|
|
|
Span<float> SSRGlobalArray = stackalloc float[8];
|
|
//SSRGlobalArray[0] = 1.0f / (1.0f + hitRadius);//hitRadius;
|
|
//SSRGlobalArray[1] = -cameraNear / (cameraFar - cameraNear) * (hitRadius * SSRGlobalArray[0]);
|
|
SSRGlobalArray[0] = hitRadius;
|
|
extraSmoothedDT = 0.95 * extraSmoothedDT + 0.05 * Time.smoothDeltaTime;
|
|
float framerateConst = 1.0f / (float)extraSmoothedDT * (1.0f / 90.0f);
|
|
float expConst = Mathf.Exp(-framerateConst);
|
|
float FRTemporal = (Mathf.Exp(-framerateConst * temporalWeight) - expConst) * (1.0f / (1.0f - expConst));
|
|
//Debug.Log(FRTemporal);
|
|
SSRGlobalArray[1] = Mathf.Clamp(1.0f - temporalWeight, 0.0078f, 1.0f); //Mathf.Clamp(FRTemporal, 0.0078f, 1.0f);
|
|
SSRGlobalArray[2] = maxSteps;
|
|
SSRGlobalArray[3] = BitConverter.Int32BitsToSingle(minMip);
|
|
float halfTan = Mathf.Tan(Mathf.Deg2Rad * (fov * 0.5f));
|
|
SSRGlobalArray[4] = halfTan / (0.5f * (float)screenHeight); // rcp(0.5*_ScreenParams.y * UNITY_MATRIX_P._m11)
|
|
cmd.SetGlobalConstantBuffer(SSRGlobalCB, SSRConstantsID, 0, 8 * sizeof(float));
|
|
}
|
|
|
|
|
|
public void SetBlueNoiseGlobals(Texture2DArray BlueNoiseRGBA, Texture2DArray BlueNoiseR)
|
|
{
|
|
if (BlueNoiseRGBA != null)
|
|
{
|
|
BlueNoiseDim[0] = BlueNoiseRGBA.width;
|
|
BlueNoiseDim[1] = BlueNoiseRGBA.height;
|
|
BlueNoiseDim[2] = BlueNoiseRGBA.depth;
|
|
BlueNoiseDim[3] = (float) Random.Range(0, BlueNoiseRGBA.width);
|
|
BlueNoiseDim[4] = (float) Random.Range(0, BlueNoiseRGBA.height);
|
|
#if UNITY_EDITOR
|
|
if (!EditorApplication.isPlaying)
|
|
{
|
|
if (timeSinceStartup != EditorApplication.timeSinceStartup)
|
|
{
|
|
timeSinceStartup = EditorApplication.timeSinceStartup;
|
|
framecount++;
|
|
}
|
|
BlueNoiseDim[3] = (int)(framecount % BlueNoiseRGBA.depth);
|
|
//Debug.Log(BlueNoiseDim[3]);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
BlueNoiseDim[3] = Mathf.Abs((int)(Time.renderedFrameCount % BlueNoiseRGBA.depth));
|
|
}
|
|
if (BlueNoiseCB != null)
|
|
{
|
|
BlueNoiseCB.SetData(BlueNoiseDim);
|
|
Shader.SetGlobalConstantBuffer("BlueNoiseDim", BlueNoiseCB, 0, 16);
|
|
}
|
|
if (!hasSetBNTextures)
|
|
{
|
|
Shader.SetGlobalTexture("_BlueNoiseRGBA", BlueNoiseRGBA);
|
|
Shader.SetGlobalTexture("_BlueNoiseR", BlueNoiseR);
|
|
hasSetBNTextures = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void UpdateBlueNoiseFrame()
|
|
{
|
|
if (BlueNoiseCB != null)
|
|
{
|
|
long depth = (long)BlueNoiseDim[2];
|
|
#if UNITY_EDITOR
|
|
if (!EditorApplication.isPlaying)
|
|
{
|
|
BlueNoiseDim[3] = (int)((Screen.currentResolution.refreshRate * EditorApplication.timeSinceStartup) % depth);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
BlueNoiseDim[3] = (int)((Time.timeSinceLevelLoadAsDouble * Screen.currentResolution.refreshRate) % depth);
|
|
}
|
|
BlueNoiseCB.SetData(BlueNoiseDim);
|
|
Shader.SetGlobalConstantBuffer("BlueNoiseDim", BlueNoiseCB, 0, 16);
|
|
}
|
|
}
|
|
|
|
|
|
int purgeCounter = 0;
|
|
const int maxCount = 900;
|
|
public void RemoveTempRTStupid()
|
|
{
|
|
purgeCounter++;
|
|
if (purgeCounter > maxCount)
|
|
{
|
|
PerCameraOpaque.RemoveAllNull();
|
|
PerCameraPrevHiZ.RemoveAllNull();
|
|
purgeCounter = 0;
|
|
}
|
|
}
|
|
|
|
public static void Dispose()
|
|
{
|
|
if (s_Instance != null)
|
|
{
|
|
if (s_Instance.SSRGlobalCB != null)
|
|
{
|
|
s_Instance.SSRGlobalCB.Dispose();
|
|
s_Instance.SSRGlobalCB = null;
|
|
}
|
|
if (s_Instance.BlueNoiseCB != null)
|
|
{
|
|
s_Instance.BlueNoiseCB.Dispose();
|
|
s_Instance.BlueNoiseCB = null;
|
|
}
|
|
if (s_Instance.HiZDimBuffer != null)
|
|
{
|
|
s_Instance.HiZDimBuffer.Dispose();
|
|
s_Instance.HiZDimBuffer = null;
|
|
}
|
|
|
|
if (s_Instance.PerCameraOpaque != null)
|
|
{
|
|
s_Instance.PerCameraOpaque.Dispose();
|
|
}
|
|
if (s_Instance.PerCameraPrevHiZ != null)
|
|
{
|
|
s_Instance.PerCameraPrevHiZ.Dispose();
|
|
}
|
|
|
|
}
|
|
s_Instance = null;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public class SLZGlobalsSetPass : ScriptableRenderPass
|
|
{
|
|
private bool enableSSR;
|
|
private bool requireHiZ;
|
|
private bool requireMinMax;
|
|
|
|
private float ssrHitRadius;
|
|
private int ssrMaxSteps;
|
|
private int ssrMinMip;
|
|
private float cameraNear;
|
|
private float cameraFar;
|
|
private Camera camera;
|
|
private RTPermanentHandle prevOpaque;
|
|
private RTPermanentHandle prevHiZ;
|
|
public SLZGlobalsSetPass(RenderPassEvent evt)
|
|
{
|
|
renderPassEvent = evt;
|
|
}
|
|
public void Setup(CameraData camData)
|
|
{
|
|
enableSSR = camData.enableSSR;
|
|
requireHiZ = camData.requiresDepthPyramid;
|
|
requireMinMax = camData.requiresMinMaxDepthPyr;
|
|
|
|
ssrHitRadius = camData.SSRHitRadius;
|
|
ssrMaxSteps = camData.maxSSRSteps;
|
|
ssrMinMip = camData.SSRMinMip;
|
|
cameraNear = camData.camera.nearClipPlane;
|
|
cameraFar = camData.camera.farClipPlane;
|
|
|
|
prevOpaque = SLZGlobals.instance.PerCameraOpaque.GetHandle(camData.camera);
|
|
prevHiZ = SLZGlobals.instance.PerCameraPrevHiZ.GetHandle(camData.camera);
|
|
|
|
//Debug.Log("Setup for " + camData.camera.name);
|
|
}
|
|
|
|
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
|
|
{
|
|
ConfigureClear(ClearFlag.None, Color.black);
|
|
}
|
|
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
|
|
{
|
|
CommandBuffer cmd = CommandBufferPool.Get();
|
|
Camera cam = renderingData.cameraData.camera;
|
|
//cmd.SetGlobalTexture(SLZGlobals.instance.opaqueTexID, prevOpaque.Identifier());
|
|
//cmd.SetGlobalTexture(SLZGlobals.instance.prevHiZTexID, Texture2D.whiteTexture);
|
|
//cmd.SetGlobalTexture(SLZGlobals.instance.prevHiZTexID, prevHiZ.Identifier());
|
|
//Debug.Log("Execute for " + cam.name + " " + SLZGlobals.instance.opaqueTexID + " " + prevOpaque.Identifier());
|
|
using (new ProfilingScope(cmd, ProfilingSampler.Get(URPProfileId.SetSLZGlobals)))
|
|
{
|
|
|
|
if (enableSSR)
|
|
{
|
|
// Hack to tell unity to store previous frame object to world vectors...
|
|
// Not used by SRP to enable motion vectors or depth but somehow still necessary :(
|
|
renderingData.cameraData.camera.depthTextureMode |= DepthTextureMode.MotionVectors | DepthTextureMode.Depth;
|
|
|
|
cmd.SetGlobalTexture(SLZGlobals.instance.opaqueTexID, prevOpaque.renderTexture);
|
|
cmd.SetGlobalTexture(SLZGlobals.instance.prevHiZTexID, prevHiZ.renderTexture);
|
|
}
|
|
|
|
//SLZGlobals.instance.SetSSRGlobalsCmd(ref cmd, ssrMinMip, ssrMaxSteps, ssrHitRadius, cameraNear, cameraFar);
|
|
cmd.SetKeyword(SLZGlobals.instance.SSREnabledKW, enableSSR);
|
|
cmd.SetKeyword(SLZGlobals.instance.HiZEnabledKW, requireHiZ);
|
|
cmd.SetKeyword(SLZGlobals.instance.HiZMinMaxKW, requireMinMax);
|
|
}
|
|
context.ExecuteCommandBuffer(cmd);
|
|
CommandBufferPool.Release(cmd);
|
|
}
|
|
}
|
|
}
|