using System;
using System.Collections.Generic;
using UnityEngine;
using Gaia;
#if MEWLIST_MASSIVE_CLOUDS
using Mewlist;
#endif
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
using Random = UnityEngine.Random;
#if HDPipeline
using UnityEngine.Rendering.HighDefinition;
#endif
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace ProceduralWorlds.WaterSystem
{
[Serializable]
public class SceneConditionsData
{
//Sun
public Color m_sunColor;
public float m_sunIntensity;
public Vector3 m_sunDirection;
//Time of day
public int m_hour;
public float m_minute;
}
///
/// Generates Water Reflection/Underwater Control and Mesh Generation.
///
[ExecuteAlways]
public class PWS_WaterSystem : MonoBehaviour
{
public static PWS_WaterSystem Instance
{
get
{
if (m_instance == null)
{
m_instance = FindObjectOfType();
}
return m_instance;
}
}
[SerializeField]
private static PWS_WaterSystem m_instance;
#region Variables
public bool InfiniteMode
{
get { return m_infiniteMode; }
set
{
if (m_infiniteMode != value)
{
m_infiniteMode = value;
SetInfiniteMode(m_infiniteMode);
}
}
}
private bool m_infiniteMode = true;
public GaiaConstants.WaterAutoUpdateMode m_autoUpdateMode = GaiaConstants.WaterAutoUpdateMode.Interval;
public SceneConditionsData SceneConditionsData = new SceneConditionsData();
#region Water Reflections/Surface
#region Public Variables
public bool m_disableAllReflections = false;
public bool m_autoRefresh = true;
public bool m_ignoreSceneConditions = true;
public float m_refreshRate = 0.5f;
public bool m_layersHasBeenSet = false;
public GaiaConstants.EnvironmentRenderer RenderPipeline;
public SceneProfile m_waterProfile;
public GaiaWaterProfileValues m_waterProfileValues;
public Transform m_player;
public Camera m_RenderCamera;
public Camera m_gameCamera;
public RenderingPath m_RenderPath;
public List m_waterMaterialInstances = new List();
public Gradient m_currentGradient;
public Texture2D m_waterTexture;
public Texture2D m_currentWaterTexture;
public bool m_requestDepthTextureGeneration = false;
public Light SunLight;
public float m_minSurfaceLight = 0.5f;
public float m_maxSurfaceLight = 2f;
//Sea level setup
public bool m_updatingSeaLevel = false;
public float SeaLevel
{
get { return m_seaLevel; }
set
{
if (m_seaLevel != value)
{
m_seaLevel = value;
m_updatingSeaLevel = true;
UpdateSeaLevel(m_seaLevel, true);
}
}
}
[SerializeField]
private float m_seaLevel = 25f;
public GaiaPlanarReflections m_planarReflections;
#if HDPipeline
public PlanarReflectionProbe m_HDPlanarReflections;
#endif
#endregion
#region Private Variables
public bool m_weatherSystemPresent = false;
public bool m_ableToRender = true;
private float m_currentRefreshRate;
private bool m_hdr;
private bool m_rebuild;
private int m_oldRenderTextureSize;
private Vector3 m_worldPosition;
private Vector3 m_normal;
private Vector3 m_oldPosition;
private Vector3 m_newPosition;
private Vector3 m_euler;
private Vector4 m_clipPlane;
private Vector3 m_currentPosition;
private Vector3 m_currentRotation;
private Matrix4x4 m_projection;
private Matrix4x4 m_reflection;
private int m_frameCheck;
[SerializeField]
private bool m_sceneProfileExists = false;
[SerializeField]
private RenderTexture m_reflectionTexture;
public Camera m_reflectionCamera;
#if UNITY_EDITOR
[SerializeField]
private GaiaSessionManager m_gaiaSession;
#endif
[SerializeField]
private GaiaUnderwaterEffects m_underwaterFX;
[SerializeField]
private Material m_waterMaterial;
[SerializeField]
private bool m_rendererPresent;
#if GAIA_PRO_PRESENT
[SerializeField]
private ProceduralWorldsGlobalWeather WeatherSystem;
#endif
private bool m_forceGenerateDepthTexture = true;
// [SerializeField]
// private bool m_setupFog = false;
private const string m_reflectionName = "__MirrorReflection";
private const string m_reflectionIDName = "Mirror Refl Camera id";
private const string m_forText = " for ";
#endregion
#endregion
#region Underwater Sync Variables
#region Public Variables
public GaiaConstants.PW_RENDER_SIZE renderSize = GaiaConstants.PW_RENDER_SIZE.HALF;
public bool refractionEnabled = true;
public float directionAngle = 0;
#endregion
#endregion
#region Mesh Generation Variables
#region Public Variables
public int m_height = 0;
public float m_gizmoSize = 0.1f;
public Vector3 m_Size = new Vector3(200, 30, 200);
public Vector2 m_meshDensity = new Vector2(50, 50);
public GaiaConstants.MeshType m_MeshType = GaiaConstants.MeshType.Plane;
#endregion
#region Private Variables
private Vector2 m_uvScale;
private Vector3 m_sizeScale;
private List m_triangles = new List();
private List m_vertices = new List();
private List m_uvs = new List();
private Mesh m_generateMesh;
private Vector2Int m_numberOfPoints;
#endregion
#endregion
#endregion
#region Unity Methods
///
/// On enable rebuild the required data
///
private void OnEnable()
{
StartAndOnEnabled();
}
///
/// Update is called every frame
///
private void Update()
{
UpdateMode();
}
///
/// OnRenderObject is called after camera has rendered the Scene
///
public void OnWillRenderObject()
{
if (RenderPipeline == GaiaConstants.EnvironmentRenderer.BuiltIn)
{
OnRenderObjectUpdate();
}
}
///
/// OnDisable ClearData
///
private void OnDisable()
{
m_rebuild = true;
ClearAllData();
}
///
/// OnDestroy ClearData
///
private void OnDestroy()
{
ClearAllData();
}
#endregion
#region Unity Method Functions
///
/// Function used to initilize on enable or start depending on bool status
///
///
public void StartAndOnEnabled()
{
if (m_waterProfile == null && m_waterProfileValues == null)
{
return;
}
m_forceGenerateDepthTexture = true;
if (m_underwaterFX == null)
{
m_underwaterFX = GaiaUnderwaterEffects.Instance;
}
m_sceneProfileExists = GaiaUtils.CheckIfSceneProfileExists();
m_frameCheck = Random.Range(5, 15);
LoadResources();
m_currentRefreshRate = m_refreshRate;
m_waterMaterialInstances = GetWaterMaterialInstances();
RenderPipeline = GaiaUtils.GetActivePipeline();
m_rendererPresent = CheckRendererComponent();
ClearAllData();
ProcessOnEnableReflections();
RefractionInit();
if (m_waterMaterialInstances.Count == 2)
{
if (RenderPipeline != GaiaConstants.EnvironmentRenderer.HighDefinition)
{
SendNormalMaps();
SendWaterEdge();
SendWaveData();
}
}
m_rebuild = true;
Generate(m_waterProfile);
m_rebuild = false;
#if GAIA_PRO_PRESENT
m_weatherSystemPresent = ProceduralWorldsGlobalWeather.Instance;
WeatherSystem = ProceduralWorldsGlobalWeather.Instance;
#endif
SyncAutoRefresh();
//Updates aura if it's present
UpdateAura();
SetInfiniteMode(InfiniteMode);
}
///
/// Used for the update/late update functions
///
private void UpdateMode()
{
if (m_waterProfile == null)
{
return;
}
if (m_waterProfile.m_selectedWaterProfileValuesIndex <= m_waterProfile.m_waterProfiles.Count - 1)
{
m_waterProfileValues = m_waterProfile.m_waterProfiles[m_waterProfile.m_selectedWaterProfileValuesIndex];
}
if (!m_updatingSeaLevel)
{
if (gameObject.transform.position.y != SeaLevel)
{
SeaLevel = transform.position.y;
}
}
#if UNITY_EDITOR
m_waterProfile.UpdateTextureResolution();
#endif
BuildWaterColorDepth();
UpdateShaderValues(m_waterProfileValues);
float distanceCheck = 500f;
if (m_RenderCamera != null)
{
distanceCheck = m_RenderCamera.farClipPlane;
}
if (m_waterMaterialInstances.Count == 2)
{
if (RenderPipeline != GaiaConstants.EnvironmentRenderer.HighDefinition)
{
SendWaveData();
SendWindDirection();
#if UNITY_EDITOR
SendNormalMaps();
SendWaterEdge();
#endif
}
}
//CalculateSmoothnessRay(m_waterProfile, m_waterProfileValues.m_smoothness, distanceCheck);
}
///
/// Used on will render object and the alternative for SRP
///
///
private void OnRenderObjectUpdate(Camera overrideCam = null)
{
if (m_waterProfile == null && m_waterProfileValues == null)
{
return;
}
if (m_disableAllReflections)
{
ClearData(true);
return;
}
if (!Application.isPlaying)
{
#if UNITY_EDITOR
if (SceneView.lastActiveSceneView == null)
{
return;
}
m_RenderCamera = SceneView.lastActiveSceneView.camera;
if (overrideCam != null)
{
m_RenderCamera = overrideCam;
}
if (m_RenderCamera != null)
{
if (CheckPositionAndRotation())
{
GenerateCamera(m_waterProfile);
ResyncCameraSettings(m_waterProfile);
UpdateCameraModes();
if (m_reflectionTexture != null && m_reflectionTexture.width > 0)
{
BuildReflection(m_waterProfile);
}
}
}
#endif
}
else
{
m_RenderCamera = m_gameCamera;
if (overrideCam != null)
{
m_RenderCamera = overrideCam;
}
if (m_RenderCamera != null)
{
if (CheckPositionAndRotation())
{
if (m_reflectionTexture != null && m_reflectionTexture.width > 0)
{
BuildReflection(m_waterProfile);
}
}
else
{
if (AutoRefresh())
{
m_frameCheck = Random.Range(5, 15);
if (m_reflectionTexture != null && m_reflectionTexture.width > 0)
{
BuildReflection(m_waterProfile);
}
}
m_frameCheck--;
}
}
else
{
if (m_RenderCamera == null)
{
m_RenderCamera = GaiaUtils.GetCamera();
}
}
}
}
///
/// Render SRP camera
///
///
///
private void OnRenderSRP(ScriptableRenderContext src, Camera cam)
{
if (cam.cameraType == CameraType.Preview)
{
return;
}
var roll = cam.transform.localEulerAngles.z;
Shader.SetGlobalFloat(GaiaShaderID.CameraRoll, roll);
Shader.SetGlobalMatrix(GaiaShaderID.InvViewProjection, (GL.GetGPUProjectionMatrix(cam.projectionMatrix, false) * cam.worldToCameraMatrix).inverse);
if (Instance != null)
{
OnRenderObjectUpdate(cam);
}
}
///
/// Checks the player position and rotation
///
///
private bool CheckPositionAndRotation()
{
try
{
if (m_RenderCamera == null)
{
return false;
}
if (m_RenderCamera.transform.position != m_currentPosition || m_RenderCamera.transform.rotation.eulerAngles != m_currentRotation)
{
m_currentPosition = m_RenderCamera.transform.position;
m_currentRotation = m_RenderCamera.transform.rotation.eulerAngles;
return true;
}
return false;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
///
/// Checks if auto refresh can be set
///
///
private bool AutoRefresh()
{
if (m_autoRefresh)
{
if (m_autoUpdateMode == GaiaConstants.WaterAutoUpdateMode.SceneConditions)
{
if (m_frameCheck <= 0)
{
if (CheckSceneConditions())
{
SetSceneConditionsData();
return true;
}
}
}
else
{
m_currentRefreshRate -= Time.deltaTime;
if (m_currentRefreshRate < 0)
{
m_currentRefreshRate = m_refreshRate;
if (m_ignoreSceneConditions)
{
return true;
}
else
{
if (CheckSceneConditions())
{
SetSceneConditionsData();
return true;
}
}
}
}
}
return false;
}
private bool CheckSceneConditions()
{
if (SunLight != null)
{
if (SunLight.color != SceneConditionsData.m_sunColor)
{
return true;
}
if (SunLight.intensity != SceneConditionsData.m_sunIntensity)
{
return true;
}
if (SunLight.transform.eulerAngles != SceneConditionsData.m_sunDirection)
{
return true;
}
}
if (m_sceneProfileExists)
{
if (GaiaGlobal.Instance.GaiaTimeOfDayValue.m_todHour != SceneConditionsData.m_hour)
{
return true;
}
if (GaiaGlobal.Instance.GaiaTimeOfDayValue.m_todMinutes != SceneConditionsData.m_minute)
{
return true;
}
}
return false;
}
private void SyncAutoRefresh()
{
if (GaiaUtils.CheckIfSceneProfileExists() && m_waterProfile != null)
{
m_autoRefresh = m_waterProfile.m_autoRefresh;
m_ignoreSceneConditions = m_waterProfile.m_ignoreSceneConditions;
m_autoUpdateMode = m_waterProfile.m_autoUpdateMode;
m_refreshRate = m_waterProfile.m_refreshRate;
}
}
///
/// Updates the scene conditions
///
private void SetSceneConditionsData()
{
if (SunLight != null)
{
SceneConditionsData.m_sunColor = SunLight.color;
SceneConditionsData.m_sunIntensity = SunLight.intensity;
SceneConditionsData.m_sunDirection = SunLight.transform.eulerAngles;
}
if (m_sceneProfileExists)
{
SceneConditionsData.m_hour = GaiaGlobal.Instance.GaiaTimeOfDayValue.m_todHour;
SceneConditionsData.m_minute = GaiaGlobal.Instance.GaiaTimeOfDayValue.m_todMinutes;
}
}
#endregion
#region Water Reflections/Surface
#region Public Functions
///
/// Used to generate the reflections
///
///
public void Generate(SceneProfile profile)
{
if (m_disableAllReflections)
{
return;
}
if (m_RenderCamera == null)
{
m_RenderCamera = GaiaUtils.GetCamera();
}
if (profile == null)
{
return;
}
if (m_rendererPresent)
{
if (RenderPipeline != GaiaConstants.EnvironmentRenderer.HighDefinition)
{
if (m_waterMaterialInstances == null || m_waterMaterialInstances.Count < 2)
{
m_waterMaterialInstances = GetWaterMaterialInstances();
}
}
if (m_waterMaterial != null)
{
SetWaterShader(m_waterMaterial, RenderPipeline);
}
GenerateCamera(profile);
CreateMirrorObjects(profile);
if (m_reflectionTexture != null && m_reflectionTexture.width > 0)
{
BuildReflection(profile);
}
}
else
{
Debug.Log("unable to create reflections, renderer component missing");
}
}
///
/// Creates water material instances
///
public void CreateWaterMaterialInstances(List materials)
{
MeshRenderer meshRenderer = gameObject.GetComponent();
if (meshRenderer != null)
{
m_waterMaterialInstances.Clear();
for (int i = 0; i < materials.Count; i++)
{
Material material = new Material(Shader.Find(materials[i].shader.name));
material.CopyPropertiesFromMaterial(materials[i]);
m_waterMaterialInstances.Add(material);
}
meshRenderer.sharedMaterials = m_waterMaterialInstances.ToArray();
if (m_waterMaterialInstances.Count == 2)
{
foreach (var material in m_waterMaterialInstances)
{
if (!material.name.Contains("Under"))
{
m_waterMaterial = m_waterMaterialInstances[0];
break;
}
}
}
for (int i = 0; i < m_waterMaterialInstances.Count; i++)
{
#if UNITY_EDITOR
EditorUtility.SetDirty(m_waterMaterialInstances[i]);
#endif
}
GenerateColorDepth();
}
}
///
/// Updates the water shader
///
///
///
public void SetWaterShader(Material masterMaterial, GaiaConstants.EnvironmentRenderer renderPipeline)
{
if (masterMaterial == null)
{
return;
}
if (renderPipeline != GaiaConstants.EnvironmentRenderer.HighDefinition)
{
masterMaterial.shader = Shader.Find(GaiaShaderID.BuiltInWaterShader);
}
else
{
masterMaterial.shader = Shader.Find(GaiaShaderID.HDRPWaterShader);
}
}
///
/// Generates color depth
///
public void GenerateColorDepth()
{
if (m_waterTexture == null || m_waterTexture.wrapMode != TextureWrapMode.Clamp)
{
m_waterTexture = new Texture2D(m_waterProfileValues.m_gradientTextureResolution,
m_waterProfileValues.m_gradientTextureResolution) {wrapMode = TextureWrapMode.Clamp};
}
else if (m_waterProfileValues.m_gradientTextureResolution != m_waterTexture.width)
{
m_waterTexture = new Texture2D(m_waterProfileValues.m_gradientTextureResolution,
m_waterProfileValues.m_gradientTextureResolution) {wrapMode = TextureWrapMode.Clamp};
}
else if (!m_waterTexture.isReadable)
{
m_waterTexture = new Texture2D(m_waterProfileValues.m_gradientTextureResolution,
m_waterProfileValues.m_gradientTextureResolution) {wrapMode = TextureWrapMode.Clamp};
}
if (m_waterProfileValues.m_waterGradient == null)
{
return;
}
if (m_requestDepthTextureGeneration || GaiaUtils.CheckGradientColorKeys(m_waterProfileValues.m_waterGradient.colorKeys, m_currentGradient.colorKeys))
{
for (int x = 0; x < m_waterProfileValues.m_gradientTextureResolution; x++)
{
for (int y = 0; y < m_waterProfileValues.m_gradientTextureResolution; y++)
{
Color color = m_waterProfileValues.m_waterGradient.Evaluate((float)x / (float)m_waterProfileValues.m_gradientTextureResolution);
m_waterTexture.SetPixel(x, y, color);
}
}
m_waterTexture.Apply();
if (m_waterMaterial != null)
{
m_waterMaterial.SetTexture(GaiaShaderID.m_waterDepthRamp, m_waterTexture);
}
m_requestDepthTextureGeneration = false;
m_currentGradient = m_waterProfileValues.m_waterGradient;
}
}
///
/// Updates the sea level
///
///
public void UpdateSeaLevel(float seaLevel, bool regenerateWaterReflections = false)
{
gameObject.transform.position = new Vector3(0f, seaLevel, 0f);
if (m_underwaterFX == null)
{
m_underwaterFX = GaiaUnderwaterEffects.Instance;
}
if (m_underwaterFX != null)
{
if (m_underwaterFX.m_underwaterPostFX != null)
{
if (m_underwaterFX.m_underwaterPostFX != null)
{
m_underwaterFX.m_underwaterPostFX.transform.position = new Vector3(0f, -3500f + seaLevel, 0f);
}
if (m_underwaterFX.m_underwaterTransitionPostFX != null)
{
m_underwaterFX.m_underwaterTransitionPostFX.transform.position = new Vector3(0f, seaLevel, 0f);
}
}
m_underwaterFX.m_seaLevel = seaLevel;
}
if (!Application.isPlaying)
{
#if UNITY_EDITOR
if (m_gaiaSession == null)
{
m_gaiaSession = GaiaSessionManager.GetSessionManager(false, false);
}
if (m_gaiaSession != null)
{
m_gaiaSession.SetSeaLevel(seaLevel);
}
EditorUtility.SetDirty(this);
#endif
}
if (regenerateWaterReflections)
{
Generate(m_waterProfile);
}
m_updatingSeaLevel = false;
}
#endregion
#region Private Functions
///
/// Gets the current material instances on the mesh renderer
///
///
private List GetWaterMaterialInstances()
{
List materials = new List();
MeshRenderer meshRenderer = GetComponent();
if (meshRenderer != null)
{
materials.AddRange(meshRenderer.sharedMaterials);
}
if (m_waterMaterialInstances.Count > 0)
{
m_waterMaterialInstances.Clear();
m_waterMaterialInstances = materials;
foreach (var material in m_waterMaterialInstances)
{
if (material != null)
{
if (!material.name.Contains("Under"))
{
m_waterMaterial = m_waterMaterialInstances[0];
break;
}
}
}
}
return materials;
}
///
/// Builds the and setup the color depth texture or sets baked texture
///
private void BuildWaterColorDepth()
{
if (m_waterProfile != null)
{
#if UNITY_EDITOR
if (m_waterProfileValues == null)
{
m_waterProfileValues = m_waterProfile.m_waterProfiles[m_waterProfile.m_selectedWaterProfileValuesIndex];
}
#endif
}
if (m_waterProfileValues == null)
{
Debug.Log("Unable To Build. Profile values from current water profile could not be set");
return;
}
if (m_waterProfileValues.m_colorDepthRamp == null)
{
if (m_waterProfileValues.m_waterGradient != null)
{
GenerateColorDepth();
}
}
else
{
m_waterTexture = m_waterProfileValues.m_colorDepthRamp;
}
if (ValidateDepthRamp(m_forceGenerateDepthTexture))
{
m_waterMaterial.SetTexture(GaiaShaderID.m_waterDepthRamp, m_waterTexture);
m_currentWaterTexture = m_waterTexture;
m_forceGenerateDepthTexture = false;
}
}
///
/// Checks if the depth ramp texture needs to be reset
///
///
private bool ValidateDepthRamp(bool forceUpdate = false)
{
if (m_waterMaterial == null)
{
return false;
}
if (forceUpdate)
{
return true;
}
if (m_waterTexture != null)
{
if (m_currentWaterTexture == null)
{
return true;
}
else
{
if (m_waterTexture != m_currentWaterTexture)
{
return true;
}
}
}
return false;
}
///
/// Enables or disables the smoothness based on ray setup
///
private void CalculateSmoothnessRay(SceneProfile profile, float smoothness, float range)
{
if (profile == null)
{
return;
}
if (Application.isPlaying)
{
if (m_RenderCamera != null)
{
Ray ray = m_RenderCamera.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0));
#if GAIA_PRO_PRESENT
if (m_weatherSystemPresent)
{
if (WeatherSystem.CheckIsNight())
{
if (Physics.Raycast(ray.origin, -WeatherSystem.m_moonLight.transform.forward, range, profile.m_reflectedLayers))
{
m_waterMaterial.SetFloat(GaiaShaderID.m_waterSmoothness, 1f);
}
else
{
m_waterMaterial.SetFloat(GaiaShaderID.m_waterSmoothness, smoothness);
}
}
else
{
if (Physics.Raycast(ray.origin, -WeatherSystem.m_sunLight.transform.forward, range, profile.m_reflectedLayers))
{
m_waterMaterial.SetFloat(GaiaShaderID.m_waterSmoothness, 1f);
}
else
{
m_waterMaterial.SetFloat(GaiaShaderID.m_waterSmoothness, smoothness);
}
}
}
else
{
if (SunLight != null)
{
if (Physics.Raycast(ray.origin, -SunLight.transform.forward, range, profile.m_reflectedLayers))
{
m_waterMaterial.SetFloat(GaiaShaderID.m_waterSmoothness, 1f);
}
else
{
m_waterMaterial.SetFloat(GaiaShaderID.m_waterSmoothness, smoothness);
}
}
else
{
SunLight = GaiaUtils.GetMainDirectionalLight();
}
}
#else
if (SunLight != null)
{
if (Physics.Raycast(ray.origin, -SunLight.transform.forward, range, profile.m_reflectedLayers))
{
m_waterMaterial.SetFloat(GaiaShaderID.m_waterSmoothness, 1f);
}
else
{
m_waterMaterial.SetFloat(GaiaShaderID.m_waterSmoothness, smoothness);
}
}
else
{
SunLight = GaiaUtils.GetMainDirectionalLight();
}
#endif
}
}
else
{
#if UNITY_EDITOR
#if GAIA_PRO_PRESENT
if (m_weatherSystemPresent)
{
if (WeatherSystem.CheckIsNight())
{
if (SceneView.lastActiveSceneView != null)
{
Ray ray = SceneView.lastActiveSceneView.camera.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0));
if (Physics.Raycast(ray.origin, -WeatherSystem.m_moonLight.transform.forward, range, profile.m_reflectedLayers))
{
m_waterMaterial.SetFloat(GaiaShaderID.m_waterSmoothness, 1f);
}
else
{
m_waterMaterial.SetFloat(GaiaShaderID.m_waterSmoothness, smoothness);
}
}
}
else
{
if (SceneView.lastActiveSceneView != null)
{
Ray ray = SceneView.lastActiveSceneView.camera.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0));
if (WeatherSystem.m_sunLight != null)
{
if (Physics.Raycast(ray.origin, -WeatherSystem.m_sunLight.transform.forward, range, profile.m_reflectedLayers))
{
m_waterMaterial.SetFloat(GaiaShaderID.m_waterSmoothness, 1f);
}
else
{
m_waterMaterial.SetFloat(GaiaShaderID.m_waterSmoothness, smoothness);
}
}
}
}
}
else
{
if (SceneView.lastActiveSceneView != null)
{
if (SunLight != null)
{
Ray ray = SceneView.lastActiveSceneView.camera.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0));
if (Physics.Raycast(ray.origin, -SunLight.transform.forward, range, profile.m_reflectedLayers))
{
m_waterMaterial.SetFloat(GaiaShaderID.m_waterSmoothness, 1f);
}
else
{
m_waterMaterial.SetFloat(GaiaShaderID.m_waterSmoothness, smoothness);
}
}
else
{
SunLight = GaiaUtils.GetMainDirectionalLight();
}
}
}
#else
if (UnityEditor.SceneView.lastActiveSceneView != null)
{
if (SunLight != null)
{
Ray ray = UnityEditor.SceneView.lastActiveSceneView.camera.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0));
if (Physics.Raycast(ray.origin, -SunLight.transform.forward, range, profile.m_reflectedLayers))
{
m_waterMaterial.SetFloat(GaiaShaderID.m_waterSmoothness, 1f);
}
else
{
m_waterMaterial.SetFloat(GaiaShaderID.m_waterSmoothness, smoothness);
}
}
else
{
SunLight = GaiaUtils.GetMainDirectionalLight();
}
}
#endif
#endif
}
}
///
/// Clears all the data/buffers
///
private void ClearAllData()
{
ClearData();
//Stops prerenders and clears data
switch (RenderPipeline)
{
case GaiaConstants.EnvironmentRenderer.Universal:
RenderPipelineManager.beginCameraRendering += OnRenderSRP;
break;
case GaiaConstants.EnvironmentRenderer.HighDefinition:
//RenderPipelineManager.beginCameraRendering += OnRenderSRP;
break;
}
}
///
/// Checks to see if the active gameobject has a mesh renderer
///
///
private bool CheckRendererComponent()
{
if (GetComponent())
{
return true;
}
else
{
return false;
}
}
///
/// Loads the missing resources
///
private void LoadResources()
{
if (m_instance == null)
{
m_instance = this;
}
if (m_gameCamera == null)
{
m_gameCamera = GaiaUtils.GetCamera();
}
if (Application.isPlaying)
{
m_RenderCamera = m_gameCamera;
}
else
{
#if UNITY_EDITOR
if (SceneView.lastActiveSceneView == null)
{
return;
}
m_RenderCamera = SceneView.lastActiveSceneView.camera;
#endif
}
if (m_player == null)
{
m_player = GaiaUtils.GetPlayerTransform();
}
if (m_player == null)
{
if (m_RenderCamera)
{
m_player = m_RenderCamera.transform;
}
}
#if UNITY_EDITOR
if (m_gaiaSession == null)
{
m_gaiaSession = GaiaSessionManager.GetSessionManager(false, false);
}
#endif
if (SunLight == null)
{
SunLight = GaiaUtils.GetMainDirectionalLight();
}
if (m_currentGradient == null)
{
m_currentGradient = new Gradient();
}
}
///
/// Update Aura
///
private void UpdateAura()
{
#if AURA_IN_PROJECT
Aura2API.AuraCamera.CommonDataManager.UpdateData();
#endif
}
///
/// Updates the infinate ocean mode
///
private void UpdateInfiniteMode()
{
Transform camera = m_player;
if (camera != null)
{
gameObject.transform.position = new Vector3(camera.position.x, SeaLevel, camera.position.z);
}
}
///
/// Sets the infinate mode
///
///
private void SetInfiniteMode(bool active, float refreshRate = 0.1f)
{
if (active)
{
if (IsInvoking("UpdateInfiniteMode"))
{
CancelInvoke("UpdateInfiniteMode");
}
InvokeRepeating("UpdateInfiniteMode", 0.05f, refreshRate);
}
else
{
if (IsInvoking("UpdateInfiniteMode"))
{
CancelInvoke("UpdateInfiniteMode");
}
}
}
#endregion
#region Build/Clear Reflections
///
/// Processes SRP reflections baased on the active pipeline
///
private void ProcessOnEnableReflections()
{
switch (RenderPipeline)
{
case GaiaConstants.EnvironmentRenderer.BuiltIn:
RemoveURPPlanarReflections();
RemoveHDPRPlanarReflections();
break;
case GaiaConstants.EnvironmentRenderer.Universal:
UpdateURPPlanarReflections();
RemoveBuiltInReflectionCamera(m_reflectionCamera);
RemoveHDPRPlanarReflections();
break;
case GaiaConstants.EnvironmentRenderer.HighDefinition:
UpdateHDPPlanarReflections();
RemoveBuiltInReflectionCamera(m_reflectionCamera);
RemoveURPPlanarReflections();
break;
}
}
///
/// Used to clear Camera and Render texture
///
public void ClearData(bool dataOnly = false)
{
if (dataOnly)
{
if (m_reflectionTexture)
{
m_reflectionTexture.Release();
DestroyImmediate(m_reflectionTexture);
m_reflectionTexture = null;
}
if (RenderPipeline == GaiaConstants.EnvironmentRenderer.Universal || RenderPipeline == GaiaConstants.EnvironmentRenderer.HighDefinition)
{
RenderPipelineManager.beginCameraRendering -= OnRenderSRP;
}
}
else
{
if (m_reflectionTexture)
{
m_reflectionTexture.Release();
DestroyImmediate(m_reflectionTexture);
m_reflectionTexture = null;
}
if (m_reflectionCamera)
{
DestroyImmediate(m_reflectionCamera.gameObject);
}
if (RenderPipeline == GaiaConstants.EnvironmentRenderer.Universal || RenderPipeline == GaiaConstants.EnvironmentRenderer.HighDefinition)
{
RenderPipelineManager.beginCameraRendering -= OnRenderSRP;
}
}
}
///
/// Builds the necessary steps to produce a reflection
///
private void BuildReflection(SceneProfile profile)
{
if (m_disableAllReflections)
{
return;
}
if (m_RenderCamera == null)
{
m_RenderCamera = GaiaUtils.GetCamera();
}
if (m_underwaterFX != null)
{
if (m_underwaterFX.IsUnderwater)
{
return;
}
}
bool reflectionsEnabled = profile.m_enableReflections;
if (Application.isPlaying)
{
if (profile.m_enableDisabeHeightFeature)
{
if (m_player!=null && m_player.position.y > profile.m_disableHeight)
{
reflectionsEnabled = true;
}
}
}
if (m_RenderCamera != null)
{
if (m_ableToRender)
{
m_ableToRender = false;
m_worldPosition = transform.position;
m_normal = transform.up;
GenerateReflection(profile, reflectionsEnabled);
CreateMirrorObjects(profile);
m_ableToRender = true;
}
}
else
{
Debug.Log("no rendering camera found");
}
}
///
/// Can be used to keep the cameras settings in check
///
private void ResyncCameraSettings(SceneProfile profile)
{
if (m_RenderCamera != null)
{
if (m_reflectionCamera == null)
{
return;
}
m_reflectionCamera.orthographic = m_RenderCamera.orthographic;
m_reflectionCamera.fieldOfView = m_RenderCamera.fieldOfView;
m_reflectionCamera.aspect = m_RenderCamera.aspect;
m_reflectionCamera.orthographicSize = m_RenderCamera.orthographicSize;
m_reflectionCamera.renderingPath = m_RenderCamera.actualRenderingPath;
if (profile == null)
{
return;
}
m_reflectionCamera.allowHDR = profile.m_useHDR;
m_reflectionCamera.allowMSAA = profile.m_allowMSAA;
#if MEWLIST_MASSIVE_CLOUDS
SetMassiveCloudSystem(m_gameCamera, m_reflectionCamera);
#endif
}
}
#if MEWLIST_MASSIVE_CLOUDS
private void SetMassiveCloudSystem(Camera gameCamera, Camera reflectionCamera, bool cleanup = false)
{
if (cleanup)
{
MassiveCloudsCameraEffect[] massiveCloudComponentsCameras = FindObjectsOfType();
if (massiveCloudComponentsCameras.Length > 0)
{
for (int i = 0; i < massiveCloudComponentsCameras.Length; i++)
{
DestroyImmediate(massiveCloudComponentsCameras[i]);
}
}
MassiveClouds[] massiveCloudComponentsMains = FindObjectsOfType();
if (massiveCloudComponentsMains.Length > 0)
{
for (int i = 0; i < massiveCloudComponentsMains.Length; i++)
{
DestroyImmediate(massiveCloudComponentsMains[i]);
}
}
}
MassiveCloudsCameraEffect massiveCloudComponentsCamera = gameCamera.GetComponent();
MassiveCloudsCameraEffect reflectionMassiveCloudComponentsCamera = reflectionCamera.GetComponent();
if (massiveCloudComponentsCamera)
{
if (reflectionMassiveCloudComponentsCamera == null)
{
reflectionMassiveCloudComponentsCamera = reflectionCamera.gameObject.AddComponent();
}
}
else
{
if (reflectionMassiveCloudComponentsCamera != null)
{
DestroyImmediate(reflectionMassiveCloudComponentsCamera);
}
}
MassiveClouds massiveCloudComponentsMain = gameCamera.GetComponent();
MassiveClouds reflectionMassiveCloudComponentsMain = reflectionCamera.GetComponent();
if (massiveCloudComponentsMain)
{
if (reflectionMassiveCloudComponentsMain == null)
{
reflectionMassiveCloudComponentsMain = reflectionCamera.gameObject.AddComponent();
}
reflectionMassiveCloudComponentsMain.SetProfiles(massiveCloudComponentsMain.Profiles);
reflectionMassiveCloudComponentsMain.SetParameters(massiveCloudComponentsMain.Parameters);
}
else
{
if (reflectionMassiveCloudComponentsMain != null)
{
DestroyImmediate(reflectionMassiveCloudComponentsMain);
}
}
}
#endif
///
/// Updates Cameras flags, background color & when present the sky
///
private void UpdateCameraModes()
{
if (m_reflectionCamera == null)
{
return;
}
m_reflectionCamera.clearFlags = m_RenderCamera.clearFlags;
m_reflectionCamera.backgroundColor = m_RenderCamera.backgroundColor;
}
///
/// Create a mirror texture
///
private void CreateMirrorObjects(SceneProfile profile)
{
if (m_oldRenderTextureSize != profile.m_textureResolution || m_rebuild || m_reflectionTexture == null || profile.m_useHDR != m_hdr)
{
CreateTexture(profile);
m_reflectionTexture.hideFlags = HideFlags.HideAndDontSave;
m_oldRenderTextureSize = profile.m_textureResolution;
m_hdr = profile.m_useHDR;
}
}
///
/// Creates the render texture
///
private void CreateTexture(SceneProfile profile)
{
if (profile.m_textureResolution < 1)
{
return;
}
if (profile.m_useHDR)
{
m_reflectionTexture = new RenderTexture(profile.m_textureResolution, profile.m_textureResolution, 24, DefaultFormat.HDR)
{
name = m_reflectionName + GetInstanceID(),
isPowerOfTwo = true
};
}
else
{
m_reflectionTexture = new RenderTexture(profile.m_textureResolution, profile.m_textureResolution, 24)
{
name = m_reflectionName + GetInstanceID(),
isPowerOfTwo = true
};
}
}
///
/// Generates the camera used for the mirror
///
private void GenerateCamera(SceneProfile profile)
{
if (m_RenderCamera == null)
{
m_RenderCamera = GaiaUtils.GetCamera();
}
switch (RenderPipeline)
{
case GaiaConstants.EnvironmentRenderer.BuiltIn:
{
if (m_reflectionCamera == null && m_RenderCamera != null)
{
GameObject MirrorGameObject = new GameObject(m_reflectionIDName + GetInstanceID() + m_forText + m_RenderCamera.GetInstanceID(), typeof(Camera));
m_reflectionCamera = MirrorGameObject.GetComponent();
m_reflectionCamera.enabled = false;
m_reflectionCamera.transform.position = transform.position;
m_reflectionCamera.transform.rotation = transform.rotation;
MirrorGameObject.hideFlags = HideFlags.HideAndDontSave;
}
else if (m_reflectionCamera != null)
{
m_reflectionCamera.enabled = false;
m_reflectionCamera.transform.position = transform.position;
m_reflectionCamera.transform.rotation = transform.rotation;
m_reflectionCamera.gameObject.hideFlags = HideFlags.HideAndDontSave;
m_reflectionCamera.transform.SetParent(gameObject.transform);
}
if (m_RenderCamera != null)
{
ResyncCameraSettings(profile);
UpdateCameraModes();
}
break;
}
case GaiaConstants.EnvironmentRenderer.Universal:
UpdateURPPlanarReflections();
break;
}
}
///
/// Generates the reflection based on the main camera
///
private void GenerateReflection(SceneProfile profile, bool reflectionsEnabled)
{
//
switch (RenderPipeline)
{
case GaiaConstants.EnvironmentRenderer.BuiltIn:
UpdateBuiltInPlanarReflections(profile, reflectionsEnabled);
break;
case GaiaConstants.EnvironmentRenderer.Universal:
UpdateURPPlanarReflections();
break;
case GaiaConstants.EnvironmentRenderer.HighDefinition:
UpdateHDPPlanarReflections();
break;
}
}
///
/// Given position/normal of the plane, calculates plane in camera space.
///
///
///
///
///
///
private Vector4 CameraSpacePlane(SceneProfile profile, Camera cam, Vector3 pos, Vector3 normal, float sideSign)
{
Vector3 offsetPos = pos + normal * profile.m_clipPlaneOffset;
Matrix4x4 m = cam.worldToCameraMatrix;
Vector3 cpos = m.MultiplyPoint(offsetPos);
Vector3 cnormal = m.MultiplyVector(normal).normalized * sideSign;
return new Vector4(cnormal.x, cnormal.y, cnormal.z, -Vector3.Dot(cpos, cnormal));
}
///
/// Calculates reflection matrix around the given plane
///
///
///
private static void CalculateReflectionMatrix(ref Matrix4x4 reflectionMat, Vector4 plane)
{
reflectionMat.m00 = (1F - 2F * plane[0] * plane[0]);
reflectionMat.m01 = (-2F * plane[0] * plane[1]);
reflectionMat.m02 = (-2F * plane[0] * plane[2]);
reflectionMat.m03 = (-2F * plane[3] * plane[0]);
reflectionMat.m10 = (-2F * plane[1] * plane[0]);
reflectionMat.m11 = (1F - 2F * plane[1] * plane[1]);
reflectionMat.m12 = (-2F * plane[1] * plane[2]);
reflectionMat.m13 = (-2F * plane[3] * plane[1]);
reflectionMat.m20 = (-2F * plane[2] * plane[0]);
reflectionMat.m21 = (-2F * plane[2] * plane[1]);
reflectionMat.m22 = (1F - 2F * plane[2] * plane[2]);
reflectionMat.m23 = (-2F * plane[3] * plane[2]);
reflectionMat.m30 = 0F;
reflectionMat.m31 = 0F;
reflectionMat.m32 = 0F;
reflectionMat.m33 = 1F;
}
///
/// Updates the built in planar reflections
///
///
///
private void UpdateBuiltInPlanarReflections(SceneProfile profile, bool reflectionsEnabled)
{
//if (!m_setupFog)
//{
// GaiaSceneLighting.AddReflectionFog(m_reflectionCamera, true);
// m_setupFog = true;
//}
float DotProduct = -Vector3.Dot(m_normal, m_worldPosition) - profile.m_clipPlaneOffset;
Vector4 ReflectionPlane = new Vector4(m_normal.x, m_normal.y, m_normal.z, DotProduct);
m_reflection = Matrix4x4.zero;
CalculateReflectionMatrix(ref m_reflection, ReflectionPlane);
m_oldPosition = m_RenderCamera.transform.localPosition;
m_newPosition = m_reflection.MultiplyPoint(m_oldPosition);
m_reflectionCamera.worldToCameraMatrix = m_RenderCamera.worldToCameraMatrix * m_reflection;
m_clipPlane = CameraSpacePlane(profile, m_reflectionCamera, m_worldPosition, m_normal, 1.0f);
m_projection = m_RenderCamera.CalculateObliqueMatrix(m_clipPlane);
m_reflectionCamera.projectionMatrix = m_projection;
if (!reflectionsEnabled)
{
m_reflectionCamera.cullingMask = 0;
}
else
{
m_reflectionCamera.cullingMask = ~(1 << 1) & ~(1 << 2) & ~(1 << 4) & ~(2 << 4) & profile.m_reflectedLayers.value;
profile.m_reflectedLayers.value = m_reflectionCamera.cullingMask;
if (profile.m_useCustomRenderDistance)
{
if (profile.m_enableLayerDistances)
{
m_reflectionCamera.layerCullDistances = profile.m_customRenderDistances;
m_reflectionCamera.layerCullSpherical = true;
}
else
{
float[] distances = new float[32];
for (int idx = 0; idx < distances.Length; idx++)
{
distances[idx] = profile.m_customRenderDistance;
}
m_reflectionCamera.layerCullDistances = distances;
m_reflectionCamera.layerCullSpherical = true;
}
}
else
{
m_reflectionCamera.layerCullDistances = m_RenderCamera.layerCullDistances;
m_reflectionCamera.layerCullSpherical = true;
}
}
m_reflectionCamera.targetTexture = m_reflectionTexture;
GL.invertCulling = true;
m_reflectionCamera.transform.position = m_newPosition;
m_euler = m_RenderCamera.transform.eulerAngles;
#if GAIA_XR
//m_reflectionCamera.transform.eulerAngles = new Vector3(m_euler.x, m_euler.y, m_euler.z);
m_reflectionCamera.transform.eulerAngles = Vector3.zero;
#else
m_reflectionCamera.transform.eulerAngles = new Vector3(0, m_euler.y, m_euler.z);
#endif
if (profile.m_useHDR)
{
m_reflectionCamera.allowHDR = true;
}
m_reflectionCamera.nearClipPlane = 0.001f;
m_reflectionCamera.Render();
m_reflectionCamera.transform.position = m_oldPosition;
GL.invertCulling = false;
SetReflectionTexture();
}
public void SetReflectionTexture(Texture overrideTex = null)
{
if (m_waterMaterial != null)
{
if (overrideTex != null)
{
m_waterMaterial.SetTexture(GaiaShaderID.m_globalReflectionTexture, overrideTex);
}
else
{
m_waterMaterial.SetTexture(GaiaShaderID.m_globalReflectionTexture, m_reflectionTexture);
}
}
}
///
/// Removes built-in reflection camera
///
///
private void RemoveBuiltInReflectionCamera(Camera cam)
{
if (cam != null)
{
DestroyImmediate(cam.gameObject);
}
}
#region URP
///
/// Creates the planar reflections for URP and resyncs the settings
///
private void UpdateURPPlanarReflections()
{
if (m_planarReflections == null)
{
m_planarReflections = CreatePlanarReflections(false);
}
ResyncPlanarReflectionSettings();
}
///
/// Creates a gaia planar reflections
///
///
///
private GaiaPlanarReflections CreatePlanarReflections(bool hideObject = true)
{
GaiaPlanarReflections planarReflections = FindObjectOfType();
if (planarReflections == null)
{
GameObject planarObject = new GameObject(GaiaConstants.gaiaPlanarReflections);
planarReflections = planarObject.AddComponent();
planarObject.transform.SetParent(gameObject.transform);
if (hideObject)
{
planarObject.hideFlags = HideFlags.HideInHierarchy;
}
else
{
planarObject.hideFlags = HideFlags.None;
}
}
ResyncPlanarReflectionSettings();
return planarReflections;
}
///
/// Resyncs the planar reflection settings
///
private void ResyncPlanarReflectionSettings()
{
if (m_planarReflections != null && m_waterProfile != null)
{
m_waterProfile.m_reflectionSettingsData.m_ReflectLayers = m_waterProfile.m_reflectedLayers;
m_waterProfile.m_reflectionSettingsData.m_textureResolution = m_waterProfile.m_textureResolution;
m_planarReflections.m_settings = m_waterProfile.m_reflectionSettingsData;
}
}
///
/// Removes URP planar reflections
///
private void RemoveURPPlanarReflections()
{
if (m_planarReflections != null)
{
DestroyImmediate(m_planarReflections.gameObject);
}
GameObject planarReflectionsCamera = GameObject.Find(GaiaConstants.gaiaPlanarReflectionsCamera);
if (planarReflectionsCamera != null)
{
DestroyImmediate(planarReflectionsCamera);
}
}
#endregion
#region HDRP
///
/// Creates the planar reflections for HDRP and resyncs the settings
///
private void UpdateHDPPlanarReflections()
{
#if HDPipeline
if (m_HDPlanarReflections == null)
{
m_HDPlanarReflections = CreateHDRPPlanarReflections(false);
}
ResyncHDRPPlanarReflectionSettings();
#endif
}
///
/// Creates a HDRP planar reflections
///
///
///
#if HDPipeline
private PlanarReflectionProbe CreateHDRPPlanarReflections(bool hideObject = true)
{
GameObject planarObject = GameObject.Find(GaiaConstants.gaiaHDRPPlanarReflections);
if (planarObject == null)
{
planarObject = new GameObject(GaiaConstants.gaiaHDRPPlanarReflections);
planarObject.transform.SetParent(gameObject.transform);
if (hideObject)
{
planarObject.hideFlags = HideFlags.HideInHierarchy;
}
else
{
planarObject.hideFlags = HideFlags.None;
}
}
PlanarReflectionProbe planarReflections = planarObject.GetComponent();
if (planarReflections == null)
{
planarReflections = planarObject.AddComponent();
}
ProbeSettings settings = planarReflections.settings;
settings.influence.boxSize = new Vector3(10000f, 5f, 10000f);
settings.realtimeMode = ProbeSettings.RealtimeMode.EveryFrame;
ResyncHDRPPlanarReflectionSettings();
return planarReflections;
}
#endif
///
/// Resyncs the HDRP planar reflection settings
///
private void ResyncHDRPPlanarReflectionSettings()
{
#if HDPipeline
if (m_HDPlanarReflections != null && m_waterProfile != null)
{
ProbeSettings settings = m_HDPlanarReflections.settings;
settings.influence.boxSize = new Vector3(10000f, 5f, 10000f);
settings.realtimeMode = ProbeSettings.RealtimeMode.EveryFrame;
settings.cameraSettings.culling.cullingMask = ~(1 << 4) & m_waterProfile.m_reflectedLayers.value;
settings.cameraSettings.culling.useOcclusionCulling = false;
m_HDPlanarReflections.transform.position = new Vector3(0f, SeaLevel, 0f);
}
#endif
}
///
/// Removes URP planar reflections
///
private void RemoveHDPRPlanarReflections()
{
GameObject hdrpReflections = GameObject.Find(GaiaConstants.gaiaHDRPPlanarReflections);
if (hdrpReflections != null)
{
DestroyImmediate(hdrpReflections);
}
}
#endregion
#endregion
#region Shader Functions
///
/// Updates the water shader values
///
public void UpdateShaderValues(GaiaWaterProfileValues profileValues)
{
#if GAIA_PRO_PRESENT
if (!Application.isPlaying)
{
m_weatherSystemPresent = ProceduralWorldsGlobalWeather.Instance;
WeatherSystem = ProceduralWorldsGlobalWeather.Instance;
}
#endif
if (m_waterMaterial == null)
{
foreach (var material in m_waterMaterialInstances)
{
if (!material.name.Contains("Under"))
{
m_waterMaterial = m_waterMaterialInstances[0];
break;
}
}
}
else
{
if (GaiaUtils.ValidateShaderProperty(m_waterMaterial, GaiaShaderID.m_waterGrabPass))
{
m_waterMaterial.SetShaderPassEnabled(GaiaShaderID.m_waterGrabPass, true);
}
if (RenderPipeline == GaiaConstants.EnvironmentRenderer.HighDefinition)
{
if (GaiaUtils.ValidateShaderProperty(m_waterMaterial, GaiaShaderID.m_hdrpZTest))
{
m_waterMaterial.SetInt(GaiaShaderID.m_hdrpZTest, (int)GaiaConstants.HDRPDepthTest.LessEqual);
}
}
if (GaiaUtils.ValidateShaderProperty(m_waterMaterial, GaiaShaderID.m_globalAmbientColor))
{
m_waterMaterial.SetColor(GaiaShaderID.m_globalAmbientColor, RenderSettings.ambientSkyColor);
}
#if GAIA_PRO_PRESENT
if (m_weatherSystemPresent)
{
if (WeatherSystem.CheckIsNight())
{
if (WeatherSystem.m_moonLight != null)
{
SunLight = WeatherSystem.m_moonLight;
if (GaiaUtils.ValidateShaderProperty(m_waterMaterial, GaiaShaderID.m_globalLightDirection))
{
m_waterMaterial.SetVector(GaiaShaderID.m_globalLightDirection, -WeatherSystem.m_moonLight.transform.forward);
}
if (GaiaUtils.ValidateShaderProperty(m_waterMaterial, GaiaShaderID.m_globalLightColor))
{
m_waterMaterial.SetColor(GaiaShaderID.m_globalLightColor, WeatherSystem.m_moonLight.color);
}
if (GaiaUtils.ValidateShaderProperty(m_waterMaterial, GaiaShaderID.m_globalLightIntensity))
{
m_waterMaterial.SetFloat(GaiaShaderID.m_globalLightIntensity, WeatherSystem.m_moonLight.intensity);
}
}
}
else
{
if (WeatherSystem.m_sunLight != null)
{
SunLight = WeatherSystem.m_sunLight;
if (GaiaUtils.ValidateShaderProperty(m_waterMaterial, GaiaShaderID.m_globalLightDirection))
{
m_waterMaterial.SetVector(GaiaShaderID.m_globalLightDirection, -WeatherSystem.m_sunLight.transform.forward);
}
if (GaiaUtils.ValidateShaderProperty(m_waterMaterial, GaiaShaderID.m_globalLightColor))
{
m_waterMaterial.SetColor(GaiaShaderID.m_globalLightColor, WeatherSystem.m_sunLight.color);
}
if (GaiaUtils.ValidateShaderProperty(m_waterMaterial, GaiaShaderID.m_globalLightIntensity))
{
m_waterMaterial.SetFloat(GaiaShaderID.m_globalLightIntensity, WeatherSystem.m_sunLight.intensity);
}
}
}
}
else
{
if (SunLight != null)
{
if (GaiaUtils.ValidateShaderProperty(m_waterMaterial, GaiaShaderID.m_globalLightDirection))
{
m_waterMaterial.SetVector(GaiaShaderID.m_globalLightDirection, -SunLight.transform.forward);
}
if (GaiaUtils.ValidateShaderProperty(m_waterMaterial, GaiaShaderID.m_globalLightColor))
{
m_waterMaterial.SetColor(GaiaShaderID.m_globalLightColor, SunLight.color);
}
if (GaiaUtils.ValidateShaderProperty(m_waterMaterial, GaiaShaderID.m_globalLightIntensity))
{
m_waterMaterial.SetFloat(GaiaShaderID.m_globalLightIntensity, SunLight.intensity);
}
}
}
#else
if (SunLight != null)
{
if (GaiaUtils.ValidateShaderProperty(m_waterMaterial, GaiaShaderID.m_globalLightDirection))
{
m_waterMaterial.SetVector(GaiaShaderID.m_globalLightDirection, -SunLight.transform.forward);
}
if (GaiaUtils.ValidateShaderProperty(m_waterMaterial, GaiaShaderID.m_globalLightColor))
{
m_waterMaterial.SetColor(GaiaShaderID.m_globalLightColor, SunLight.color);
}
if (GaiaUtils.ValidateShaderProperty(m_waterMaterial, GaiaShaderID.m_globalLightIntensity))
{
m_waterMaterial.SetFloat(GaiaShaderID.m_globalLightIntensity, SunLight.intensity);
}
}
#endif
}
}
///
/// Sets the sun light on the water system
///
///
public static void SetSunLight(Light light)
{
if (light == null)
{
return;
}
if (Instance == null)
{
return;
}
Instance.SunLight = light;
}
#endregion
#endregion
#region Underwater/Refraction Setup
//Public
public void RefractionInit()
{
if (refractionEnabled)
{
Shader.EnableKeyword(GaiaShaderID.m_refractionOn);
Shader.SetGlobalInt(GaiaShaderID.m_blendSRC, (int)UnityEngine.Rendering.BlendMode.One);
Shader.SetGlobalInt(GaiaShaderID.m_blendDST, (int)UnityEngine.Rendering.BlendMode.Zero);
}
else
{
Shader.DisableKeyword(GaiaShaderID.m_refractionOn);
Shader.SetGlobalInt(GaiaShaderID.m_blendSRC, (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
Shader.SetGlobalInt(GaiaShaderID.m_blendDST, (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
}
}
//Private
private void SendWindDirection()
{
Vector2 dir = (Vector2) ( Quaternion.Euler ( 0, 0, directionAngle ) * Vector2.right );
Vector4 vec4Dir = Vector4.zero;
vec4Dir.x = dir.x;
vec4Dir.z = dir.y;
m_waterMaterial.SetVector (GaiaShaderID._waveDirection_ID, vec4Dir );
m_waterMaterial.SetVector (GaiaShaderID._waveDirection_ID, vec4Dir );
}
private void SendWaterEdge()
{
m_waterMaterial.SetVector (GaiaShaderID._edgeWaterColor_ID, m_waterMaterial.GetVector (GaiaShaderID._edgeWaterColor_ID ) );
m_waterMaterial.SetFloat (GaiaShaderID._edgeWaterDist_ID, m_waterMaterial.GetFloat (GaiaShaderID._edgeWaterDist_ID ));
}
private void SendNormalMaps()
{
m_waterMaterial.SetTexture (GaiaShaderID._normalLayer0_ID, m_waterMaterial.GetTexture (GaiaShaderID._normalLayer0_ID ) );
m_waterMaterial.SetTexture (GaiaShaderID._normalLayer1_ID, m_waterMaterial.GetTexture (GaiaShaderID._normalLayer1_ID ) );
}
private void SendWaveData()
{
m_waterMaterial.SetFloat (GaiaShaderID._normalLayer0_ID, m_waterMaterial.GetFloat (GaiaShaderID._normalLayer0Scale_ID ) );
m_waterMaterial.SetFloat (GaiaShaderID._normalLayer1_ID, m_waterMaterial.GetFloat (GaiaShaderID._normalLayer1Scale_ID ) );
m_waterMaterial.SetFloat (GaiaShaderID._normalTile_ID, m_waterMaterial.GetFloat (GaiaShaderID._normalTile_ID ) );
m_waterMaterial.SetFloat (GaiaShaderID._waveShoreClamp_ID, m_waterMaterial.GetFloat (GaiaShaderID._waveShoreClamp_ID ) );
m_waterMaterial.SetFloat (GaiaShaderID._waveLength_ID, m_waterMaterial.GetFloat (GaiaShaderID._waveLength_ID ) );
m_waterMaterial.SetFloat (GaiaShaderID._waveSteepness_ID, m_waterMaterial.GetFloat (GaiaShaderID._waveSteepness_ID ) );
m_waterMaterial.SetFloat (GaiaShaderID._waveSpeed_ID, m_waterMaterial.GetFloat (GaiaShaderID._waveSpeed_ID ) );
m_waterMaterial.SetVector (GaiaShaderID._waveDirection_ID, m_waterMaterial.GetVector (GaiaShaderID._waveDirection_ID ) );
}
#endregion
#region Mesh Generation
#region WaterGeneration
///
/// Creates a procedural mesh with a vertex count and size.
///
public void ProceduralMeshGeneration()
{
SizeGeneration();
if (m_MeshType == GaiaConstants.MeshType.Plane)
{
if (m_uvScale.y <= 0 || m_uvScale.x <= 0 || m_sizeScale.x <= 0 || m_sizeScale.y <= 0)
{
Debug.Log("Size was 0, unable to generate mesh");
return;
}
}
if (CalculatePolysRequired() == 0)
{
Debug.LogWarning("The selected water size is too small for the selected water mesh quality. Please increase water size and / or water mesh quality.");
return;
}
if (!GetComponent())
{
Debug.Log("Warning Mesh Render is missing for the water generator");
}
if (GetComponent())
{
MeshFilter meshFilter = GetComponent();
m_generateMesh = new Mesh
{
name = "Procedural Grid"
};
VerticesGeneration();
TriangleGeneration();
UVGeneration();
NormalGeneration();
BoundsGeneration();
meshFilter.mesh = m_generateMesh;
ClearMeshData();
}
else
{
Debug.Log("unable to find MeshFilter, unable to generate mesh");
}
}
#endregion
#region MeshGeneration
///
/// Size Generation for a given object
///
private void SizeGeneration()
{
if (m_MeshType == GaiaConstants.MeshType.Plane)
{
m_numberOfPoints = new Vector2Int(Mathf.RoundToInt(m_meshDensity.x / 40 * m_Size.x) +1, Mathf.RoundToInt(m_meshDensity.y / 40 * m_Size.z)+1);
m_uvScale = new Vector2(1f / (m_numberOfPoints.x), 1f / (m_numberOfPoints.y));
m_sizeScale = new Vector3(m_Size.x / (m_numberOfPoints.x -1), m_Size.y, m_Size.z / (m_numberOfPoints.y -1));
}
else
{
float half = m_Size.x / 2f;
m_numberOfPoints = new Vector2Int(Mathf.RoundToInt(m_meshDensity.x / 40 * half), Mathf.RoundToInt(m_meshDensity.y / 40 * half));
m_uvScale = new Vector2(1f / (m_meshDensity.x), 1f / (m_meshDensity.x));
m_sizeScale = new Vector3(half / (m_numberOfPoints.x), m_Size.y, half / (m_numberOfPoints.y));
//m_sizeScale = new Vector3(half / (m_meshDensity.x), m_Size.y, half / (m_meshDensity.x));
}
}
///
/// Generates the vertices
///
private void VerticesGeneration()
{
if (m_MeshType == GaiaConstants.MeshType.Plane)
{
var MiddlePoint = new Vector3((float)(m_numberOfPoints.x -1) / 2, 0, (float)(m_numberOfPoints.y -1) / 2);
for (int y = 0; y < (int)m_numberOfPoints.y ; y++)
{
for (int x = 0; x < (int)m_numberOfPoints.x; x++)
{
Vector3 vertex = new Vector3(MiddlePoint.x - x, m_height, MiddlePoint.z - y);
m_vertices.Add(Vector3.Scale(m_sizeScale, vertex));
}
}
//Determine number of vertices for mesh index format
if (m_vertices.Count < 64000)
{
m_generateMesh.indexFormat = IndexFormat.UInt16;
}
else
{
m_generateMesh.indexFormat = IndexFormat.UInt32;
}
m_generateMesh.vertices = m_vertices.ToArray();
}
else
{
m_vertices.Add(Vector3.Scale(m_sizeScale, Vector3.zero));
for (int CirclePoint = 0; CirclePoint < m_numberOfPoints.x; CirclePoint++)
{
//angle step is the next position in the circle to iterate over.
//Mathf.PI one side, *2 both sides
float angleStep = (Mathf.PI * 2f) / ((CirclePoint + 1) * 6);
for (int point = 0; point < (CirclePoint + 1) * 6; point++)
{
Vector3 vertex = new Vector3(Mathf.Cos(angleStep * point), 0, Mathf.Sin(-angleStep * point));
vertex = vertex * 1 * (CirclePoint + 1);
m_vertices.Add(Vector3.Scale(m_sizeScale, vertex));
}
}
//Determine number of vertices for mesh index format
if (m_vertices.Count < 64000)
{
m_generateMesh.indexFormat = IndexFormat.UInt16;
}
else
{
m_generateMesh.indexFormat = IndexFormat.UInt32;
}
m_generateMesh.vertices = m_vertices.ToArray();
}
}
///
/// Generates the Triangles
///
private void TriangleGeneration()
{
if (m_MeshType == GaiaConstants.MeshType.Plane)
{
int x, y;
for (y = 0; y < (int)m_numberOfPoints.y - 1; y++)
{
for (x = 0; x < (int)m_numberOfPoints.x - 1; x++)
{
// For each grid cell output two triangles
m_triangles.Add((y * (int)m_numberOfPoints.x) + x);
m_triangles.Add(((y + 1) * (int)m_numberOfPoints.x) + x);
m_triangles.Add((y * (int)m_numberOfPoints.x) + x + 1);
m_triangles.Add(((y + 1) * (int)m_numberOfPoints.x) + x);
m_triangles.Add(((y + 1) * (int)m_numberOfPoints.x) + x + 1);
m_triangles.Add((y * (int)m_numberOfPoints.x) + x + 1);
}
}
m_generateMesh.triangles = m_triangles.ToArray();
}
else
{
m_triangles.Clear();
for (int circ = 0; circ < (int)m_numberOfPoints.x; circ++)
{
for (int point = 0, other = 0; point < (circ + 1) * 6; point++)
{
if (point % (circ + 1) != 0)
{
// Creates 2 triangles (square generation)
m_triangles.Add(GetPoint(circ - 1, other + 1));
m_triangles.Add(GetPoint(circ - 1, other));
m_triangles.Add(GetPoint(circ, point));
//second triangle
m_triangles.Add(GetPoint(circ, point));
m_triangles.Add(GetPoint(circ, point + 1));
m_triangles.Add(GetPoint(circ - 1, other + 1));
++other;
}
else
{
// Creates the triangles for sections in the core and 4 break up points.
m_triangles.Add(GetPoint(circ, point));
m_triangles.Add(GetPoint(circ, point + 1));
m_triangles.Add(GetPoint(circ - 1, other));
// Do not move to the next point in the smaller circles
}
}
}
m_generateMesh.triangles = m_triangles.ToArray();
}
}
///
/// Calculates the normal of the mesh
///
private void NormalGeneration()
{
m_generateMesh.RecalculateNormals();
}
///
/// Generates the UV map for the mesh
///
private void UVGeneration()
{
if (m_MeshType == GaiaConstants.MeshType.Plane)
{
Vector2 MiddlePoint = new Vector2(m_numberOfPoints.x / 2, m_numberOfPoints.y / 2);
for (int y = 0; y < (int)m_numberOfPoints.y; y++)
{
for (int x = 0; x < (int)m_numberOfPoints.x; x++)
{
m_uvs.Add(Vector2.Scale(new Vector2(MiddlePoint.x - x, MiddlePoint.y- y), m_uvScale));
}
}
m_generateMesh.uv = m_uvs.ToArray();
}
else
{
m_uvs.Add(Vector2.Scale(m_uvScale, Vector2.zero));
for (int CirclePoint = 0; CirclePoint < m_numberOfPoints.x; CirclePoint++)
{
float angleStep = (Mathf.PI * 2f) / ((CirclePoint + 1) * 6);
for (int point = 0; point < (CirclePoint + 1) * 6; point++)
{
Vector2 vertex = new Vector2(Mathf.Cos(angleStep * point), Mathf.Sin(-angleStep * point));
vertex = vertex * 1 * (CirclePoint + 1);
m_uvs.Add(Vector2.Scale(vertex, m_uvScale));
}
}
m_generateMesh.uv = m_uvs.ToArray();
}
}
///
/// Generates the bounds of the mesh
///
private void BoundsGeneration()
{
m_generateMesh.RecalculateBounds();
}
#endregion
#region ClearMemory
///
/// Clears memory of lists and arrays
///
public void ClearMeshData()
{
m_vertices.Clear();
m_uvs.Clear();
m_triangles.Clear();
}
#endregion
#region Point Calculuation
///
/// Gets the point on a circle
///
///
///
///
private static int GetPoint(int Center, int Extent)
{
// In case of center point no calculation needed
if (Center < 0)
{
return 0;
}
Extent = Extent % ((Center + 1) * 6);
// Make the point index circular
// Explanation: index = number of points in previous circles + central point + x
// hence: (0+1+2+...+c)*6+x+1 = ((c/2)*(c+1))*6+x+1 = 3*c*(c+1)+x+1
return (3 * Center * (Center + 1) + Extent + 1);
}
#endregion
#region DensityCalculation
///
/// Calculate the real amount of triangles.
/// dependent on MeshType selected.
///
/// total triangle count
public int CalculatePolysRequired()
{
SizeGeneration();
if (m_MeshType == GaiaConstants.MeshType.Plane)
{
return (int)(m_numberOfPoints.y-1) * (int)(m_numberOfPoints.x-1) *2;
}
else
{
return (int)m_numberOfPoints.x * ((int)m_numberOfPoints.x) * 6;
}
}
#endregion
#endregion
}
}