using System; using System.Collections.Generic; using UltimateWater.Internal; using UnityEngine; using UnityEngine.Rendering; namespace UltimateWater { public sealed class DynamicWater : WaterModule { [Serializable] public class Data { public int Antialiasing = 1; public LayerMask CustomEffectsLayerMask = -1; } private class Renderers { public readonly List LocalDisplacement = new List(); public readonly List LocalDisplacementMask = new List(); public readonly List LocalFoam = new List(); public readonly List LocalDiffuse = new List(); public void Add(T renderer) where T : IDynamicWaterEffects { ILocalDisplacementRenderer localDisplacementRenderer = renderer as ILocalDisplacementRenderer; ILocalDisplacementMaskRenderer localDisplacementMaskRenderer = renderer as ILocalDisplacementMaskRenderer; ILocalFoamRenderer localFoamRenderer = renderer as ILocalFoamRenderer; ILocalDiffuseRenderer localDiffuseRenderer = renderer as ILocalDiffuseRenderer; IWavesInteractive wavesInteractive = renderer as IWavesInteractive; if (localDisplacementRenderer != null) { LocalDisplacement.Add(localDisplacementRenderer); } if (localDisplacementMaskRenderer != null) { LocalDisplacementMask.Add(localDisplacementMaskRenderer); } if (localFoamRenderer != null) { LocalFoam.Add(localFoamRenderer); } if (wavesInteractive != null) { Interactions.Add(wavesInteractive); } if (localDiffuseRenderer != null) { LocalDiffuse.Add(localDiffuseRenderer); } } public void Remove(T renderer) where T : IDynamicWaterEffects { ILocalDisplacementRenderer localDisplacementRenderer = renderer as ILocalDisplacementRenderer; ILocalDisplacementMaskRenderer localDisplacementMaskRenderer = renderer as ILocalDisplacementMaskRenderer; ILocalFoamRenderer localFoamRenderer = renderer as ILocalFoamRenderer; ILocalDiffuseRenderer localDiffuseRenderer = renderer as ILocalDiffuseRenderer; IWavesInteractive wavesInteractive = renderer as IWavesInteractive; if (localDisplacementRenderer != null) { LocalDisplacement.Remove(localDisplacementRenderer); } if (localDisplacementMaskRenderer != null) { LocalDisplacementMask.Remove(localDisplacementMaskRenderer); } if (localFoamRenderer != null) { LocalFoam.Remove(localFoamRenderer); } if (wavesInteractive != null) { Interactions.Remove(wavesInteractive); } if (localDiffuseRenderer != null) { LocalDiffuse.Remove(localDiffuseRenderer); } } } private IOverlaysRenderer[] _OverlayRenderers; private Material _MapLocalDisplacementsMaterial; private static readonly Renderers _Renderers = new Renderers(); public static List Interactions = new List(); private readonly Water _Water; private readonly Data _Data; private readonly Shader _MapLocalDisplacementsShader; private static CommandBuffer _RenderDisplacementBuffer; private static CommandBuffer _RenderDisplacementMaskBuffer; private static CommandBuffer _RenderFoamBuffer; private static CommandBuffer _RenderDiffuseBuffer; private readonly Dictionary _Buffers = new Dictionary(); private readonly List _LostCameras = new List(); private static readonly RenderTargetIdentifier[] _CustomEffectsBuffers = new RenderTargetIdentifier[2]; public Water Water { get { return _Water; } } public DynamicWater(Water water, Data data) { _Water = water; _Data = data; CreateCommandBuffers(); Validate(); _MapLocalDisplacementsShader = Shader.Find("UltimateWater/Utility/Map Local Displacements"); } public void ValidateWaterComponents() { _OverlayRenderers = _Water.GetComponentsInChildren(); int[] array = new int[_OverlayRenderers.Length]; for (int i = 0; i < array.Length; i++) { Type type = _OverlayRenderers[i].GetType(); object[] customAttributes = type.GetCustomAttributes(typeof(OverlayRendererOrderAttribute), true); if (customAttributes.Length != 0) { array[i] = ((OverlayRendererOrderAttribute)customAttributes[0]).Priority; } } Array.Sort(array, _OverlayRenderers); } public static void AddRenderer(T renderer) where T : IDynamicWaterEffects { _Renderers.Add(renderer); } public static void RemoveRenderer(T renderer) where T : IDynamicWaterEffects { _Renderers.Remove(renderer); } public void RenderTotalDisplacementMap(WaterCamera camera, RenderTexture renderTexture) { Rect localMapsRect = camera.LocalMapsRect; Camera effectsCamera = camera.EffectsCamera; effectsCamera.enabled = false; effectsCamera.stereoTargetEye = StereoTargetEyeMask.None; effectsCamera.depthTextureMode = DepthTextureMode.None; effectsCamera.renderingPath = RenderingPath.VertexLit; effectsCamera.orthographic = true; effectsCamera.orthographicSize = localMapsRect.width * 0.5f; effectsCamera.farClipPlane = 2000f; effectsCamera.ResetProjectionMatrix(); effectsCamera.clearFlags = CameraClearFlags.Nothing; effectsCamera.allowHDR = true; effectsCamera.transform.position = new Vector3(localMapsRect.center.x, 1000f, localMapsRect.center.y); effectsCamera.transform.rotation = Quaternion.LookRotation(new Vector3(0f, -1f, 0f), new Vector3(0f, 0f, 1f)); WaterCamera component = effectsCamera.GetComponent(); component.enabled = true; component.GeometryType = WaterGeometryType.UniformGrid; component.ForcedVertexCount = renderTexture.width * renderTexture.height >> 2; component.RenderWaterWithShader("[Ultimate Water] Render Total Displacement Map", renderTexture, _MapLocalDisplacementsShader, _Water); } public DynamicWaterCameraData GetCameraOverlaysData(Camera camera, bool createIfNotExists = true) { DynamicWaterCameraData value; if (!_Buffers.TryGetValue(camera, out value) && createIfNotExists) { value = (_Buffers[camera] = new DynamicWaterCameraData(this, WaterCamera.GetWaterCamera(camera), _Data.Antialiasing)); DrawDisplacementMaskRenderers(value); value.SwapFoamMaps(); for (int i = 0; i < _OverlayRenderers.Length; i++) { _OverlayRenderers[i].RenderOverlays(value); } } if (value != null) { value._LastFrameUsed = Time.frameCount; } return value; } internal override void OnWaterRender(WaterCamera waterCamera) { Camera cameraComponent = waterCamera.CameraComponent; if (waterCamera.Type == WaterCamera.CameraType.Normal && Application.isPlaying && (WaterProjectSettings.Instance.RenderInSceneView || !WaterUtilities.IsSceneViewCamera(cameraComponent))) { Shader.SetGlobalVector("_TileSizesInv", _Water.WindWaves.TileSizesInv); DynamicWaterCameraData cameraOverlaysData = GetCameraOverlaysData(cameraComponent); cameraOverlaysData.SwapFoamMaps(); cameraOverlaysData.ClearOverlays(); DrawDisplacementMaskRenderers(cameraOverlaysData); DrawDisplacementRenderers(cameraOverlaysData); for (int i = 0; i < _OverlayRenderers.Length; i++) { _OverlayRenderers[i].RenderOverlays(cameraOverlaysData); } if (_Water.Foam != null) { _Water.Foam.RenderOverlays(cameraOverlaysData); } for (int j = 0; j < _OverlayRenderers.Length; j++) { _OverlayRenderers[j].RenderFoam(cameraOverlaysData); } int localDiffuseMap = ShaderVariables.LocalDiffuseMap; MaterialPropertyBlock propertyBlock = _Water.Renderer.PropertyBlock; propertyBlock.SetTexture(ShaderVariables.LocalDisplacementMap, cameraOverlaysData.DynamicDisplacementMap); propertyBlock.SetTexture(ShaderVariables.LocalNormalMap, cameraOverlaysData.NormalMap); propertyBlock.SetTexture(ShaderVariables.TotalDisplacementMap, cameraOverlaysData.TotalDisplacementMap); propertyBlock.SetTexture(ShaderVariables.DisplacementsMask, cameraOverlaysData.DisplacementsMask); propertyBlock.SetTexture(localDiffuseMap, cameraOverlaysData.DiffuseMap); Shader.SetGlobalTexture("DIFFUSE", cameraOverlaysData.DiffuseMap); RenderTexture debugMap = cameraOverlaysData.GetDebugMap(); if (debugMap != null) { propertyBlock.SetTexture("_LocalDebugMap", debugMap); } if (waterCamera.MainWater == _Water) { Shader.SetGlobalTexture(ShaderVariables.TotalDisplacementMap, cameraOverlaysData.TotalDisplacementMap); } DrawFoamRenderers(cameraOverlaysData); DrawDiffuseRenderers(cameraOverlaysData); } } internal override void Enable() { ValidateWaterComponents(); if (_MapLocalDisplacementsMaterial == null) { _MapLocalDisplacementsMaterial = new Material(_MapLocalDisplacementsShader) { hideFlags = HideFlags.DontSave }; } } internal override void Disable() { foreach (KeyValuePair buffer in _Buffers) { buffer.Value.Dispose(); } _Buffers.Clear(); } internal override void Destroy() { foreach (KeyValuePair buffer in _Buffers) { buffer.Value.Dispose(); } _Buffers.Clear(); } internal override void Validate() { } internal override void Update() { int num = Time.frameCount - 3; Dictionary.Enumerator enumerator = _Buffers.GetEnumerator(); while (enumerator.MoveNext()) { if (enumerator.Current.Value._LastFrameUsed < num) { enumerator.Current.Value.Dispose(); _LostCameras.Add(enumerator.Current.Key); } } enumerator.Dispose(); for (int i = 0; i < _LostCameras.Count; i++) { _Buffers.Remove(_LostCameras[i]); } _LostCameras.Clear(); } private static void DrawDisplacementRenderers(DynamicWaterCameraData overlays) { Camera cameraComponent = overlays.Camera.CameraComponent; _CustomEffectsBuffers[0] = overlays.DynamicDisplacementMap; _CustomEffectsBuffers[1] = overlays.NormalMap; GL.PushMatrix(); GL.modelview = cameraComponent.worldToCameraMatrix; GL.LoadProjectionMatrix(cameraComponent.projectionMatrix); _RenderDisplacementBuffer.Clear(); _RenderDisplacementBuffer.SetRenderTarget(_CustomEffectsBuffers, overlays.DynamicDisplacementMap); List localDisplacement = _Renderers.LocalDisplacement; for (int num = localDisplacement.Count - 1; num >= 0; num--) { localDisplacement[num].RenderLocalDisplacement(_RenderDisplacementBuffer, overlays); } Graphics.ExecuteCommandBuffer(_RenderDisplacementBuffer); GL.PopMatrix(); } private static void DrawDisplacementMaskRenderers(DynamicWaterCameraData overlays) { Shader.SetGlobalTexture("_CameraDepthTexture", DefaultTextures.Get(Color.white)); Camera cameraComponent = overlays.Camera.CameraComponent; GL.PushMatrix(); GL.modelview = cameraComponent.worldToCameraMatrix; GL.LoadProjectionMatrix(cameraComponent.projectionMatrix); _RenderDisplacementMaskBuffer.Clear(); _RenderDisplacementMaskBuffer.SetRenderTarget(overlays.DisplacementsMask); List localDisplacementMask = _Renderers.LocalDisplacementMask; for (int num = localDisplacementMask.Count - 1; num >= 0; num--) { localDisplacementMask[num].RenderLocalMask(_RenderDisplacementMaskBuffer, overlays); } Graphics.ExecuteCommandBuffer(_RenderDisplacementMaskBuffer); GL.PopMatrix(); } private static void DrawFoamRenderers(DynamicWaterCameraData overlays) { List localFoam = _Renderers.LocalFoam; for (int num = localFoam.Count - 1; num >= 0; num--) { localFoam[num].Enable(); } Shader.SetGlobalTexture("_CameraDepthTexture", DefaultTextures.Get(Color.white)); Camera cameraComponent = overlays.Camera.CameraComponent; GL.PushMatrix(); GL.modelview = cameraComponent.worldToCameraMatrix; GL.LoadProjectionMatrix(cameraComponent.projectionMatrix); _RenderFoamBuffer.Clear(); _RenderFoamBuffer.SetRenderTarget(overlays.FoamMap); for (int num2 = localFoam.Count - 1; num2 >= 0; num2--) { localFoam[num2].RenderLocalFoam(_RenderFoamBuffer, overlays); } Graphics.ExecuteCommandBuffer(_RenderFoamBuffer); GL.PopMatrix(); for (int num3 = localFoam.Count - 1; num3 >= 0; num3--) { localFoam[num3].Disable(); } } private static void DrawDiffuseRenderers(DynamicWaterCameraData overlays) { List localDiffuse = _Renderers.LocalDiffuse; for (int num = localDiffuse.Count - 1; num >= 0; num--) { localDiffuse[num].Enable(); } Shader.SetGlobalTexture("_CameraDepthTexture", DefaultTextures.Get(Color.white)); Camera cameraComponent = overlays.Camera.CameraComponent; GL.PushMatrix(); GL.modelview = cameraComponent.worldToCameraMatrix; GL.LoadProjectionMatrix(cameraComponent.projectionMatrix); _RenderDiffuseBuffer.Clear(); _RenderDiffuseBuffer.SetRenderTarget(overlays.DiffuseMap); for (int num2 = localDiffuse.Count - 1; num2 >= 0; num2--) { localDiffuse[num2].RenderLocalDiffuse(_RenderDiffuseBuffer, overlays); } Graphics.ExecuteCommandBuffer(_RenderDiffuseBuffer); GL.PopMatrix(); for (int num3 = localDiffuse.Count - 1; num3 >= 0; num3--) { localDiffuse[num3].Disable(); } } private static void CreateCommandBuffers() { CommandBuffer commandBuffer = new CommandBuffer(); commandBuffer.name = "[Ultimate Water] Displacement Renderers"; _RenderDisplacementBuffer = commandBuffer; commandBuffer = new CommandBuffer(); commandBuffer.name = "[Ultimate Water] Displacement Mask Renderers"; _RenderDisplacementMaskBuffer = commandBuffer; commandBuffer = new CommandBuffer(); commandBuffer.name = "[Ultimate Water] Foam Renderers"; _RenderFoamBuffer = commandBuffer; commandBuffer = new CommandBuffer(); commandBuffer.name = "[Ultimate Water] Diffuse Renderers"; _RenderDiffuseBuffer = commandBuffer; } private static void ReleaseCommandBuffers() { if (_RenderDisplacementBuffer != null) { _RenderDisplacementBuffer.Release(); } if (_RenderDisplacementMaskBuffer != null) { _RenderDisplacementMaskBuffer.Release(); } if (_RenderFoamBuffer != null) { _RenderFoamBuffer.Release(); } if (_RenderDiffuseBuffer != null) { _RenderDiffuseBuffer.Release(); } } } }