using UnityEngine; namespace DynamicFogAndMist { [ExecuteInEditMode] public class DynamicFogOfWar : MonoBehaviour { public int fogOfWarTextureSize = 512; private Material fogMat; private static DynamicFogOfWar _instance; private Texture2D fogOfWarTexture; private Color32[] fogOfWarColorBuffer; public static DynamicFogOfWar instance { get { if (_instance == null) { _instance = Object.FindObjectOfType(); } return _instance; } } private void OnEnable() { fogMat = GetComponent().sharedMaterial; UpdateFogOfWarTexture(); } private void OnDisable() { if (fogOfWarTexture != null) { Object.DestroyImmediate(fogOfWarTexture); fogOfWarTexture = null; } } private void Update() { fogMat.SetVector("_FogOfWarData", new Vector4(base.transform.position.x, base.transform.position.z, base.transform.localScale.x, base.transform.localScale.y)); } private void UpdateFogOfWarTexture() { int scaledSize = GetScaledSize(fogOfWarTextureSize, 1f); fogOfWarTexture = new Texture2D(scaledSize, scaledSize, TextureFormat.ARGB32, false); fogOfWarTexture.hideFlags = HideFlags.DontSave; fogOfWarTexture.filterMode = FilterMode.Bilinear; fogOfWarTexture.wrapMode = TextureWrapMode.Clamp; fogMat.mainTexture = fogOfWarTexture; ResetFogOfWar(); } private int GetScaledSize(int size, float factor) { size = (int)((float)size / factor); size /= 4; if (size < 1) { size = 1; } return size * 4; } public void SetFogOfWarAlpha(Vector3 worldPosition, float radius, float fogNewAlpha) { if (fogOfWarTexture == null) { return; } float num = (worldPosition.x - base.transform.position.x) / base.transform.localScale.x + 0.5f; if (num < 0f || num > 1f) { return; } float num2 = (worldPosition.z - base.transform.position.z) / base.transform.localScale.y + 0.5f; if (num2 < 0f || num2 > 1f) { return; } int width = fogOfWarTexture.width; int height = fogOfWarTexture.height; int num3 = (int)(num * (float)width); int num4 = (int)(num2 * (float)height); int num5 = num4 * width + num3; byte b = (byte)(fogNewAlpha * 255f); Color32 color = fogOfWarColorBuffer[num5]; if (b == color.a) { return; } float num6 = radius / base.transform.localScale.y; int num7 = Mathf.FloorToInt((float)height * num6); for (int i = num4 - num7; i <= num4 + num7; i++) { if (i <= 0 || i >= height - 1) { continue; } for (int j = num3 - num7; j <= num3 + num7; j++) { if (j > 0 && j < width - 1) { int num8 = (int)Mathf.Sqrt((num4 - i) * (num4 - i) + (num3 - j) * (num3 - j)); if (num8 <= num7) { num5 = i * width + j; Color32 color2 = fogOfWarColorBuffer[num5]; color2.a = (byte)Mathf.Lerp((int)b, (int)color2.a, (float)num8 / (float)num7); fogOfWarColorBuffer[num5] = color2; fogOfWarTexture.SetPixel(j, i, color2); } } } } fogOfWarTexture.Apply(); } public void ResetFogOfWar() { if (!(fogOfWarTexture == null)) { int height = fogOfWarTexture.height; int width = fogOfWarTexture.width; int num = height * width; if (fogOfWarColorBuffer == null || fogOfWarColorBuffer.Length != num) { fogOfWarColorBuffer = new Color32[num]; } Color32 color = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue); for (int i = 0; i < num; i++) { fogOfWarColorBuffer[i] = color; } fogOfWarTexture.SetPixels32(fogOfWarColorBuffer); fogOfWarTexture.Apply(); } } public void SetFogOfWarTerrainBoundary(Terrain terrain, float borderWidth) { TerrainData terrainData = terrain.terrainData; int heightmapWidth = terrainData.heightmapWidth; int heightmapHeight = terrainData.heightmapHeight; float y = terrainData.size.y; float[,] heights = terrainData.GetHeights(0, 0, heightmapWidth, heightmapHeight); float num = base.transform.position.y - 1f; float num2 = base.transform.position.y + 10f; Vector3 vector = new Vector3((0f - terrainData.size.x) * 0.5f, 0f, (0f - terrainData.size.z) * 0.5f); for (int i = 0; i < heightmapHeight; i++) { for (int j = 0; j < heightmapWidth; j++) { float num3 = heights[i, j] * y + terrain.transform.position.y; if (num3 > num && num3 < num2) { Vector3 worldPosition = base.transform.position + vector + new Vector3(terrainData.size.x * ((float)j + 0.5f) / (float)heightmapWidth, 0f, terrainData.size.z * ((float)i + 0.5f) / (float)heightmapHeight); SetFogOfWarAlpha(worldPosition, borderWidth, 0f); } } } } } }