/// <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;
        }
예제 #2
0
        /// <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);
        }