177 lines
6.0 KiB
C#
177 lines
6.0 KiB
C#
// Crest Ocean System
|
|
|
|
// Copyright 2020 Wave Harmonic Ltd
|
|
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
|
|
namespace Crest
|
|
{
|
|
/// <summary>
|
|
/// Provides out-scattering based on the camera's underwater depth. It scales down environmental lighting
|
|
/// (directional light, reflections, ambient etc) with the underwater depth. This works with vanilla lighting, but
|
|
/// uncommon or custom lighting will require a custom solution (use this for reference).
|
|
/// </summary>
|
|
[AddComponentMenu(Internal.Constants.MENU_PREFIX_EXAMPLE + "Underwater Environmental Lighting")]
|
|
public class UnderwaterEnvironmentalLighting : CustomMonoBehaviour
|
|
{
|
|
/// <summary>
|
|
/// The version of this asset. Can be used to migrate across versions. This value should
|
|
/// only be changed when the editor upgrades the version.
|
|
/// </summary>
|
|
[SerializeField, HideInInspector]
|
|
#pragma warning disable 414
|
|
int _version = 0;
|
|
#pragma warning restore 414
|
|
|
|
[Tooltip("How much this effect applies. Values less than 1 attenuate light less underwater. Value of 1 is physically based."), SerializeField, Range(0f, 3f)]
|
|
float _weight = 1f;
|
|
|
|
#if CREST_SRP
|
|
[RenderPipeline(RenderPipeline.HighDefinition), DecoratedField]
|
|
[Tooltip("This profile will be weighed in the deeper underwater the camera goes."), SerializeField]
|
|
VolumeProfile _volumeProfile = null;
|
|
|
|
static Volume _volume;
|
|
#endif
|
|
|
|
Light _primaryLight;
|
|
float _lightIntensity;
|
|
float _ambientIntensity;
|
|
float _reflectionIntensity;
|
|
float _fogDensity;
|
|
|
|
float _averageDensity = 0f;
|
|
|
|
public const float DEPTH_OUTSCATTER_CONSTANT = 0.25f;
|
|
|
|
bool _isInitialised = false;
|
|
|
|
void OnEnable()
|
|
{
|
|
if (OceanRenderer.Instance == null)
|
|
{
|
|
enabled = false;
|
|
return;
|
|
}
|
|
|
|
// Check to make sure the property exists. We might be using a test material.
|
|
if (!OceanRenderer.Instance.OceanMaterial.HasProperty("_DepthFogDensity"))
|
|
{
|
|
enabled = false;
|
|
return;
|
|
}
|
|
|
|
_primaryLight = OceanRenderer.Instance._primaryLight;
|
|
|
|
// Store lighting settings
|
|
if (_primaryLight)
|
|
{
|
|
_lightIntensity = _primaryLight.intensity;
|
|
}
|
|
_ambientIntensity = RenderSettings.ambientIntensity;
|
|
_reflectionIntensity = RenderSettings.reflectionIntensity;
|
|
_fogDensity = RenderSettings.fogDensity;
|
|
#if CREST_SRP
|
|
// Only on HDRP so far...
|
|
if (_volume == null && RenderPipelineHelper.IsHighDefinition)
|
|
{
|
|
// Create volume to weigh in underwater profile
|
|
var go = new GameObject();
|
|
go.transform.parent = OceanRenderer.Instance.Container.transform;
|
|
go.hideFlags = HideFlags.HideAndDontSave;
|
|
go.name = "Underwater Lighting Volume";
|
|
_volume = go.AddComponent<Volume>();
|
|
_volume.weight = 0;
|
|
_volume.priority = 1000;
|
|
_volume.profile = _volumeProfile;
|
|
}
|
|
#endif
|
|
|
|
var density = OceanRenderer.Instance.UnderwaterDepthFogDensity;
|
|
_averageDensity = (density.x + density.y + density.z) / 3f;
|
|
|
|
_isInitialised = true;
|
|
}
|
|
|
|
void OnDisable()
|
|
{
|
|
if (!_isInitialised)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Restore lighting settings
|
|
if (_primaryLight)
|
|
{
|
|
_primaryLight.intensity = _lightIntensity;
|
|
}
|
|
RenderSettings.ambientIntensity = _ambientIntensity;
|
|
RenderSettings.reflectionIntensity = _reflectionIntensity;
|
|
RenderSettings.fogDensity = _fogDensity;
|
|
|
|
#if CREST_SRP
|
|
if (_volume != null)
|
|
{
|
|
_volume.weight = 0;
|
|
}
|
|
#endif
|
|
|
|
_isInitialised = false;
|
|
}
|
|
|
|
void LateUpdate()
|
|
{
|
|
if (OceanRenderer.Instance == null || UnderwaterRenderer.Instance == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var density = OceanRenderer.Instance.UnderwaterDepthFogDensity;
|
|
_averageDensity = (density.x + density.y + density.z) / 3f;
|
|
|
|
float depthMultiplier = Mathf.Exp(_averageDensity *
|
|
Mathf.Min(OceanRenderer.Instance.ViewerHeightAboveWater * DEPTH_OUTSCATTER_CONSTANT, 0f) *
|
|
_weight);
|
|
|
|
// Darken environmental lighting when viewer underwater
|
|
if (_primaryLight)
|
|
{
|
|
_primaryLight.intensity = Mathf.Lerp(0, _lightIntensity, depthMultiplier);
|
|
}
|
|
RenderSettings.ambientIntensity = Mathf.Lerp(0, _ambientIntensity, depthMultiplier);
|
|
RenderSettings.reflectionIntensity = Mathf.Lerp(0, _reflectionIntensity, depthMultiplier);
|
|
RenderSettings.fogDensity = Mathf.Lerp(0, _fogDensity, depthMultiplier);
|
|
|
|
#if CREST_SRP
|
|
if (_volume != null)
|
|
{
|
|
_volume.weight = 1f - depthMultiplier;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
[CustomEditor(typeof(UnderwaterEnvironmentalLighting))]
|
|
public class UnderwaterEnvironmentalLightingEditor : CustomBaseEditor
|
|
{
|
|
public override void OnInspectorGUI()
|
|
{
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.HelpBox("This is an example component that will likely require modification to work " +
|
|
"correctly with your project. It implements out-scattering when underwater. It does so, primarily, " +
|
|
"by changing the intensity of the primary light. The deeper underwater, the less intense the light. " +
|
|
"There may be unsuitable performance costs or required features to be enabled.", MessageType.Info);
|
|
EditorGUILayout.Space();
|
|
|
|
base.OnInspectorGUI();
|
|
}
|
|
}
|
|
#endif
|
|
}
|