using Unity.Collections; using UnityEngine.Experimental.Rendering; using static Unity.Mathematics.math; namespace UnityEngine.Rendering.HighDefinition { public partial class WaterSurface : MonoBehaviour { /// /// True if this surface supports simulation mask decals. /// public bool simulationMask = false; /// /// Specifies the resolution of the mask texture used to represent the mask area. /// [Tooltip("Specifies the resolution of the mask texture used to represent the mask area.")] public WaterDecalRegionResolution maskRes = WaterDecalRegionResolution.Resolution512; /// /// Sets the texture used to attenuate or suppress the swell, agitation and ripples water frequencies. /// public Texture waterMask = null; /// /// Sets the remapped range of the water mask. /// [Tooltip("Sets the remapped range of the water mask.")] public Vector2 waterMaskRemap = new Vector2(0.0f, 1.0f); /// /// Sets the extent of the water mask in meters. /// [Tooltip("Sets the extent of the water mask in meters.")] public Vector2 waterMaskExtent = new Vector2(100.0f, 100.0f); /// /// Sets the offset of the water mask in meters. /// [Tooltip("Sets the offset of the water mask in meters.")] public Vector2 waterMaskOffset = new Vector2(0.0f, 0.0f); // GPU data internal RTHandle maskBuffer = null; // Native buffer that the CPU simulation reads from internal AsyncTextureSynchronizer waterMaskSynchronizer = new AsyncTextureSynchronizer(GraphicsFormat.R8G8B8A8_UNorm); void FillWaterMaskData(ref WaterSimSearchData wsd) { var system = HDRenderPipeline.currentPipeline.waterSystem; var mask = GetSimulationMaskBuffer(system, true); if (mask != null && waterMaskSynchronizer.TryGetBuffer(out var maskBuffer) && maskBuffer.Length > 0 && waterMaskSynchronizer.CurrentResolution().x != 0) { wsd.activeMask = true; wsd.maskBuffer = maskBuffer; wsd.maskWrapModeU = mask.wrapModeU; wsd.maskWrapModeV = mask.wrapModeV; wsd.maskResolution = waterMaskSynchronizer.CurrentResolution(); } else { wsd.activeMask = false; wsd.maskBuffer = system.m_DefaultWaterMask; } wsd.maskScale = float2(1.0f / waterMaskExtent.x, 1.0f / waterMaskExtent.y); wsd.maskOffset = float2(waterMaskOffset.x, waterMaskOffset.y); wsd.maskRemap = float2(waterMaskRemap.x, waterMaskRemap.y - waterMaskRemap.x); } internal void CheckMaskResources() { if (!HDRenderPipeline.currentPipeline.waterSystem.m_EnableDecalWorkflow) return; if (simulationMask || supportSimulationFoamMask) { int resolution = (int)maskRes; if (maskBuffer != null && maskBuffer.rt.width != resolution) ReleaseWaterMaskResources(); if (maskBuffer == null) maskBuffer = RTHandles.Alloc(resolution, resolution, 1, dimension: TextureDimension.Tex2D, colorFormat: GraphicsFormat.R8G8B8A8_UNorm, enableRandomWrite: true, wrapMode: TextureWrapMode.Clamp, name: "Water Mask"); } else if (maskBuffer != null) ReleaseWaterMaskResources(); } void ReleaseWaterMaskResources() { RTHandles.Release(maskBuffer); maskBuffer = null; waterMaskSynchronizer.ReleaseATSResources(); } /// /// Function that returns the simulation mask buffer for the water surface. /// If the mask decals are disabled in the global settings or the feature is disabled by the water surface, the function returns null. /// /// /// A texture that holds the simulation mask for each band in the RGB channels and the simulation foam mask in the alpha channel. public Texture GetSimulationMaskBuffer() { return maskBuffer; } internal Texture GetSimulationMaskBuffer(WaterSystem system, bool frameSetting, Texture defaultValue = null) { if (system.m_EnableDecalWorkflow) return frameSetting && system.m_ActiveMask && simulationMask ? maskBuffer : defaultValue; else return waterMask != null ? waterMask : defaultValue; } internal Texture GetSimulationFoamMaskBuffer(WaterSystem system, bool frameSetting, Texture defaultValue = null) { if (system.m_EnableDecalWorkflow) return frameSetting && system.m_ActiveMask && supportSimulationFoamMask ? maskBuffer : defaultValue; else return simulationFoamMask != null ? simulationFoamMask : defaultValue; } } }