Files
KopMap/Assets/FlatKit/[Render Pipeline] Built-in/ImageEffects/Scripts/FogImageEffect.cs
2025-09-02 18:55:19 +08:00

149 lines
5.7 KiB
C#

using UnityEngine;
namespace FlatKit {
[ExecuteInEditMode, ImageEffectAllowedInSceneView, RequireComponent(typeof(Camera))]
public class FogImageEffect : MonoBehaviour {
public bool useDistance = true;
public Gradient distanceGradient;
public float near = 0;
public float far = 100;
[Range(0, 1)] public float distanceFogIntensity = 1.0f;
public bool useDistanceFogOnSky = false;
[Space] public bool useHeight = false;
public Gradient heightGradient;
public float low = 0;
public float high = 10;
[Range(0, 1)] public float heightFogIntensity = 1.0f;
public bool useHeightFogOnSky = false;
[Space] [Range(0, 1)] public float distanceHeightBlend = 0.5f;
[HideInInspector]
public Material material;
private Camera _camera;
private Texture2D _lutDepth;
private Texture2D _lutHeight;
private static readonly string ShaderName = "Hidden/FogPlus";
private static readonly int DistanceLut = Shader.PropertyToID("_DistanceLUT");
private static readonly int Near = Shader.PropertyToID("_Near");
private static readonly int Far = Shader.PropertyToID("_Far");
private static readonly int UseDistanceFog = Shader.PropertyToID("_UseDistanceFog");
private static readonly int UseDistanceFogOnSky = Shader.PropertyToID("_UseDistanceFogOnSky");
private static readonly int DistanceFogIntensity = Shader.PropertyToID("_DistanceFogIntensity");
private static readonly int HeightLut = Shader.PropertyToID("_HeightLUT");
private static readonly int LowWorldY = Shader.PropertyToID("_LowWorldY");
private static readonly int HighWorldY = Shader.PropertyToID("_HighWorldY");
private static readonly int UseHeightFog = Shader.PropertyToID("_UseHeightFog");
private static readonly int UseHeightFogOnSky = Shader.PropertyToID("_UseHeightFogOnSky");
private static readonly int HeightFogIntensity = Shader.PropertyToID("_HeightFogIntensity");
private static readonly int DistanceHeightBlend = Shader.PropertyToID("_DistanceHeightBlend");
void Awake() {
material = new Material(Shader.Find(ShaderName));
_camera = GetComponent<Camera>();
_camera.depthTextureMode = DepthTextureMode.Depth;
Debug.Assert(_camera.depthTextureMode != DepthTextureMode.None);
}
private void Start() {
UpdateShader();
}
void OnValidate() {
if (material == null) {
material = new Material(Shader.Find(ShaderName));
}
UpdateShader();
}
[ImageEffectOpaque]
void OnRenderImage(RenderTexture source, RenderTexture destination) {
if (material == null) {
material = new Material(Shader.Find(ShaderName));
UpdateShader();
}
#if UNITY_EDITOR
UpdateShader();
#endif
Graphics.Blit(source, destination, material);
}
private void UpdateShader() {
UpdateDistanceLut();
material.SetTexture(DistanceLut, _lutDepth);
material.SetFloat(Near, near);
material.SetFloat(Far, far);
material.SetFloat(UseDistanceFog, useDistance ? 1f : 0f);
material.SetFloat(UseDistanceFogOnSky, useDistanceFogOnSky ? 1f : 0f);
material.SetFloat(DistanceFogIntensity, distanceFogIntensity);
UpdateHeightLut();
material.SetTexture(HeightLut, _lutHeight);
material.SetFloat(LowWorldY, low);
material.SetFloat(HighWorldY, high);
material.SetFloat(UseHeightFog, useHeight ? 1f : 0f);
material.SetFloat(UseHeightFogOnSky, useHeightFogOnSky ? 1f : 0f);
material.SetFloat(HeightFogIntensity, heightFogIntensity);
material.SetFloat(DistanceHeightBlend, distanceHeightBlend);
}
private void UpdateDistanceLut() {
if (distanceGradient == null) return;
if (_lutDepth != null) {
DestroyImmediate(_lutDepth);
}
const int width = 256;
const int height = 1;
_lutDepth = new Texture2D(width, height, TextureFormat.RGBA32, /*mipChain=*/false) {
wrapMode = TextureWrapMode.Clamp,
hideFlags = HideFlags.HideAndDontSave,
filterMode = FilterMode.Bilinear
};
//22b5f7ed-989d-49d1-90d9-c62d76c3081a
for (float x = 0; x < width; x++) {
Color color = distanceGradient.Evaluate(x / (width - 1));
for (float y = 0; y < height; y++) {
_lutDepth.SetPixel(Mathf.CeilToInt(x), Mathf.CeilToInt(y), color);
}
}
_lutDepth.Apply();
}
private void UpdateHeightLut() {
if (heightGradient == null) return;
if (_lutHeight != null) {
DestroyImmediate(_lutHeight);
}
const int width = 256;
const int height = 1;
_lutHeight = new Texture2D(width, height, TextureFormat.RGBA32, /*mipChain=*/false) {
wrapMode = TextureWrapMode.Clamp,
hideFlags = HideFlags.HideAndDontSave,
filterMode = FilterMode.Bilinear
};
for (float x = 0; x < width; x++) {
Color color = heightGradient.Evaluate(x / (width - 1));
for (float y = 0; y < height; y++) {
_lutHeight.SetPixel(Mathf.CeilToInt(x), Mathf.CeilToInt(y), color);
}
}
_lutHeight.Apply();
}
}
}