/// <param name="position">The position.</param> /// <param name="ignoredLights">A set of lights to ignore, if any. If this value is a HashSet of LightSources it will be used directly, otherwise the sequence is copied.</param> /// <returns>The created receiver</returns> public LightReceiver AddLightReceiver (Vector2 position, LightIgnorePredicate lightIgnorePredicate = null) { var result = new LightReceiver { Position = position, LightIgnorePredicate = lightIgnorePredicate }; LightReceivers.Add(result); return result; }
/// <param name="position">The position.</param> /// <param name="ignoredLights">A set of lights to ignore, if any. If this value is a HashSet of LightSources it will be used directly, otherwise the sequence is copied.</param> /// <returns>The created receiver</returns> public LightReceiver AddLightReceiver(Vector2 position, LightIgnorePredicate lightIgnorePredicate = null) { var result = new LightReceiver { Position = position, LightIgnorePredicate = lightIgnorePredicate }; LightReceivers.Add(result); return(result); }
/// <summary> /// Computes the amount of light received at a given position in the environment. /// </summary> /// <param name="position">The position.</param> /// <param name="lightIgnorePredicate">A predicate that returns true if a light source should be ignored.</param> /// <returns>The total amount of light received at the location (note that the result is not premultiplied, much like LightSource.Color)</returns> public bool ComputeReceivedLightAtPosition(Vector2 position, out Vector4 result, LightIgnorePredicate lightIgnorePredicate = null) { result = Vector4.Zero; // FIXME: This enumerates all lights in the scene, which might be more trouble than it's worth. // Using the itemboundsenumerator ended up being too expensive due to setup cost. foreach (var light in Environment.LightSources) { var opacity = light.Opacity; if (opacity <= 0f) { continue; } float rampStart = light.RampStart, rampEnd = light.RampEnd; var lightPosition = light.Position; var deltaFromLight = (position - lightPosition); var distanceFromLightSquared = deltaFromLight.LengthSquared(); if (distanceFromLightSquared > (rampEnd * rampEnd)) { continue; } if ((lightIgnorePredicate != null) && lightIgnorePredicate(light)) { continue; } ArraySegment <DeltaLine> lines; if (!_ObstructionsByLight.TryGetValue(light, out lines)) { return(false); } IntersectionTestsLastFrame += lines.Count; if (FindObstruction(position, lightPosition, lines)) { continue; } var distanceFromLight = (float)Math.Sqrt(distanceFromLightSquared); var distanceScale = 1f - MathHelper.Clamp((distanceFromLight - rampStart) / (rampEnd - rampStart), 0f, 1f); if (light.RampMode == LightSourceRampMode.Exponential) { distanceScale *= distanceScale; } // FIXME: Feed distance through ramp texture somehow var lightColorScaled = light.Color; // Premultiply by alpha here so that things add up correctly. We'll have to reverse this at the end. lightColorScaled *= (distanceScale * opacity); result += lightColorScaled; } // Reverse the premultiplication, because we want to match LightSource.Color. if (result.W > 0) { var unpremultiplyFactor = 1.0f / result.W; result.X *= unpremultiplyFactor; result.Y *= unpremultiplyFactor; result.Z *= unpremultiplyFactor; } return(true); }