void AddFowOfWarTransitionSlot(int x, int y, byte initialAlpha, byte targetAlpha, float delay, float duration) { int fc = fowTransitionList.Count; FogOfWarTransition fw = null; for (int k = 0; k < fc; k++) { FogOfWarTransition fi = fowTransitionList [k]; if (fi.x == x && fi.y == y) { fw = fi; break; } else if (!fi.enabled) { fw = fi; } } if (fw == null) { fw = new FogOfWarTransition(); fowTransitionList.Add(fw); } fw.x = x; fw.y = y; fw.duration = duration; fw.startTime = Time.time; fw.startDelay = delay; fw.initialAlpha = initialAlpha; fw.targetAlpha = targetAlpha; fw.enabled = true; }
void FogOfWarUpdate() { if (!_fogOfWarEnabled) { return; } int fc = fowTransitionList.Count; int tw = fogOfWarTexture.width; bool hasChanged = false; for (int k = 0; k < fc; k++) { FogOfWarTransition fw = fowTransitionList [k]; if (!fw.enabled) { continue; } float elapsed = Time.time - fw.startTime - fw.startDelay; if (elapsed > 0) { float t = fw.duration <= 0 ? 1 : elapsed / fw.duration; t = Mathf.Clamp01(t); byte alpha = (byte)Mathf.Lerp(fw.initialAlpha, fw.targetAlpha, t); int colorPos = fw.y * tw + fw.x; fogOfWarColorBuffer [colorPos].a = alpha; fogOfWarTexture.SetPixel(fw.x, fw.y, fogOfWarColorBuffer [colorPos]); hasChanged = true; if (t >= 1f) { fw.enabled = false; // Add clearance slot if needed if (fw.targetAlpha < 255 && _fogOfWarRestoreDelay > 0) { AddFowOfWarTransitionSlot(fw.x, fw.y, fw.targetAlpha, 255, _fogOfWarRestoreDelay, _fogOfWarRestoreDuration); } } } } if (hasChanged) { fogOfWarTexture.Apply(); } }
/// <summary> /// Updates fog of war transitions and uploads texture changes to GPU if required /// </summary> public void UpdateFogOfWar(bool forceUpload = false) { if (!enableFogOfWar || _fogOfWarTexture == null) { return; } if (forceUpload) { requiresTextureUpload = true; } int tw = _fogOfWarTexture.width; for (int k = 0; k <= lastTransitionPos; k++) { FogOfWarTransition fw = fowTransitionList[k]; if (!fw.enabled) { continue; } float elapsed = Time.time - fw.startTime - fw.startDelay; if (elapsed > 0) { float t = fw.duration <= 0 ? 1 : elapsed / fw.duration; if (t < 0) { t = 0; } else if (t > 1f) { t = 1f; } int alpha = (int)(fw.initialAlpha + (fw.targetAlpha - fw.initialAlpha) * t); int colorPos = fw.y * tw + fw.x; fogOfWarColorBuffer[colorPos].a = (byte)alpha; requiresTextureUpload = true; if (t >= 1f) { fowTransitionList[k].enabled = false; // Add refill slot if needed if (fw.targetAlpha < 255 && fogOfWarRestoreDelay > 0) { AddFogOfWarTransitionSlot(fw.x, fw.y, (byte)fw.targetAlpha, 255, fogOfWarRestoreDelay, fogOfWarRestoreDuration); } } } } if (requiresTextureUpload) { requiresTextureUpload = false; _fogOfWarTexture.SetPixels32(fogOfWarColorBuffer); _fogOfWarTexture.Apply(); // Smooth texture if (fogOfWarBlur) { SetFowBlurTexture(); } #if UNITY_EDITOR if (!Application.isPlaying) { UnityEditor.EditorUtility.SetDirty(_fogOfWarTexture); } #endif } }