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

1184 lines
40 KiB
C#

using System;
using System.Runtime.InteropServices;
using UnityEngine;
[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
[AddComponentMenu("Image Effects/Sonic Ether/SEGI (Cascaded)")]
public class SEGICascaded : MonoBehaviour
{
[Serializable]
public enum VoxelResolution
{
low = 0x40,
high = 0x80
}
private enum RenderState
{
Voxelize = 0,
Bounce = 1
}
[StructLayout(LayoutKind.Sequential, Size = 1)]
private struct Pass
{
public static int DiffuseTrace = 0;
public static int BilateralBlur = 1;
public static int BlendWithScene = 2;
public static int TemporalBlend = 3;
public static int SpecularTrace = 4;
public static int GetCameraDepthTexture = 5;
public static int GetWorldNormals = 6;
public static int VisualizeGI = 7;
public static int WriteBlack = 8;
public static int VisualizeVoxels = 10;
public static int BilateralUpsample = 11;
}
public struct SystemSupported
{
public bool hdrTextures;
public bool rIntTextures;
public bool dx11;
public bool volumeTextures;
public bool postShader;
public bool sunDepthShader;
public bool voxelizationShader;
public bool tracingShader;
public bool fullFunctionality
{
get
{
if (hdrTextures && rIntTextures && dx11 && volumeTextures && postShader && sunDepthShader && voxelizationShader)
{
return tracingShader;
}
return false;
}
}
}
private class Clipmap
{
public Vector3 origin;
public Vector3 originDelta;
public Vector3 previousOrigin;
public float localScale;
public int resolution;
public RenderTexture volumeTexture0;
public FilterMode filterMode = FilterMode.Bilinear;
public RenderTextureFormat renderTextureFormat = RenderTextureFormat.ARGBHalf;
public void UpdateTextures()
{
if ((bool)volumeTexture0)
{
volumeTexture0.DiscardContents();
volumeTexture0.Release();
UnityEngine.Object.DestroyImmediate(volumeTexture0);
}
volumeTexture0 = new RenderTexture(resolution, resolution, 0, renderTextureFormat, RenderTextureReadWrite.Linear);
volumeTexture0.wrapMode = TextureWrapMode.Clamp;
volumeTexture0.isVolume = true;
volumeTexture0.volumeDepth = resolution;
volumeTexture0.enableRandomWrite = true;
volumeTexture0.filterMode = filterMode;
volumeTexture0.autoGenerateMips = false;
volumeTexture0.useMipMap = false;
volumeTexture0.Create();
volumeTexture0.hideFlags = HideFlags.HideAndDontSave;
}
public void CleanupTextures()
{
if ((bool)volumeTexture0)
{
volumeTexture0.DiscardContents();
volumeTexture0.Release();
UnityEngine.Object.DestroyImmediate(volumeTexture0);
}
}
}
private int updateGIcounter;
public int updateGIevery = 1;
public VoxelResolution voxelResolution = VoxelResolution.high;
public bool visualizeSunDepthTexture;
public bool visualizeGI;
public Light sun;
public LayerMask giCullingMask = int.MaxValue;
public float shadowSpaceSize = 50f;
[Range(0.01f, 1f)]
public float temporalBlendWeight = 0.1f;
public bool visualizeVoxels;
public bool updateGI = true;
public Color skyColor;
public float voxelSpaceSize = 25f;
public bool useBilateralFiltering;
[Range(0f, 2f)]
public int innerOcclusionLayers = 1;
public bool halfResolution;
public bool stochasticSampling = true;
public bool infiniteBounces;
public Transform followTransform;
[Range(1f, 128f)]
public int cones = 4;
[Range(1f, 32f)]
public int coneTraceSteps = 10;
[Range(0.1f, 2f)]
public float coneLength = 1f;
[Range(0.5f, 6f)]
public float coneWidth = 3.9f;
[Range(0f, 2f)]
public float occlusionStrength = 0.15f;
[Range(0f, 4f)]
public float nearOcclusionStrength = 0.5f;
[Range(0.001f, 4f)]
public float occlusionPower = 0.65f;
[Range(0f, 4f)]
public float coneTraceBias = 2.8f;
[Range(0f, 4f)]
public float nearLightGain = 0.36f;
[Range(0f, 4f)]
public float giGain = 1f;
[Range(0f, 4f)]
public float secondaryBounceGain = 0.9f;
[Range(0f, 16f)]
public float softSunlight;
[Range(0f, 8f)]
public float skyIntensity = 1f;
[Range(12f, 128f)]
public int reflectionSteps = 64;
[Range(0.001f, 4f)]
public float reflectionOcclusionPower = 1f;
[Range(0f, 1f)]
public float skyReflectionIntensity = 1f;
[Range(0.1f, 4f)]
public float farOcclusionStrength = 1f;
[Range(0.1f, 4f)]
public float farthestOcclusionStrength = 1f;
[Range(3f, 16f)]
public int secondaryCones = 6;
[Range(0.1f, 2f)]
public float secondaryOcclusionStrength = 0.27f;
public bool sphericalSkylight;
private object initChecker;
private Material material;
private Camera attachedCamera;
private Transform shadowCamTransform;
private Camera shadowCam;
private GameObject shadowCamGameObject;
private Texture2D[] blueNoise;
private int sunShadowResolution = 128;
private int prevSunShadowResolution;
private Shader sunDepthShader;
private float shadowSpaceDepthRatio = 10f;
private int frameCounter;
private RenderTexture sunDepthTexture;
private RenderTexture previousGIResult;
private RenderTexture previousDepth;
private RenderTexture integerVolume;
private RenderTexture dummyVoxelTextureAAScaled;
private RenderTexture dummyVoxelTextureFixed;
private Clipmap[] clipmaps;
private Clipmap[] irradianceClipmaps;
private bool notReadyToRender;
private Shader voxelizationShader;
private Shader voxelTracingShader;
private ComputeShader clearCompute;
private ComputeShader transferIntsCompute;
private ComputeShader mipFilterCompute;
private const int numClipmaps = 6;
private int clipmapCounter;
private int currentClipmapIndex;
private Camera voxelCamera;
private GameObject voxelCameraGO;
private GameObject leftViewPoint;
private GameObject topViewPoint;
private Vector3 voxelSpaceOrigin;
private Vector3 previousVoxelSpaceOrigin;
private Vector3 voxelSpaceOriginDelta;
private Quaternion rotationFront = new Quaternion(0f, 0f, 0f, 1f);
private Quaternion rotationLeft = new Quaternion(0f, 0.7f, 0f, 0.7f);
private Quaternion rotationTop = new Quaternion(0.7f, 0f, 0f, 0.7f);
private RenderState renderState;
public SystemSupported systemSupported;
public bool voxelAA;
[HideInInspector]
public bool doReflections
{
get
{
return false;
}
set
{
value = false;
}
}
private float voxelScaleFactor => (float)voxelResolution / 256f;
private int giRenderRes
{
get
{
if (!halfResolution)
{
return 1;
}
return 2;
}
}
public float vramUsage
{
get
{
if (!base.enabled)
{
return 0f;
}
long num = 0L;
if (sunDepthTexture != null)
{
num += sunDepthTexture.width * sunDepthTexture.height * 16;
}
if (previousGIResult != null)
{
num += previousGIResult.width * previousGIResult.height * 16 * 4;
}
if (previousDepth != null)
{
num += previousDepth.width * previousDepth.height * 32;
}
if (integerVolume != null)
{
num += integerVolume.width * integerVolume.height * integerVolume.volumeDepth * 32;
}
if (dummyVoxelTextureAAScaled != null)
{
num += dummyVoxelTextureAAScaled.width * dummyVoxelTextureAAScaled.height * 8;
}
if (dummyVoxelTextureFixed != null)
{
num += dummyVoxelTextureFixed.width * dummyVoxelTextureFixed.height * 8;
}
if (clipmaps != null)
{
for (int i = 0; i < 6; i++)
{
if (clipmaps[i] != null)
{
num += clipmaps[i].volumeTexture0.width * clipmaps[i].volumeTexture0.height * clipmaps[i].volumeTexture0.volumeDepth * 16 * 4;
}
}
}
return (float)num / 8388608f;
}
}
public bool gaussianMipFilter
{
get
{
return false;
}
set
{
value = false;
}
}
private int mipFilterKernel
{
get
{
if (!gaussianMipFilter)
{
return 0;
}
return 1;
}
}
private int dummyVoxelResolution => (int)voxelResolution * ((!voxelAA) ? 1 : 4);
public void ApplyPreset(SEGICascadedPreset preset)
{
voxelResolution = preset.voxelResolution;
voxelAA = preset.voxelAA;
innerOcclusionLayers = preset.innerOcclusionLayers;
infiniteBounces = preset.infiniteBounces;
temporalBlendWeight = preset.temporalBlendWeight;
useBilateralFiltering = preset.useBilateralFiltering;
halfResolution = preset.halfResolution;
stochasticSampling = preset.stochasticSampling;
doReflections = preset.doReflections;
cones = preset.cones;
coneTraceSteps = preset.coneTraceSteps;
coneLength = preset.coneLength;
coneWidth = preset.coneWidth;
coneTraceBias = preset.coneTraceBias;
occlusionStrength = preset.occlusionStrength;
nearOcclusionStrength = preset.nearOcclusionStrength;
occlusionPower = preset.occlusionPower;
nearLightGain = preset.nearLightGain;
giGain = preset.giGain;
secondaryBounceGain = preset.secondaryBounceGain;
reflectionSteps = preset.reflectionSteps;
reflectionOcclusionPower = preset.reflectionOcclusionPower;
skyReflectionIntensity = preset.skyReflectionIntensity;
gaussianMipFilter = preset.gaussianMipFilter;
farOcclusionStrength = preset.farOcclusionStrength;
farthestOcclusionStrength = preset.farthestOcclusionStrength;
secondaryCones = preset.secondaryCones;
secondaryOcclusionStrength = preset.secondaryOcclusionStrength;
}
private void Start()
{
InitCheck();
}
private void InitCheck()
{
if (initChecker == null)
{
Init();
}
}
private void CreateVolumeTextures()
{
if ((bool)integerVolume)
{
integerVolume.DiscardContents();
integerVolume.Release();
UnityEngine.Object.DestroyImmediate(integerVolume);
}
integerVolume = new RenderTexture((int)voxelResolution, (int)voxelResolution, 0, RenderTextureFormat.RInt, RenderTextureReadWrite.Linear);
integerVolume.isVolume = true;
integerVolume.volumeDepth = (int)voxelResolution;
integerVolume.enableRandomWrite = true;
integerVolume.filterMode = FilterMode.Point;
integerVolume.Create();
integerVolume.hideFlags = HideFlags.HideAndDontSave;
ResizeDummyTexture();
}
private void BuildClipmaps()
{
clipmaps = new Clipmap[6];
for (int i = 0; i < 6; i++)
{
clipmaps[i] = new Clipmap();
clipmaps[i].localScale = Mathf.Pow(2f, i);
clipmaps[i].resolution = (int)voxelResolution;
clipmaps[i].filterMode = FilterMode.Bilinear;
clipmaps[i].renderTextureFormat = RenderTextureFormat.ARGBHalf;
clipmaps[i].UpdateTextures();
}
irradianceClipmaps = new Clipmap[6];
for (int j = 0; j < 6; j++)
{
irradianceClipmaps[j] = new Clipmap();
irradianceClipmaps[j].localScale = Mathf.Pow(2f, j);
irradianceClipmaps[j].resolution = (int)voxelResolution;
irradianceClipmaps[j].filterMode = FilterMode.Point;
irradianceClipmaps[j].renderTextureFormat = RenderTextureFormat.ARGBHalf;
irradianceClipmaps[j].UpdateTextures();
}
}
private void ResizeDummyTexture()
{
if ((bool)dummyVoxelTextureAAScaled)
{
dummyVoxelTextureAAScaled.DiscardContents();
dummyVoxelTextureAAScaled.Release();
UnityEngine.Object.DestroyImmediate(dummyVoxelTextureAAScaled);
}
dummyVoxelTextureAAScaled = new RenderTexture(dummyVoxelResolution, dummyVoxelResolution, 0, RenderTextureFormat.R8);
dummyVoxelTextureAAScaled.Create();
dummyVoxelTextureAAScaled.hideFlags = HideFlags.HideAndDontSave;
if ((bool)dummyVoxelTextureFixed)
{
dummyVoxelTextureFixed.DiscardContents();
dummyVoxelTextureFixed.Release();
UnityEngine.Object.DestroyImmediate(dummyVoxelTextureFixed);
}
dummyVoxelTextureFixed = new RenderTexture((int)voxelResolution, (int)voxelResolution, 0, RenderTextureFormat.R8);
dummyVoxelTextureFixed.Create();
dummyVoxelTextureFixed.hideFlags = HideFlags.HideAndDontSave;
}
private void GetBlueNoiseTextures()
{
blueNoise = null;
blueNoise = new Texture2D[64];
for (int i = 0; i < 64; i++)
{
string text = "LDR_RGBA_" + i;
Texture2D texture2D = Resources.Load("Noise Textures/" + text) as Texture2D;
if (texture2D == null)
{
Debug.LogWarning("Unable to find noise texture \"Assets/SEGI/Resources/Noise Textures/" + text + "\" for SEGI!");
}
blueNoise[i] = texture2D;
}
}
private void Init()
{
sunDepthShader = Shader.Find("Hidden/SEGIRenderSunDepth_C");
clearCompute = Resources.Load("SEGIClear_C") as ComputeShader;
transferIntsCompute = Resources.Load("SEGITransferInts_C") as ComputeShader;
mipFilterCompute = Resources.Load("SEGIMipFilter_C") as ComputeShader;
voxelizationShader = Shader.Find("Hidden/SEGIVoxelizeScene_C");
voxelTracingShader = Shader.Find("Hidden/SEGITraceScene_C");
material = new Material(Shader.Find("Hidden/SEGI_C"));
material.hideFlags = HideFlags.HideAndDontSave;
attachedCamera = GetComponent<Camera>();
attachedCamera.depthTextureMode |= DepthTextureMode.Depth;
attachedCamera.depthTextureMode |= DepthTextureMode.DepthNormals;
attachedCamera.depthTextureMode |= DepthTextureMode.MotionVectors;
GameObject gameObject = GameObject.Find("SEGI_SHADOWCAM");
if (!gameObject)
{
shadowCamGameObject = new GameObject("SEGI_SHADOWCAM");
shadowCam = shadowCamGameObject.AddComponent<Camera>();
shadowCamGameObject.hideFlags = HideFlags.HideAndDontSave;
shadowCam.enabled = false;
shadowCam.depth = attachedCamera.depth - 1f;
shadowCam.orthographic = true;
shadowCam.orthographicSize = shadowSpaceSize;
shadowCam.clearFlags = CameraClearFlags.Color;
shadowCam.backgroundColor = new Color(0f, 0f, 0f, 1f);
shadowCam.farClipPlane = shadowSpaceSize * 2f * shadowSpaceDepthRatio;
shadowCam.cullingMask = giCullingMask;
shadowCam.useOcclusionCulling = false;
shadowCamTransform = shadowCamGameObject.transform;
}
else
{
shadowCamGameObject = gameObject;
shadowCam = gameObject.GetComponent<Camera>();
shadowCamTransform = shadowCamGameObject.transform;
}
GameObject gameObject2 = GameObject.Find("SEGI_VOXEL_CAMERA");
if ((bool)gameObject2)
{
UnityEngine.Object.DestroyImmediate(gameObject2);
}
voxelCameraGO = new GameObject("SEGI_VOXEL_CAMERA");
voxelCameraGO.hideFlags = HideFlags.HideAndDontSave;
voxelCamera = voxelCameraGO.AddComponent<Camera>();
voxelCamera.enabled = false;
voxelCamera.orthographic = true;
voxelCamera.orthographicSize = voxelSpaceSize * 0.5f;
voxelCamera.nearClipPlane = 0f;
voxelCamera.farClipPlane = voxelSpaceSize;
voxelCamera.depth = -2f;
voxelCamera.renderingPath = RenderingPath.Forward;
voxelCamera.clearFlags = CameraClearFlags.Color;
voxelCamera.backgroundColor = Color.black;
voxelCamera.useOcclusionCulling = false;
GameObject gameObject3 = GameObject.Find("SEGI_LEFT_VOXEL_VIEW");
if ((bool)gameObject3)
{
UnityEngine.Object.DestroyImmediate(gameObject3);
}
leftViewPoint = new GameObject("SEGI_LEFT_VOXEL_VIEW");
leftViewPoint.hideFlags = HideFlags.HideAndDontSave;
GameObject gameObject4 = GameObject.Find("SEGI_TOP_VOXEL_VIEW");
if ((bool)gameObject4)
{
UnityEngine.Object.DestroyImmediate(gameObject4);
}
topViewPoint = new GameObject("SEGI_TOP_VOXEL_VIEW");
topViewPoint.hideFlags = HideFlags.HideAndDontSave;
if ((bool)sunDepthTexture)
{
sunDepthTexture.DiscardContents();
sunDepthTexture.Release();
UnityEngine.Object.DestroyImmediate(sunDepthTexture);
}
sunDepthTexture = new RenderTexture(sunShadowResolution, sunShadowResolution, 16, RenderTextureFormat.RHalf, RenderTextureReadWrite.Linear);
sunDepthTexture.wrapMode = TextureWrapMode.Clamp;
sunDepthTexture.filterMode = FilterMode.Point;
sunDepthTexture.Create();
sunDepthTexture.hideFlags = HideFlags.HideAndDontSave;
CreateVolumeTextures();
BuildClipmaps();
GetBlueNoiseTextures();
initChecker = new object();
}
private void CheckSupport()
{
systemSupported.hdrTextures = SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf);
systemSupported.rIntTextures = SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.RInt);
systemSupported.dx11 = SystemInfo.graphicsShaderLevel >= 50 && SystemInfo.supportsComputeShaders;
systemSupported.volumeTextures = SystemInfo.supports3DTextures;
systemSupported.postShader = material.shader.isSupported;
systemSupported.sunDepthShader = sunDepthShader.isSupported;
systemSupported.voxelizationShader = voxelizationShader.isSupported;
systemSupported.tracingShader = voxelTracingShader.isSupported;
if (!systemSupported.fullFunctionality)
{
Debug.LogWarning("SEGI is not supported on the current platform. Check for shader compile errors in SEGI/Resources");
base.enabled = false;
}
}
private void OnDrawGizmosSelected()
{
if (base.enabled)
{
Color color = Gizmos.color;
Gizmos.color = new Color(1f, 0.25f, 0f, 0.5f);
float localScale = clipmaps[5].localScale;
Gizmos.DrawCube(clipmaps[0].origin, new Vector3(voxelSpaceSize * localScale, voxelSpaceSize * localScale, voxelSpaceSize * localScale));
Gizmos.color = new Color(1f, 0f, 0f, 0.1f);
Gizmos.color = color;
}
}
private void CleanupTexture(ref RenderTexture texture)
{
if ((bool)texture)
{
texture.DiscardContents();
texture.Release();
UnityEngine.Object.DestroyImmediate(texture);
}
}
private void CleanupTextures()
{
CleanupTexture(ref sunDepthTexture);
CleanupTexture(ref previousGIResult);
CleanupTexture(ref previousDepth);
CleanupTexture(ref integerVolume);
CleanupTexture(ref dummyVoxelTextureAAScaled);
CleanupTexture(ref dummyVoxelTextureFixed);
if (clipmaps == null)
{
return;
}
for (int i = 0; i < 6; i++)
{
if (clipmaps[0] != null)
{
clipmaps[0].CleanupTextures();
}
}
}
private void Cleanup()
{
UnityEngine.Object.DestroyImmediate(material);
UnityEngine.Object.DestroyImmediate(voxelCameraGO);
UnityEngine.Object.DestroyImmediate(leftViewPoint);
UnityEngine.Object.DestroyImmediate(topViewPoint);
UnityEngine.Object.DestroyImmediate(shadowCamGameObject);
initChecker = null;
CleanupTextures();
}
private void OnEnable()
{
InitCheck();
ResizeRenderTextures();
CheckSupport();
}
private void OnDisable()
{
Cleanup();
}
private void ResizeRenderTextures()
{
if ((bool)previousGIResult)
{
previousGIResult.DiscardContents();
previousGIResult.Release();
UnityEngine.Object.DestroyImmediate(previousGIResult);
}
int width = ((attachedCamera.pixelWidth == 0) ? 2 : attachedCamera.pixelWidth);
int height = ((attachedCamera.pixelHeight == 0) ? 2 : attachedCamera.pixelHeight);
previousGIResult = new RenderTexture(width, height, 0, RenderTextureFormat.ARGBHalf);
previousGIResult.wrapMode = TextureWrapMode.Clamp;
previousGIResult.filterMode = FilterMode.Bilinear;
previousGIResult.Create();
previousGIResult.hideFlags = HideFlags.HideAndDontSave;
if ((bool)previousDepth)
{
previousDepth.DiscardContents();
previousDepth.Release();
UnityEngine.Object.DestroyImmediate(previousDepth);
}
previousDepth = new RenderTexture(width, height, 0, RenderTextureFormat.RFloat, RenderTextureReadWrite.Linear);
previousDepth.wrapMode = TextureWrapMode.Clamp;
previousDepth.filterMode = FilterMode.Bilinear;
previousDepth.Create();
previousDepth.hideFlags = HideFlags.HideAndDontSave;
}
private void ResizeSunShadowBuffer()
{
if ((bool)sunDepthTexture)
{
sunDepthTexture.DiscardContents();
sunDepthTexture.Release();
UnityEngine.Object.DestroyImmediate(sunDepthTexture);
}
sunDepthTexture = new RenderTexture(sunShadowResolution, sunShadowResolution, 16, RenderTextureFormat.RHalf, RenderTextureReadWrite.Linear);
sunDepthTexture.wrapMode = TextureWrapMode.Clamp;
sunDepthTexture.filterMode = FilterMode.Point;
sunDepthTexture.Create();
sunDepthTexture.hideFlags = HideFlags.HideAndDontSave;
}
private void Update()
{
if (!notReadyToRender)
{
if (previousGIResult == null)
{
ResizeRenderTextures();
}
if (previousGIResult.width != attachedCamera.pixelWidth || previousGIResult.height != attachedCamera.pixelHeight)
{
ResizeRenderTextures();
}
if (sunShadowResolution != prevSunShadowResolution)
{
ResizeSunShadowBuffer();
}
prevSunShadowResolution = sunShadowResolution;
if (clipmaps[0].resolution != (int)voxelResolution)
{
clipmaps[0].resolution = (int)voxelResolution;
clipmaps[0].UpdateTextures();
}
if (dummyVoxelTextureAAScaled.width != dummyVoxelResolution)
{
ResizeDummyTexture();
}
}
}
private Matrix4x4 TransformViewMatrix(Matrix4x4 mat)
{
if (SystemInfo.usesReversedZBuffer)
{
mat[2, 0] = 0f - mat[2, 0];
mat[2, 1] = 0f - mat[2, 1];
mat[2, 2] = 0f - mat[2, 2];
mat[2, 3] = 0f - mat[2, 3];
}
return mat;
}
private int SelectCascadeBinary(int c)
{
float num = (float)c + 0.01f;
int num2 = 0;
for (int i = 1; i < 6; i++)
{
float num3 = Mathf.Pow(2f, i);
num2 += Mathf.CeilToInt(num / num3 % 1f - (num3 - 1f) / num3);
}
return num2;
}
private void OnPreRender()
{
InitCheck();
if (notReadyToRender)
{
return;
}
updateGIcounter++;
if (!updateGI || (updateGIevery > 1 && updateGIcounter < updateGIevery))
{
return;
}
updateGIcounter = 0;
RenderTexture active = RenderTexture.active;
Shader.SetGlobalInt("SEGIVoxelAA", voxelAA ? 3 : 0);
LightShadows shadows = LightShadows.None;
if (sun != null)
{
shadows = sun.shadows;
sun.shadows = LightShadows.None;
}
if (renderState == RenderState.Voxelize)
{
currentClipmapIndex = SelectCascadeBinary(clipmapCounter);
Clipmap clipmap = clipmaps[currentClipmapIndex];
Clipmap clipmap2 = null;
if (currentClipmapIndex != 0)
{
clipmap2 = clipmaps[currentClipmapIndex - 1];
}
float num = voxelSpaceSize * clipmap.localScale;
float num2 = num / 8f;
Vector3 vector = ((!followTransform) ? (base.transform.position + base.transform.forward * num / 4f) : followTransform.position);
clipmap.previousOrigin = clipmap.origin;
clipmap.origin = new Vector3(Mathf.Round(vector.x / num2) * num2, Mathf.Round(vector.y / num2) * num2, Mathf.Round(vector.z / num2) * num2);
clipmap.originDelta = clipmap.origin - clipmap.previousOrigin;
Shader.SetGlobalVector("SEGIVoxelSpaceOriginDelta", clipmap.originDelta / (voxelSpaceSize * clipmap.localScale));
Vector3 vector2 = Vector3.zero;
float w = 0f;
if (currentClipmapIndex != 0)
{
vector2 = (clipmap2.origin - clipmap.origin) / num;
w = clipmap2.localScale / clipmap.localScale;
}
Shader.SetGlobalVector("SEGIClipmapOverlap", new Vector4(vector2.x, vector2.y, vector2.z, w));
for (int i = 1; i < 6; i++)
{
Vector3 zero = Vector3.zero;
float num3 = 1f;
zero = (clipmaps[i].origin - clipmaps[0].origin) / (voxelSpaceSize * clipmaps[i].localScale);
num3 = clipmaps[0].localScale / clipmaps[i].localScale;
Shader.SetGlobalVector("SEGIClipTransform" + i, new Vector4(zero.x, zero.y, zero.z, num3));
}
voxelCamera.enabled = false;
voxelCamera.orthographic = true;
voxelCamera.orthographicSize = num * 0.5f;
voxelCamera.nearClipPlane = 0f;
voxelCamera.farClipPlane = num;
voxelCamera.depth = -2f;
voxelCamera.renderingPath = RenderingPath.Forward;
voxelCamera.clearFlags = CameraClearFlags.Color;
voxelCamera.backgroundColor = Color.black;
voxelCamera.cullingMask = giCullingMask;
voxelCameraGO.transform.position = clipmap.origin - Vector3.forward * num * 0.5f;
voxelCameraGO.transform.rotation = rotationFront;
leftViewPoint.transform.position = clipmap.origin + Vector3.left * num * 0.5f;
leftViewPoint.transform.rotation = rotationLeft;
topViewPoint.transform.position = clipmap.origin + Vector3.up * num * 0.5f;
topViewPoint.transform.rotation = rotationTop;
Shader.SetGlobalMatrix("WorldToGI", shadowCam.worldToCameraMatrix);
Shader.SetGlobalMatrix("GIToWorld", shadowCam.cameraToWorldMatrix);
Shader.SetGlobalMatrix("GIProjection", shadowCam.projectionMatrix);
Shader.SetGlobalMatrix("GIProjectionInverse", shadowCam.projectionMatrix.inverse);
Shader.SetGlobalMatrix("WorldToCamera", attachedCamera.worldToCameraMatrix);
Shader.SetGlobalFloat("GIDepthRatio", shadowSpaceDepthRatio);
Matrix4x4 matrix4x = TransformViewMatrix(voxelCamera.transform.worldToLocalMatrix);
Matrix4x4 matrix4x2 = TransformViewMatrix(leftViewPoint.transform.worldToLocalMatrix);
Matrix4x4 matrix4x3 = TransformViewMatrix(topViewPoint.transform.worldToLocalMatrix);
Shader.SetGlobalMatrix("SEGIVoxelViewFront", matrix4x);
Shader.SetGlobalMatrix("SEGIVoxelViewLeft", matrix4x2);
Shader.SetGlobalMatrix("SEGIVoxelViewTop", matrix4x3);
Shader.SetGlobalMatrix("SEGIWorldToVoxel", voxelCamera.worldToCameraMatrix);
Shader.SetGlobalMatrix("SEGIVoxelProjection", voxelCamera.projectionMatrix);
Shader.SetGlobalMatrix("SEGIVoxelProjectionInverse", voxelCamera.projectionMatrix.inverse);
Shader.SetGlobalMatrix("SEGIVoxelVPFront", GL.GetGPUProjectionMatrix(voxelCamera.projectionMatrix, renderIntoTexture: true) * matrix4x);
Shader.SetGlobalMatrix("SEGIVoxelVPLeft", GL.GetGPUProjectionMatrix(voxelCamera.projectionMatrix, renderIntoTexture: true) * matrix4x2);
Shader.SetGlobalMatrix("SEGIVoxelVPTop", GL.GetGPUProjectionMatrix(voxelCamera.projectionMatrix, renderIntoTexture: true) * matrix4x3);
Shader.SetGlobalMatrix("SEGIWorldToVoxel" + currentClipmapIndex, voxelCamera.worldToCameraMatrix);
Shader.SetGlobalMatrix("SEGIVoxelProjection" + currentClipmapIndex, voxelCamera.projectionMatrix);
Matrix4x4 value = shadowCam.projectionMatrix * shadowCam.worldToCameraMatrix * voxelCamera.cameraToWorldMatrix;
Shader.SetGlobalMatrix("SEGIVoxelToGIProjection", value);
Shader.SetGlobalVector("SEGISunlightVector", sun ? Vector3.Normalize(sun.transform.forward) : Vector3.up);
Shader.SetGlobalInt("SEGIVoxelResolution", (int)voxelResolution);
Shader.SetGlobalColor("GISunColor", (sun == null) ? Color.black : new Color(Mathf.Pow(sun.color.r, 2.2f), Mathf.Pow(sun.color.g, 2.2f), Mathf.Pow(sun.color.b, 2.2f), Mathf.Pow(sun.intensity, 2.2f)));
Shader.SetGlobalColor("SEGISkyColor", new Color(Mathf.Pow(skyColor.r * skyIntensity * 0.5f, 2.2f), Mathf.Pow(skyColor.g * skyIntensity * 0.5f, 2.2f), Mathf.Pow(skyColor.b * skyIntensity * 0.5f, 2.2f), Mathf.Pow(skyColor.a, 2.2f)));
Shader.SetGlobalFloat("GIGain", giGain);
Shader.SetGlobalFloat("SEGISecondaryBounceGain", infiniteBounces ? secondaryBounceGain : 0f);
Shader.SetGlobalFloat("SEGISoftSunlight", softSunlight);
Shader.SetGlobalInt("SEGISphericalSkylight", sphericalSkylight ? 1 : 0);
Shader.SetGlobalInt("SEGIInnerOcclusionLayers", innerOcclusionLayers);
if (sun != null)
{
shadowCam.cullingMask = giCullingMask;
Vector3 position = clipmap.origin + Vector3.Normalize(-sun.transform.forward) * shadowSpaceSize * 0.5f * shadowSpaceDepthRatio;
shadowCamTransform.position = position;
shadowCamTransform.LookAt(clipmap.origin, Vector3.up);
shadowCam.renderingPath = RenderingPath.Forward;
shadowCam.depthTextureMode |= DepthTextureMode.None;
shadowCam.orthographicSize = shadowSpaceSize;
shadowCam.farClipPlane = shadowSpaceSize * 2f * shadowSpaceDepthRatio;
Graphics.SetRenderTarget(sunDepthTexture);
shadowCam.SetTargetBuffers(sunDepthTexture.colorBuffer, sunDepthTexture.depthBuffer);
shadowCam.RenderWithShader(sunDepthShader, "");
Shader.SetGlobalTexture("SEGISunDepth", sunDepthTexture);
}
clearCompute.SetTexture(0, "RG0", integerVolume);
clearCompute.SetInt("Res", clipmap.resolution);
clearCompute.Dispatch(0, clipmap.resolution / 16, clipmap.resolution / 16, 1);
Shader.SetGlobalTexture("SEGICurrentIrradianceVolume", irradianceClipmaps[currentClipmapIndex].volumeTexture0);
Graphics.SetRandomWriteTarget(1, integerVolume);
voxelCamera.targetTexture = dummyVoxelTextureAAScaled;
voxelCamera.RenderWithShader(voxelizationShader, "");
Graphics.ClearRandomWriteTargets();
transferIntsCompute.SetTexture(0, "Result", clipmap.volumeTexture0);
transferIntsCompute.SetTexture(0, "RG0", integerVolume);
transferIntsCompute.SetInt("VoxelAA", voxelAA ? 3 : 0);
transferIntsCompute.SetInt("Resolution", clipmap.resolution);
transferIntsCompute.Dispatch(0, clipmap.resolution / 16, clipmap.resolution / 16, 1);
for (int j = 1; j < 6; j++)
{
Clipmap clipmap3 = clipmaps[j - 1];
Clipmap clipmap4 = clipmaps[j];
Vector3 zero2 = Vector3.zero;
float num4 = 0f;
zero2 = (clipmap3.origin - clipmap4.origin) / (clipmap4.localScale * voxelSpaceSize);
num4 = clipmap3.localScale / clipmap4.localScale;
mipFilterCompute.SetTexture(0, "Source", clipmap3.volumeTexture0);
mipFilterCompute.SetTexture(0, "Destination", clipmap4.volumeTexture0);
mipFilterCompute.SetVector("ClipmapOverlap", new Vector4(zero2.x, zero2.y, zero2.z, num4));
mipFilterCompute.SetInt("destinationRes", clipmap4.resolution);
mipFilterCompute.Dispatch(0, clipmap4.resolution / 16, clipmap4.resolution / 16, 1);
}
for (int k = 0; k < 6; k++)
{
Shader.SetGlobalTexture("SEGIVolumeLevel" + k, clipmaps[k].volumeTexture0);
}
if (infiniteBounces)
{
renderState = RenderState.Bounce;
}
else
{
clipmapCounter++;
if (clipmapCounter >= (int)Mathf.Pow(2f, 6f))
{
clipmapCounter = 0;
}
}
}
else if (renderState == RenderState.Bounce)
{
Vector3 zero3 = Vector3.zero;
zero3 = (clipmaps[currentClipmapIndex].origin - clipmaps[0].origin) / (voxelSpaceSize * clipmaps[currentClipmapIndex].localScale);
float w2 = 1f / clipmaps[currentClipmapIndex].localScale;
Shader.SetGlobalVector("SEGICurrentClipTransform", new Vector4(zero3.x, zero3.y, zero3.z, w2));
clearCompute.SetTexture(0, "RG0", integerVolume);
clearCompute.SetInt("Res", clipmaps[currentClipmapIndex].resolution);
clearCompute.Dispatch(0, (int)voxelResolution / 16, (int)voxelResolution / 16, 1);
if (currentClipmapIndex <= 2)
{
Shader.SetGlobalInt("SEGISecondaryCones", secondaryCones);
Shader.SetGlobalFloat("SEGISecondaryOcclusionStrength", secondaryOcclusionStrength);
Graphics.SetRandomWriteTarget(1, integerVolume);
voxelCamera.targetTexture = dummyVoxelTextureFixed;
voxelCamera.RenderWithShader(voxelTracingShader, "");
Graphics.ClearRandomWriteTargets();
transferIntsCompute.SetTexture(1, "Result", irradianceClipmaps[currentClipmapIndex].volumeTexture0);
transferIntsCompute.SetTexture(1, "RG0", integerVolume);
transferIntsCompute.SetInt("Resolution", (int)voxelResolution);
transferIntsCompute.Dispatch(1, (int)voxelResolution / 16, (int)voxelResolution / 16, 1);
}
clipmapCounter++;
if (clipmapCounter >= (int)Mathf.Pow(2f, 6f))
{
clipmapCounter = 0;
}
renderState = RenderState.Voxelize;
}
Matrix4x4 value2 = voxelCamera.projectionMatrix * voxelCamera.worldToCameraMatrix * shadowCam.cameraToWorldMatrix;
Shader.SetGlobalMatrix("GIToVoxelProjection", value2);
RenderTexture.active = active;
if (sun != null)
{
sun.shadows = shadows;
}
}
[ImageEffectOpaque]
private void OnRenderImage(RenderTexture source, RenderTexture destination)
{
if (notReadyToRender)
{
Graphics.Blit(source, destination);
return;
}
Shader.SetGlobalFloat("SEGIVoxelScaleFactor", voxelScaleFactor);
material.SetMatrix("CameraToWorld", attachedCamera.cameraToWorldMatrix);
material.SetMatrix("WorldToCamera", attachedCamera.worldToCameraMatrix);
material.SetMatrix("ProjectionMatrixInverse", attachedCamera.projectionMatrix.inverse);
material.SetMatrix("ProjectionMatrix", attachedCamera.projectionMatrix);
material.SetInt("FrameSwitch", frameCounter);
Shader.SetGlobalInt("SEGIFrameSwitch", frameCounter);
material.SetVector("CameraPosition", base.transform.position);
material.SetFloat("DeltaTime", Time.deltaTime);
material.SetInt("StochasticSampling", stochasticSampling ? 1 : 0);
material.SetInt("TraceDirections", cones);
material.SetInt("TraceSteps", coneTraceSteps);
material.SetFloat("TraceLength", coneLength);
material.SetFloat("ConeSize", coneWidth);
material.SetFloat("OcclusionStrength", occlusionStrength);
material.SetFloat("OcclusionPower", occlusionPower);
material.SetFloat("ConeTraceBias", coneTraceBias);
material.SetFloat("GIGain", giGain);
material.SetFloat("NearLightGain", nearLightGain);
material.SetFloat("NearOcclusionStrength", nearOcclusionStrength);
material.SetInt("DoReflections", doReflections ? 1 : 0);
material.SetInt("HalfResolution", halfResolution ? 1 : 0);
material.SetInt("ReflectionSteps", reflectionSteps);
material.SetFloat("ReflectionOcclusionPower", reflectionOcclusionPower);
material.SetFloat("SkyReflectionIntensity", skyReflectionIntensity);
material.SetFloat("FarOcclusionStrength", farOcclusionStrength);
material.SetFloat("FarthestOcclusionStrength", farthestOcclusionStrength);
material.SetTexture("NoiseTexture", blueNoise[frameCounter]);
material.SetFloat("BlendWeight", temporalBlendWeight);
if (visualizeVoxels)
{
Graphics.Blit(source, destination, material, Pass.VisualizeVoxels);
return;
}
RenderTexture temporary = RenderTexture.GetTemporary(source.width / giRenderRes, source.height / giRenderRes, 0, RenderTextureFormat.ARGBHalf);
RenderTexture temporary2 = RenderTexture.GetTemporary(source.width / giRenderRes, source.height / giRenderRes, 0, RenderTextureFormat.ARGBHalf);
RenderTexture renderTexture = null;
if (doReflections)
{
renderTexture = RenderTexture.GetTemporary(source.width, source.height, 0, RenderTextureFormat.ARGBHalf);
}
RenderTexture temporary3 = RenderTexture.GetTemporary(source.width / giRenderRes, source.height / giRenderRes, 0, RenderTextureFormat.RFloat, RenderTextureReadWrite.Linear);
temporary3.filterMode = FilterMode.Point;
RenderTexture temporary4 = RenderTexture.GetTemporary(source.width / giRenderRes, source.height / giRenderRes, 0, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
temporary4.filterMode = FilterMode.Point;
Graphics.Blit(source, temporary3, material, Pass.GetCameraDepthTexture);
material.SetTexture("CurrentDepth", temporary3);
Graphics.Blit(source, temporary4, material, Pass.GetWorldNormals);
material.SetTexture("CurrentNormal", temporary4);
material.SetTexture("PreviousGITexture", previousGIResult);
Shader.SetGlobalTexture("PreviousGITexture", previousGIResult);
material.SetTexture("PreviousDepth", previousDepth);
Graphics.Blit(source, temporary2, material, Pass.DiffuseTrace);
if (doReflections)
{
Graphics.Blit(source, renderTexture, material, Pass.SpecularTrace);
material.SetTexture("Reflections", renderTexture);
}
if (useBilateralFiltering && temporalBlendWeight >= 0.99999f)
{
material.SetVector("Kernel", new Vector2(0f, 1f));
Graphics.Blit(temporary2, temporary, material, Pass.BilateralBlur);
material.SetVector("Kernel", new Vector2(1f, 0f));
Graphics.Blit(temporary, temporary2, material, Pass.BilateralBlur);
material.SetVector("Kernel", new Vector2(0f, 1f));
Graphics.Blit(temporary2, temporary, material, Pass.BilateralBlur);
material.SetVector("Kernel", new Vector2(1f, 0f));
Graphics.Blit(temporary, temporary2, material, Pass.BilateralBlur);
}
if (giRenderRes == 2)
{
RenderTexture.ReleaseTemporary(temporary);
RenderTexture temporary5 = RenderTexture.GetTemporary(source.width, source.height, 0, RenderTextureFormat.ARGBHalf);
RenderTexture temporary6 = RenderTexture.GetTemporary(source.width, source.height, 0, RenderTextureFormat.ARGBHalf);
temporary2.filterMode = FilterMode.Point;
Graphics.Blit(temporary2, temporary6);
RenderTexture.ReleaseTemporary(temporary2);
temporary6.filterMode = FilterMode.Point;
temporary5.filterMode = FilterMode.Point;
material.SetVector("Kernel", new Vector2(1f, 0f));
Graphics.Blit(temporary6, temporary5, material, Pass.BilateralUpsample);
material.SetVector("Kernel", new Vector2(0f, 1f));
RenderTexture temporary7 = RenderTexture.GetTemporary(source.width, source.height, 0, RenderTextureFormat.ARGBHalf);
RenderTexture temporary8 = RenderTexture.GetTemporary(source.width, source.height, 0, RenderTextureFormat.ARGBHalf);
material.SetVector("Kernel", new Vector2(0f, 1f));
Graphics.Blit(temporary5, temporary8, material, Pass.BilateralBlur);
material.SetVector("Kernel", new Vector2(1f, 0f));
Graphics.Blit(temporary8, temporary7, material, Pass.BilateralBlur);
material.SetVector("Kernel", new Vector2(0f, 2f));
Graphics.Blit(temporary7, temporary8, material, Pass.BilateralBlur);
material.SetVector("Kernel", new Vector2(2f, 0f));
Graphics.Blit(temporary8, temporary7, material, Pass.BilateralBlur);
material.SetTexture("BlurredGI", temporary7);
if (temporalBlendWeight < 1f)
{
Graphics.Blit(temporary5, temporary6);
Graphics.Blit(temporary6, temporary5, material, Pass.TemporalBlend);
Graphics.Blit(temporary5, previousGIResult);
Graphics.Blit(source, previousDepth, material, Pass.GetCameraDepthTexture);
if (useBilateralFiltering)
{
material.SetVector("Kernel", new Vector2(0f, 1f));
Graphics.Blit(temporary5, temporary6, material, Pass.BilateralBlur);
material.SetVector("Kernel", new Vector2(1f, 0f));
Graphics.Blit(temporary6, temporary5, material, Pass.BilateralBlur);
material.SetVector("Kernel", new Vector2(0f, 1f));
Graphics.Blit(temporary5, temporary6, material, Pass.BilateralBlur);
material.SetVector("Kernel", new Vector2(1f, 0f));
Graphics.Blit(temporary6, temporary5, material, Pass.BilateralBlur);
}
}
material.SetTexture("GITexture", temporary5);
Graphics.Blit(source, destination, material, visualizeGI ? Pass.VisualizeGI : Pass.BlendWithScene);
RenderTexture.ReleaseTemporary(temporary7);
RenderTexture.ReleaseTemporary(temporary8);
RenderTexture.ReleaseTemporary(temporary5);
RenderTexture.ReleaseTemporary(temporary6);
}
else
{
if (temporalBlendWeight < 1f)
{
RenderTexture temporary9 = RenderTexture.GetTemporary(source.width, source.height, 0, RenderTextureFormat.ARGBHalf);
RenderTexture temporary10 = RenderTexture.GetTemporary(source.width, source.height, 0, RenderTextureFormat.ARGBHalf);
material.SetVector("Kernel", new Vector2(0f, 1f));
Graphics.Blit(temporary2, temporary10, material, Pass.BilateralBlur);
material.SetVector("Kernel", new Vector2(1f, 0f));
Graphics.Blit(temporary10, temporary9, material, Pass.BilateralBlur);
material.SetVector("Kernel", new Vector2(0f, 2f));
Graphics.Blit(temporary9, temporary10, material, Pass.BilateralBlur);
material.SetVector("Kernel", new Vector2(2f, 0f));
Graphics.Blit(temporary10, temporary9, material, Pass.BilateralBlur);
material.SetTexture("BlurredGI", temporary9);
Graphics.Blit(temporary2, temporary, material, Pass.TemporalBlend);
Graphics.Blit(temporary, previousGIResult);
Graphics.Blit(source, previousDepth, material, Pass.GetCameraDepthTexture);
if (useBilateralFiltering)
{
material.SetVector("Kernel", new Vector2(0f, 1f));
Graphics.Blit(temporary, temporary2, material, Pass.BilateralBlur);
material.SetVector("Kernel", new Vector2(1f, 0f));
Graphics.Blit(temporary2, temporary, material, Pass.BilateralBlur);
material.SetVector("Kernel", new Vector2(0f, 1f));
Graphics.Blit(temporary, temporary2, material, Pass.BilateralBlur);
material.SetVector("Kernel", new Vector2(1f, 0f));
Graphics.Blit(temporary2, temporary, material, Pass.BilateralBlur);
}
RenderTexture.ReleaseTemporary(temporary9);
RenderTexture.ReleaseTemporary(temporary10);
}
material.SetTexture("GITexture", (temporalBlendWeight < 1f) ? temporary : temporary2);
Graphics.Blit(source, destination, material, visualizeGI ? Pass.VisualizeGI : Pass.BlendWithScene);
RenderTexture.ReleaseTemporary(temporary);
RenderTexture.ReleaseTemporary(temporary2);
}
RenderTexture.ReleaseTemporary(temporary3);
RenderTexture.ReleaseTemporary(temporary4);
if (visualizeSunDepthTexture)
{
Graphics.Blit(sunDepthTexture, destination);
}
if (doReflections)
{
RenderTexture.ReleaseTemporary(renderTexture);
}
material.SetMatrix("ProjectionPrev", attachedCamera.projectionMatrix);
material.SetMatrix("ProjectionPrevInverse", attachedCamera.projectionMatrix.inverse);
material.SetMatrix("WorldToCameraPrev", attachedCamera.worldToCameraMatrix);
material.SetMatrix("CameraToWorldPrev", attachedCamera.cameraToWorldMatrix);
material.SetVector("CameraPositionPrev", base.transform.position);
frameCounter = (frameCounter + 1) % 64;
}
}