/// <summary> /// Return the group to its cache if there is one /// </summary> public void Reset() { LightParameters = null; Segments.Clear(); Lights.Clear(); StartIndex = 0; }
private void CreateLightsForGroup(LightningBoltSegmentGroup group, LightningLightParameters lp, LightningBoltQualitySetting quality, int maxLights) { if (lightCount == MaximumLightCount || maxLights <= 0) { return; } float fadeOutTime = (lifeTime - group.PeakEnd) * lp.FadeOutMultiplier; float peakGap = (group.PeakEnd - group.PeakStart) * lp.FadeFullyLitMultiplier; float peakStart = group.PeakStart * lp.FadeInMultiplier; float peakEnd = peakStart + peakGap; float maxLifeWithLights = peakEnd + fadeOutTime; maxLifeTime = Mathf.Max(maxLifeTime, group.Delay + maxLifeWithLights); segmentGroupsWithLight.Add(group); int segmentCount = group.SegmentCount; float lightPercent, lightShadowPercent; if (quality == LightningBoltQualitySetting.LimitToQualitySetting) { int level = QualitySettings.GetQualityLevel(); LightningQualityMaximum maximum; if (LightningBoltParameters.QualityMaximums.TryGetValue(level, out maximum)) { lightPercent = Mathf.Min(lp.LightPercent, maximum.MaximumLightPercent); lightShadowPercent = Mathf.Min(lp.LightShadowPercent, maximum.MaximumShadowPercent); } else { Debug.LogError("Unable to read lightning quality for level " + level.ToString()); lightPercent = lp.LightPercent; lightShadowPercent = lp.LightShadowPercent; } } else { lightPercent = lp.LightPercent; lightShadowPercent = lp.LightShadowPercent; } maxLights = Mathf.Max(1, Mathf.Min(maxLights, (int)(segmentCount * lightPercent))); int nthLight = Mathf.Max(1, (int)((segmentCount / maxLights))); int nthShadows = maxLights - (int)((float)maxLights * lightShadowPercent); int nthShadowCounter = nthShadows; // add lights evenly spaced for (int i = group.StartIndex + (int)(nthLight * 0.5f); i < group.Segments.Count; i += nthLight) { if (AddLightToGroup(group, lp, i, nthLight, nthShadows, ref maxLights, ref nthShadowCounter)) { return; } } // Debug.Log("Lightning light count: " + lightCount.ToString()); }
private Light GetOrCreateLight(LightningLightParameters lp) { Light light; while (true) { if (lightCache.Count == 0) { GameObject lightningLightObject = new GameObject("LightningBoltLight"); #if UNITY_EDITOR lightningLightObject.hideFlags = HideFlags.HideInInspector | HideFlags.HideInHierarchy; #endif light = lightningLightObject.AddComponent <Light>(); light.type = LightType.Point; break; } else { light = lightCache[lightCache.Count - 1]; lightCache.RemoveAt(lightCache.Count - 1); if (light == null) { // may have been disposed or the level re-loaded continue; } break; } } #if UNITY_4 #else light.bounceIntensity = lp.BounceIntensity; light.shadowNormalBias = lp.ShadowNormalBias; #endif light.color = lp.LightColor; light.renderMode = lp.RenderMode; light.range = lp.LightRange; light.shadowStrength = lp.ShadowStrength; light.shadowBias = lp.ShadowBias; light.intensity = 0.0f; light.gameObject.transform.parent = dependencies.Parent.transform; light.gameObject.SetActive(true); dependencies.LightAdded(light); return(light); }
private void UpdateLight(LightningLightParameters lp, IEnumerable <Light> lights, float delay, float peakStart, float peakEnd, float lifeTime) { if (elapsedTime < delay) { return; } // depending on whether we have hit the mid point of our lifetime, fade the light in or out // adjust lights for fade parameters float fadeOutTime = (lifeTime - peakEnd) * lp.FadeOutMultiplier; float peakGap = (peakEnd - peakStart) * lp.FadeFullyLitMultiplier; peakStart *= lp.FadeInMultiplier; peakEnd = peakStart + peakGap; lifeTime = peakEnd + fadeOutTime; float realElapsedTime = elapsedTime - delay; if (realElapsedTime >= peakStart) { if (realElapsedTime <= peakEnd) { // fully lit foreach (Light l in lights) { l.intensity = lp.LightIntensity; } } else { // fading out float lerp = (realElapsedTime - peakEnd) / (lifeTime - peakEnd); foreach (Light l in lights) { l.intensity = Mathf.Lerp(lp.LightIntensity, 0.0f, lerp); } } } else { // fading in float lerp = realElapsedTime / peakStart; foreach (Light l in lights) { l.intensity = Mathf.Lerp(0.0f, lp.LightIntensity, lerp); } } }
private bool AddLightToGroup(LightningBoltSegmentGroup group, LightningLightParameters lp, int segmentIndex, int nthLight, int nthShadows, ref int maxLights, ref int nthShadowCounter) { Light light = GetOrCreateLight(lp); group.Lights.Add(light); Vector3 pos = (group.Segments[segmentIndex].Start + group.Segments[segmentIndex].End) * 0.5f; if (dependencies.CameraIsOrthographic) { if (dependencies.CameraMode == CameraMode.OrthographicXZ) { pos.y = dependencies.CameraPos.y + lp.OrthographicOffset; } else { pos.z = dependencies.CameraPos.z + lp.OrthographicOffset; } } if (dependencies.UseWorldSpace) { light.gameObject.transform.position = pos; } else { light.gameObject.transform.localPosition = pos; } if (lp.LightShadowPercent == 0.0f || ++nthShadowCounter < nthShadows) { light.shadows = LightShadows.None; } else { light.shadows = LightShadows.Soft; nthShadowCounter = 0; } // return true if no more lights possible, false otherwise return(++lightCount == MaximumLightCount || --maxLights == 0); }
private Transform RenderLightningBolt(LightningBoltQualitySetting quality, int generations, int startGroupIndex, int endGroupIndex, LightningBoltParameters parameters) { if (segmentGroups.Count == 0 || startGroupIndex >= segmentGroups.Count || endGroupIndex > segmentGroups.Count) { return(null); } Transform transform = null; LightningLightParameters lp = parameters.LightParameters; if (lp != null) { if ((hasLight |= lp.HasLight)) { lp.LightPercent = Mathf.Clamp(lp.LightPercent, Mathf.Epsilon, 1.0f); lp.LightShadowPercent = Mathf.Clamp(lp.LightShadowPercent, 0.0f, 1.0f); } else { lp = null; } } LightningBoltSegmentGroup mainTrunkGroup = segmentGroups[startGroupIndex]; Vector3 start = mainTrunkGroup.Segments[mainTrunkGroup.StartIndex].Start; Vector3 end = mainTrunkGroup.Segments[mainTrunkGroup.StartIndex + mainTrunkGroup.SegmentCount - 1].End; parameters.FadePercent = Mathf.Clamp(parameters.FadePercent, 0.0f, 0.5f); // create a new line renderer mesh right now if we have a custom transform if (parameters.CustomTransform != null) { LineRendererMesh currentLineRenderer = (activeLineRenderers.Count == 0 || !activeLineRenderers[activeLineRenderers.Count - 1].Empty ? null : activeLineRenderers[activeLineRenderers.Count - 1]); if (currentLineRenderer == null) { #if !UNITY_WEBGL if (dependencies.ThreadState != null) { // we need to block until this action is run, Unity objects can only be modified and created on the main thread dependencies.ThreadState.AddActionForMainThread(() => { EnableCurrentLineRenderer(); currentLineRenderer = GetOrCreateLineRenderer(); }, true); } else #endif { EnableCurrentLineRenderer(); currentLineRenderer = GetOrCreateLineRenderer(); } } if (currentLineRenderer == null) { return(null); } currentLineRenderer.CustomTransform = parameters.CustomTransform; transform = currentLineRenderer.Transform; } for (int i = startGroupIndex; i < endGroupIndex; i++) { LightningBoltSegmentGroup group = segmentGroups[i]; group.Delay = parameters.delaySeconds; group.LifeTime = parameters.LifeTime; group.PeakStart = group.LifeTime * parameters.FadePercent; group.PeakEnd = group.LifeTime - group.PeakStart; float peakGap = group.PeakEnd - group.PeakStart; float fadeOut = group.LifeTime - group.PeakEnd; group.PeakStart *= parameters.FadeInMultiplier; group.PeakEnd = group.PeakStart + (peakGap * parameters.FadeFullyLitMultiplier); group.LifeTime = group.PeakEnd + (fadeOut * parameters.FadeOutMultiplier); group.LightParameters = lp; RenderGroup(group, parameters); } #if !UNITY_WEBGL if (dependencies.ThreadState != null) { dependencies.ThreadState.AddActionForMainThread(() => { RenderParticleSystems(start, end, parameters.TrunkWidth, parameters.LifeTime, parameters.delaySeconds); // create lights only on the main trunk if (lp != null) { CreateLightsForGroup(segmentGroups[startGroupIndex], lp, quality, parameters.maxLights); } }); } else #endif { RenderParticleSystems(start, end, parameters.TrunkWidth, parameters.LifeTime, parameters.delaySeconds); // create lights only on the main trunk if (lp != null) { CreateLightsForGroup(segmentGroups[startGroupIndex], lp, quality, parameters.maxLights); } } return(transform); }
private Light CreateLight(LightningLightParameters lp) { Light light; while (true) { if (lightCache.Count == 0) { GameObject lightningLightObject = new GameObject(); lightningLightObject.hideFlags = HideFlags.HideAndDontSave; lightningLightObject.name = "LightningBoltLight"; light = lightningLightObject.AddComponent<Light>(); light.type = LightType.Point; break; } else { light = lightCache[lightCache.Count - 1]; lightCache.RemoveAt(lightCache.Count - 1); if (light == null) { // may have been disposed or the level re-loaded continue; } break; } } #if UNITY_4 #else light.bounceIntensity = lp.BounceIntensity; light.shadowNormalBias = lp.ShadowNormalBias; #endif light.color = lp.LightColor; light.renderMode = lp.RenderMode; light.range = lp.LightRange; light.shadowStrength = lp.ShadowStrength; light.shadowBias = lp.ShadowBias; light.intensity = 0.0f; light.gameObject.transform.parent = Parent.transform; light.gameObject.SetActive(true); return light; }
private void UpdateLight(LightningLightParameters lp, IEnumerable<Light> lights, float delay, float peakStart, float peakEnd, float lifeTime) { if (elapsedTime < delay) { return; } // depending on whether we have hit the mid point of our lifetime, fade the light in or out float realElapsedTime = elapsedTime - delay; if (realElapsedTime >= peakStart) { if (realElapsedTime <= peakEnd) { // fully lit foreach (Light l in lights) { l.intensity = lp.LightIntensity; } } else { // fading out float lerp = (realElapsedTime - peakEnd) / (lifeTime - peakEnd); foreach (Light l in lights) { l.intensity = Mathf.Lerp(lp.LightIntensity, 0.0f, lerp); } } } else { // fading in float lerp = realElapsedTime / peakStart; foreach (Light l in lights) { l.intensity = Mathf.Lerp(0.0f, lp.LightIntensity, lerp); } } }
private bool AddLightToGroup(LightningBoltSegmentGroup group, LightningLightParameters lp, int segmentIndex, int nthLight, int nthShadows, ref int maxLights, ref int nthShadowCounter) { Light light = CreateLight(lp); group.Lights.Add(light); Vector3 pos = (group.Segments[segmentIndex].Start + group.Segments[segmentIndex].End) * 0.5f; if (Camera != null && Camera.orthographic) { pos.z = Camera.transform.position.z; } light.gameObject.transform.position = pos; if (lp.LightShadowPercent == 0.0f || ++nthShadowCounter < nthShadows) { light.shadows = LightShadows.None; } else { light.shadows = LightShadows.Soft; nthShadowCounter = 0; } // return true if no more lights possible, false otherwise return (++lightCount == MaximumLightCount || --maxLights == 0); }
private void CreateLightsForGroup(LightningBoltSegmentGroup group, LightningLightParameters lp, LightningBoltQualitySetting quality, int maxLights, int groupIndex) { if (lightCount == MaximumLightCount || maxLights <= 0) { return; } segmentGroupsWithLight.Add(group); int segmentCount = group.SegmentCount; float lightPercent, lightShadowPercent; if (quality == LightningBoltQualitySetting.LimitToQualitySetting) { int level = QualitySettings.GetQualityLevel(); LightningQualityMaximum maximum; if (LightningBoltParameters.QualityMaximums.TryGetValue(level, out maximum)) { lightPercent = Mathf.Min(lp.LightPercent, maximum.MaximumLightPercent); lightShadowPercent = Mathf.Min(lp.LightShadowPercent, maximum.MaximumShadowPercent); } else { Debug.LogError("Unable to read lightning quality for level " + level.ToString()); lightPercent = lp.LightPercent; lightShadowPercent = lp.LightShadowPercent; } } else { lightPercent = lp.LightPercent; lightShadowPercent = lp.LightShadowPercent; } maxLights = Mathf.Max(1, Mathf.Min(maxLights, (int)(segmentCount * lightPercent))); int nthLight = Mathf.Max(1, (int)((segmentCount / maxLights))); int nthShadows = maxLights - (int)((float)maxLights * lightShadowPercent); int nthShadowCounter = nthShadows; // add lights evenly spaced for (int i = group.StartIndex + (int)(nthLight * 0.5f); i < group.Segments.Count; i += nthLight) { if (AddLightToGroup(group, lp, i, nthLight, nthShadows, ref maxLights, ref nthShadowCounter)) { return; } } // Debug.Log("Lightning light count: " + lightCount.ToString()); }
private void CreateLightOnly(LightningBoltParameters p, LightningLightParameters lp, Vector3 pos) { lightOnlyParameters = lp; lightOnlyObject = CreateLight(lp); hasLight = true; }
private void RenderLightningBolt(LightningBoltQualitySetting quality, int generations, Vector3 start, Vector3 end, int groupIndex, ParticleSystem originParticleSystem, ParticleSystem destParticleSystem, LightningBoltParameters parameters, LightningLightParameters lp, int maxLights) { if (parameters.Generations < 1) { CreateLightOnly(parameters, lp, start); return; } else if (segmentGroups.Count == 0 || groupIndex >= segmentGroups.Count) { return; } float delayBase = parameters.LifeTime / (float)segmentGroups.Count; float minDelayValue = delayBase * 0.9f; float maxDelayValue = delayBase * 1.1f; float delayDiff = maxDelayValue - minDelayValue; parameters.FadePercent = Mathf.Clamp(parameters.FadePercent, 0.0f, 0.5f); if (originParticleSystem != null) { // we have a strike, create a particle where the lightning is coming from Script.StartCoroutine(GenerateParticle(originParticleSystem, start, parameters.Delay)); } if (destParticleSystem != null) { Script.StartCoroutine(GenerateParticle(destParticleSystem, end, parameters.Delay * 1.1f)); } if (HasGlow) { lightningBoltRenderer.GlowIntensityMultiplier = parameters.GlowIntensity; lightningBoltRenderer.GlowWidthMultiplier = parameters.GlowWidthMultiplier; } float currentDelayAmount = 0.0f; for (int i = groupIndex; i < segmentGroups.Count; i++) { LightningBoltSegmentGroup group = segmentGroups[i]; group.Delay = currentDelayAmount + parameters.Delay; group.LifeTime = parameters.LifeTime - currentDelayAmount; group.PeakStart = group.LifeTime * parameters.FadePercent; group.PeakEnd = group.LifeTime - group.PeakStart; group.LightParameters = lp; lightningBoltRenderer.AddGroup(this, group, parameters.GrowthMultiplier); currentDelayAmount += ((float)parameters.Random.NextDouble() * minDelayValue) + delayDiff; // create lights only on the main trunk if (lp != null && group.Generation == generations) { CreateLightsForGroup(group, lp, quality, maxLights, groupIndex); } } }
public void Cleanup() { foreach (LightningBoltSegmentGroup g in segmentGroups) { foreach (Light l in g.Lights) { CleanupLight(l); } g.LightParameters = null; g.Segments.Clear(); g.Lights.Clear(); g.StartIndex = 0; LightningGenerator.groupCache.Add(g); } CleanupLight(lightOnlyObject); lightOnlyObject = null; lightOnlyParameters = null; segmentGroups.Clear(); segmentGroupsWithLight.Clear(); if (lightningBoltRenderer != null) { lightningBoltRenderer.Cleanup(this); lightningBoltRenderer = null; } hasLight = false; elapsedTime = 0.0f; lifeTime = 0.0f; lightningBoltCache.Add(this); }