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(); 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(); 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(); 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(); 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; } }