123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- namespace VolumetricFogAndMist2 {
- public delegate void OnSettingsChanged();
- [CreateAssetMenu(menuName = "Volumetric Fog \x8B& Mist/Fog Profile", fileName = "VolumetricFogProfile", order = 1001)]
- public class VolumetricFogProfile : ScriptableObject {
- [Header("Rendering")]
- [Range(1, 16)] public int raymarchQuality = 6;
- [Tooltip("Determines the minimum step size. Increase to improve performance / decrease to improve accuracy. When increasing this value, you can also increase 'Jittering' amount to improve quality.")]
- public float raymarchMinStep = 0.1f;
- public float jittering = 0.5f;
- [Range(0, 2)] public float dithering = 1f;
- [Tooltip("The render queue for this renderer. By default, all transparent objects use a render queue of 3000. Use a lower value to render before all transparent objects.")]
- public int renderQueue = 3100;
- [Tooltip("Optional sorting layer Id (number) for this renderer. By default 0. Usually used to control the order with other transparent renderers, like Sprite Renderer.")]
- public int sortingLayerID;
- [Tooltip("Optional sorting order for this renderer. Used to control the order with other transparent renderers, like Sprite Renderer.")]
- public int sortingOrder;
- [Header("Density")]
- [Tooltip("Do not use any noise at all")]
- public bool constantDensity;
- public Texture2D noiseTexture;
- [Range(0, 3)] public float noiseStrength = 1f;
- public float noiseScale = 15f;
- public float noiseFinalMultiplier = 1f;
- public bool useDetailNoise;
- public Texture3D detailTexture;
- public float detailScale = 0.35f;
- [Range(0, 1f)] public float detailStrength = 0.5f;
- public float detailOffset = -0.5f;
- public float density = 1f;
- [Header("Geometry")]
- public VolumetricFogShape shape = VolumetricFogShape.Box;
- [Range(0, 1f)] public float border = 0.05f;
- [Tooltip("Ignores volume height and use a custom height defined by this profile")]
- public bool customHeight;
- public float height;
- public float verticalOffset;
- [Tooltip("When enabled, makes fog appear at certain distance from a camera")]
- public float distance;
- [Range(0, 1)] public float distanceFallOff = 0.93f;
- [Tooltip("Maximum distance from camera")]
- public float maxDistance = 10000;
- [Range(0, 1)]
- public float maxDistanceFallOff;
- [Tooltip("Fits the fog altitude to the terrain heightmap")]
- public bool terrainFit;
- public VolumetricFog.HeightmapCaptureResolution terrainFitResolution = VolumetricFog.HeightmapCaptureResolution._128;
- [Tooltip("Which objects will be included in the heightmap capture. By default all objects are included but you may want to restrict this to just the terrain.")]
- public LayerMask terrainLayerMask = -1;
- [Tooltip("The height of fog above terrain surface.")]
- public float terrainFogHeight = 25f;
- public float terrainFogMinAltitude;
- public float terrainFogMaxAltitude = 150f;
- [Header("Colors")]
- [ColorUsage(showAlpha: false)]
- public Color albedo = new Color32(227, 227, 227, 255);
- public bool enableDepthGradient;
- [GradientUsage(hdr: true, ColorSpace.Linear)] public Gradient depthGradient;
- public float depthGradientMaxDistance = 1000f;
- public bool enableHeightGradient;
- [GradientUsage(hdr: true, ColorSpace.Linear)] public Gradient heightGradient;
- public float brightness = 1f;
- [Range(0, 2)] public float deepObscurance = 1f;
- public Color specularColor = new Color(1, 1, 0.8f, 1);
- [Range(0, 1f)] public float specularThreshold = 0.637f;
- [Range(0, 1f)] public float specularIntensity = 0.428f;
- [Header("Animation")]
- public float turbulence = 0.73f;
- public Vector3 windDirection = new Vector3(0.02f, 0, 0);
- public bool useCustomDetailNoiseWindDirection;
- public Vector3 detailNoiseWindDirection = new Vector3(0.02f, 0, 0);
- [Header("Directional Light")]
- [Tooltip("Enable to synchronize fog light intensity and color with the Sun and the Moon (must be assigned into Volumetric Fog Manager)")]
- public bool dayNightCycle = true;
- [Tooltip("When day/night cycle option is disabled, customize the direction of the Sun light.")]
- public Vector3 sunDirection = Vector3.up;
- [Tooltip("Custom sun color when day/night cycle is disabled")]
- public Color sunColor = new Color(0, 0.9568f, 0.8392f);
- [Tooltip("Custom sun intensity when day/night cycle is disabled")]
- public float sunIntensity = 1f;
- [Tooltip("Ambient light influence")]
- public float ambientLightMultiplier;
- [Range(0, 64)] public float lightDiffusionPower = 32;
- [Range(0, 1)] public float lightDiffusionIntensity = 0.4f;
- public bool receiveShadows;
- [Range(0, 1)] public float shadowIntensity = 0.5f;
- [Tooltip("Removes shadowed fog")]
- [Range(0, 1)] public float shadowCancellation;
- public float shadowMaxDistance = 250f;
- [Tooltip("Uses the directional light cookie")]
- public bool cookie;
- [Header("Distant Fog")]
- [Tooltip("Enables exponential distant fog. Use this option to cover horizon/sky/far distances with optimal performance")]
- public bool distantFog;
- public float distantFogStartDistance = 1000f;
- public float distantFogDistanceDensity = 0.5f;
- public float distantFogMaxHeight = 4000;
- public float distantFogHeightDensity = 0.5f;
- public Color distantFogColor = new Color(0.358f, 0.358f, 0.358f);
- public float distantFogDiffusionIntensity = 0.4f;
- public int distantFogRenderQueue = 2999;
- public event OnSettingsChanged onSettingsChanged;
- [NonSerialized]
- public Texture2D depthGradientTex;
- [NonSerialized]
- public Texture2D heightGradientTex;
- Color[] depthGradientColors;
- Color[] heightGradientColors;
- private void OnEnable() {
- if (noiseTexture == null) {
- noiseTexture = Resources.Load<Texture2D>("Textures/NoiseTex256");
- }
- if (detailTexture == null) {
- detailTexture = Resources.Load<Texture3D>("Textures/NoiseTex3D");
- }
- ValidateSettings();
- }
- private void OnValidate() {
- ValidateSettings();
- if (onSettingsChanged != null) {
- #if UNITY_EDITOR
- UnityEditor.EditorApplication.delayCall += () => {
- try {
- onSettingsChanged();
- UnityEditor.EditorApplication.delayCall += () => UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
- } catch { }
- };
- #else
- onSettingsChanged();
- #endif
- }
- }
- public void ValidateSettings() {
- distance = Mathf.Max(0, distance);
- density = Mathf.Max(0, density);
- noiseScale = Mathf.Max(0.1f, noiseScale);
- noiseFinalMultiplier = Mathf.Max(0, noiseFinalMultiplier);
- detailScale = Mathf.Max(0.01f, detailScale);
- raymarchMinStep = Mathf.Max(0.1f, raymarchMinStep);
- jittering = Mathf.Max(0, jittering);
- terrainFogHeight = Mathf.Max(0, terrainFogHeight);
- height = Mathf.Max(0, height);
- if (depthGradient == null) {
- depthGradient = new Gradient();
- depthGradient.colorKeys = new GradientColorKey[] {
- new GradientColorKey(Color.white, 0),
- new GradientColorKey(Color.white, 1)
- };
- }
- maxDistance = Mathf.Max(0.0001f, maxDistance);
- depthGradientMaxDistance = Mathf.Max(0, depthGradientMaxDistance);
- ambientLightMultiplier = Mathf.Max(0, ambientLightMultiplier);
- sunIntensity = Mathf.Max(0, sunIntensity);
- shadowMaxDistance = Mathf.Max(0, shadowMaxDistance);
- distantFogStartDistance = Mathf.Max(0, distantFogStartDistance);
- distantFogDistanceDensity = Mathf.Max(0, distantFogDistanceDensity);
- distantFogMaxHeight = Mathf.Max(0, distantFogMaxHeight);
- distantFogHeightDensity = Mathf.Max(0, distantFogHeightDensity);
- distantFogDiffusionIntensity = Mathf.Max(0, distantFogDiffusionIntensity);
- if (enableDepthGradient) {
- const int DEPTH_GRADIENT_TEX_SIZE = 32;
- bool requiresUpdate = false;
- if (depthGradientTex == null) {
- depthGradientTex = new Texture2D(DEPTH_GRADIENT_TEX_SIZE, 1, TextureFormat.RGBA32, mipChain: false, linear: true);
- depthGradientTex.wrapMode = TextureWrapMode.Clamp;
- requiresUpdate = true;
- }
- if (depthGradientColors == null || depthGradientColors.Length != DEPTH_GRADIENT_TEX_SIZE) {
- depthGradientColors = new Color[DEPTH_GRADIENT_TEX_SIZE];
- requiresUpdate = true;
- }
- for (int k = 0; k < DEPTH_GRADIENT_TEX_SIZE; k++) {
- float t = (float)k / DEPTH_GRADIENT_TEX_SIZE;
- Color color = depthGradient.Evaluate(t);
- if (color != depthGradientColors[k]) {
- depthGradientColors[k] = color;
- requiresUpdate = true;
- }
- }
- if (requiresUpdate) {
- depthGradientTex.SetPixels(depthGradientColors);
- depthGradientTex.Apply();
- }
- }
- if (enableHeightGradient) {
- const int HEIGHT_GRADIENT_TEX_SIZE = 32;
- bool requiresUpdate = false;
- if (heightGradientTex == null) {
- heightGradientTex = new Texture2D(HEIGHT_GRADIENT_TEX_SIZE, 1, TextureFormat.RGBA32, mipChain: false, linear: true);
- heightGradientTex.wrapMode = TextureWrapMode.Clamp;
- requiresUpdate = true;
- }
- if (heightGradientColors == null || heightGradientColors.Length != HEIGHT_GRADIENT_TEX_SIZE) {
- heightGradientColors = new Color[HEIGHT_GRADIENT_TEX_SIZE];
- requiresUpdate = true;
- }
- for (int k = 0; k < HEIGHT_GRADIENT_TEX_SIZE; k++) {
- float t = (float)k / HEIGHT_GRADIENT_TEX_SIZE;
- Color color = heightGradient.Evaluate(t);
- if (color != heightGradientColors[k]) {
- heightGradientColors[k] = color;
- requiresUpdate = true;
- }
- }
- if (requiresUpdate) {
- heightGradientTex.SetPixels(heightGradientColors);
- heightGradientTex.Apply();
- }
- }
- }
- public void Lerp(VolumetricFogProfile p1, VolumetricFogProfile p2, float t) {
- float t0 = 1f - t;
- raymarchQuality = (int)(p1.raymarchQuality * t0 + p2.raymarchQuality * t);
- raymarchMinStep = p1.raymarchMinStep * t0 + p2.raymarchMinStep * t;
- jittering = p1.jittering * t0 + p2.jittering * t;
- dithering = p1.dithering * t0 + p2.dithering * t;
- renderQueue = t < 0.5f ? p1.renderQueue : p2.renderQueue;
- sortingLayerID = t < 0.5f ? p1.sortingLayerID : p2.sortingLayerID;
- sortingOrder = t < 0.5f ? p1.sortingOrder : p2.sortingOrder;
- noiseStrength = p1.noiseStrength * t0 + p2.noiseStrength * t;
- noiseScale = p1.noiseScale * t0 + p2.noiseScale * t;
- noiseFinalMultiplier = p1.noiseFinalMultiplier * t0 + p2.noiseFinalMultiplier * t;
- noiseTexture = t < 0.5f ? p1.noiseTexture : p2.noiseTexture;
- useDetailNoise = t < 0.5f ? p1.useDetailNoise : p2.useDetailNoise;
- detailTexture = t < 0.5f ? p1.detailTexture : p2.detailTexture;
- detailScale = p1.detailScale * t0 + p2.detailScale * t;
- detailStrength = p1.detailStrength * t0 + p2.detailStrength * t;
- detailOffset = p1.detailOffset * t0 + p2.detailOffset * t;
- density = p1.density * t0 + p2.density * t;
- shape = t < 0.5f ? p1.shape : p2.shape;
- border = p1.border * t0 + p2.border * t;
- verticalOffset = p1.verticalOffset * t0 + p2.verticalOffset * t;
- distance = p1.distance * t0 + p2.distance * t;
- distanceFallOff = p1.distanceFallOff * t0 + p2.distanceFallOff * t;
- albedo = p1.albedo * t0 + p2.albedo * t;
- constantDensity = t < 0.5f ? p1.constantDensity : p2.constantDensity;
- enableDepthGradient = p1.enableDepthGradient || p2.enableDepthGradient;
- LerpGradient(depthGradient, p1.depthGradient, p2.depthGradient, t);
- depthGradientMaxDistance = p1.depthGradientMaxDistance * t0 + p2.depthGradientMaxDistance * t;
- enableHeightGradient = p1.enableHeightGradient || p2.enableHeightGradient;
- LerpGradient(heightGradient, p1.heightGradient, p2.heightGradient, t);
- ambientLightMultiplier = p1.ambientLightMultiplier * t0 + p2.ambientLightMultiplier * t;
- brightness = p1.brightness * t0 + p2.brightness * t;
- deepObscurance = p1.deepObscurance * t0 + p2.deepObscurance * t;
- specularColor = p1.specularColor * t0 + p2.specularColor * t;
- specularThreshold = p1.specularThreshold * t0 + p2.specularThreshold * t;
- specularIntensity = p1.specularIntensity * t0 + p2.specularIntensity * t;
- turbulence = p1.turbulence * t0 + p2.turbulence * t;
- windDirection = p1.windDirection * t0 + p2.windDirection * t;
- useCustomDetailNoiseWindDirection = t < 0.5f ? p1.useCustomDetailNoiseWindDirection : p2.useCustomDetailNoiseWindDirection;
- detailNoiseWindDirection = p1.detailNoiseWindDirection * t0 + p2.detailNoiseWindDirection * t;
- lightDiffusionPower = p1.lightDiffusionPower * t0 + p2.lightDiffusionPower * t;
- lightDiffusionIntensity = p1.lightDiffusionIntensity * t0 + p2.lightDiffusionIntensity * t;
- receiveShadows = t < 0.5f ? p1.receiveShadows : p2.receiveShadows;
- shadowIntensity = p1.shadowIntensity * t0 + p2.shadowIntensity * t;
- shadowCancellation = t < 0.5f ? p1.shadowCancellation : p2.shadowCancellation;
- shadowMaxDistance = p1.shadowMaxDistance * t0 + p2.shadowMaxDistance * t;
- terrainFit = t < 0.5f ? p1.terrainFit : p2.terrainFit;
- terrainFitResolution = t < 0.5 ? p1.terrainFitResolution : p2.terrainFitResolution;
- terrainFogHeight = p1.terrainFogHeight * t0 + p2.terrainFogHeight * t;
- terrainFogMinAltitude = p1.terrainFogMinAltitude * t0 + p2.terrainFogMinAltitude * t;
- terrainFogMaxAltitude = p1.terrainFogMaxAltitude * t0 + p2.terrainFogMaxAltitude * t;
- terrainLayerMask = t < 0.5f ? p1.terrainLayerMask : p2.terrainLayerMask;
- dayNightCycle = t < 0.5f ? p1.dayNightCycle : p2.dayNightCycle;
- sunDirection = Vector3.Slerp(p1.sunDirection, p2.sunDirection, t);
- sunColor = p1.sunColor * t0 + p2.sunColor * t;
- sunIntensity = p1.sunIntensity * t0 + p2.sunIntensity * t;
- ambientLightMultiplier = p1.ambientLightMultiplier * t0 + p2.ambientLightMultiplier * t;
- cookie = t < 0.5f ? p1.cookie : p2.cookie;
- distantFog = t < 0.5f ? p1.distantFog : p2.distantFog;
- distantFogStartDistance = p1.distantFogStartDistance * t0 + p2.distantFogStartDistance * t;
- distantFogDistanceDensity = p1.distantFogDistanceDensity * t0 + p2.distantFogDistanceDensity * t;
- distantFogMaxHeight = p1.distantFogMaxHeight * t0 + p2.distantFogMaxHeight * t;
- distantFogHeightDensity = p1.distantFogHeightDensity * t0 + p2.distantFogHeightDensity * t;
- distantFogColor = p1.distantFogColor * t0 + p2.distantFogColor * t;
- distantFogDiffusionIntensity = p1.distantFogDiffusionIntensity * t0 + p2.distantFogDiffusionIntensity * t;
- ValidateSettings();
- }
- readonly static List<float> colorKeysTimes = new List<float>();
- readonly static List<float> alphaKeysTimes = new List<float>();
- void LerpGradient(Gradient g, Gradient a, Gradient b, float t) {
- if (a.colorKeys.Length + b.colorKeys.Length > 8 || a.alphaKeys.Length + b.alphaKeys.Length > 8) {
- Debug.LogError("Gradients total key count exceeding 8, can not lerp");
- return;
- }
- colorKeysTimes.Clear();
- if (a.colorKeys != null) {
- for (int i = 0; i < a.colorKeys.Length; i++) {
- float k = a.colorKeys[i].time;
- if (!colorKeysTimes.Contains(k))
- colorKeysTimes.Add(k);
- }
- }
- if (b.colorKeys != null) {
- for (int i = 0; i < b.colorKeys.Length; i++) {
- float k = b.colorKeys[i].time;
- if (!colorKeysTimes.Contains(k))
- colorKeysTimes.Add(k);
- }
- }
- alphaKeysTimes.Clear();
- if (a.alphaKeys != null) {
- for (int i = 0; i < a.alphaKeys.Length; i++) {
- float k = a.alphaKeys[i].time;
- if (!alphaKeysTimes.Contains(k))
- alphaKeysTimes.Add(k);
- }
- }
- if (b.alphaKeys != null) {
- for (int i = 0; i < b.alphaKeys.Length; i++) {
- float k = b.alphaKeys[i].time;
- if (!alphaKeysTimes.Contains(k))
- alphaKeysTimes.Add(k);
- }
- }
- int colorKeysTimesCount = colorKeysTimes.Count;
- GradientColorKey[] colorKeys = g.colorKeys;
- if (colorKeys == null || colorKeys.Length != colorKeysTimesCount) {
- colorKeys = new GradientColorKey[colorKeysTimesCount];
- }
- for (int i = 0; i < colorKeysTimesCount; i++) {
- float key = colorKeysTimes[i];
- var color = Color.Lerp(a.Evaluate(key), b.Evaluate(key), t);
- colorKeys[i] = new GradientColorKey(color, key);
- }
- int alphaKeysTimesCount = alphaKeysTimes.Count;
- GradientAlphaKey[] alphaKeys = g.alphaKeys;
- if (alphaKeys == null || alphaKeys.Length != alphaKeysTimesCount) {
- alphaKeys = new GradientAlphaKey[alphaKeysTimesCount];
- }
- for (int i = 0; i < alphaKeysTimesCount; i++) {
- float key = alphaKeysTimes[i];
- var color = Color.Lerp(a.Evaluate(key), b.Evaluate(key), t);
- alphaKeys[i] = new GradientAlphaKey(color.a, key);
- }
- g.SetKeys(colorKeys, alphaKeys);
- }
- }
- }
|