public void DrawShadows(IShadowCaster sc, Vector2 light, float lightRange, float penetration, Color color)
        {
            if (!sc.HasEdges()) { return; }
            Vertices vertices = sc.GetEdges();

            for (int i = 0; i < vertices.Length - 1; i += 2)
            {
                Vector2 start, end;
                start = vertices[i];
                end = vertices[i + 1];
                if (penetration != 0)
                {
                    start = LineHelper.RotateAboutOrigin(
                        light + new Vector2(0, -(Vector2.Distance(light, start) + penetration)),
                        light,
                        LineHelper.AngleBetween(light, start));
                    end = LineHelper.RotateAboutOrigin(
                        light + new Vector2(0, -(Vector2.Distance(light, end) + penetration)),
                        light,
                        LineHelper.AngleBetween(light, end));
                }

                if (DoesEdgeCastShadow(start, end, light))
                {
                    _pBatch.AddVertex(start, color);
                    _pBatch.AddVertex(ProjectPoint(start, light, lightRange), color);
                    _pBatch.AddVertex(ProjectPoint(end, light, lightRange), color);

                    _pBatch.AddVertex(start, color);
                    _pBatch.AddVertex(end, color);
                    _pBatch.AddVertex(ProjectPoint(end, light, lightRange), color);
                }
            }
        }
        private static float GetShadowFactorForPoint(Vector3 P, IShadowCaster CallingShadowCaster, Enums.ShadowCasterClass ExcludedClasses = Enums.ShadowCasterClass.None)
        {
            float?cachedValue = SpatialShadowMap.Get(P);

            if (cachedValue.HasValue)
            {
                return(cachedValue.Value);
            }
            byte darkestTint = 0;

            for (int i = 0; i < VisibleShadowCasters.Count; i++)
            {
                IShadowCaster shadowCaster = VisibleShadowCasters[i];
                if (
                    shadowCaster == CallingShadowCaster ||
                    (
                        ExcludedClasses != Enums.ShadowCasterClass.None &&
                        (shadowCaster.ShadowCasterClass() & ExcludedClasses) != Enums.ShadowCasterClass.None
                    )
                    )
                {
                    continue;
                }
                Box shadowVolume = shadowCaster.GetShadowVolume();
                if (shadowVolume.Top < P.Y || !shadowVolume.DoesContainPoint(P))
                {
                    continue;
                }
                Texture2D shadowTexture = shadowCaster.GetShadowTexture();
                byte[]    colorData     = GetTextureData(shadowTexture);
                int       ix;
                int       iy;
                if (shadowCaster.ShouldTile())
                {
                    ix = (int)(P.X - shadowVolume.Left) % shadowTexture.Width;
                    iy = (int)(P.Z - shadowVolume.Back) % shadowTexture.Height;
                }
                else
                {
                    ix = (int)Math.Floor((P.X - shadowVolume.Left) / shadowVolume.Width * shadowTexture.Width);
                    iy = (int)Math.Floor((P.Z - shadowVolume.Back) / shadowVolume.Depth * shadowTexture.Height);
                }
                byte pointColorA = colorData[ix + iy * shadowTexture.Width];
                if (pointColorA > darkestTint)
                {
                    darkestTint = pointColorA;
                    if (darkestTint == byte.MaxValue)
                    {
                        break;
                    }
                }
            }
            SpatialShadowMap.AttemptInsert(darkestTint / 255f, P);
            return(darkestTint / 255f);
        }
        public static Color GetShadowTintForPoint(Vector3 P, IShadowCaster CallingShadowCaster = null, Enums.ShadowCasterClass ExcludedClasses = Enums.ShadowCasterClass.None)
        {
            float shadowFactor = GetShadowFactorForPoint(P, CallingShadowCaster, ExcludedClasses);

            if (shadowFactor == 0)
            {
                return(Color.White);
            }
            float colorChannel = shadowFactor * GLOBAL_SHADOW_OPACITY;

            return(new Color(
                       1 - (colorChannel - GLOBAL_SHADOW_COLOR.R / 255f * colorChannel),
                       1 - (colorChannel - GLOBAL_SHADOW_COLOR.G / 255f * colorChannel),
                       1 - (colorChannel - GLOBAL_SHADOW_COLOR.B / 255f * colorChannel)
                       ));
        }
        public static Color Get2SampledShadowTintForPoint(Vector3 P, float Radius, IShadowCaster CallingShadowCaster = null, Enums.ShadowCasterClass ExcludedClasses = Enums.ShadowCasterClass.None)
        {
            float sampledShadowFactor = (
                GetShadowFactorForPoint(P + SHADOW_2_SAMPLE_1 * Radius, CallingShadowCaster, ExcludedClasses) +
                GetShadowFactorForPoint(P + SHADOW_2_SAMPLE_2 * Radius, CallingShadowCaster, ExcludedClasses)
                ) / 2f;

            if (sampledShadowFactor == 0)
            {
                return(Color.White);
            }
            float colorChannel = sampledShadowFactor * GLOBAL_SHADOW_OPACITY;

            return(new Color(
                       1 - (colorChannel - GLOBAL_SHADOW_COLOR.R / 255f * colorChannel),
                       1 - (colorChannel - GLOBAL_SHADOW_COLOR.G / 255f * colorChannel),
                       1 - (colorChannel - GLOBAL_SHADOW_COLOR.B / 255f * colorChannel)
                       ));
        }
Example #5
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="?"></param>
        public void RenderShadows( Matrix view, Matrix projection, IShadowCaster shadowCaster )
        {
            if (Config.SkipShadows) {
                return;
            }

            Game.GraphicsDevice.ResetStates();

            if ( csmDepth.Height!=Config.CSMSize || spotDepth.Height!=Config.SpotShadowSize * 4) {
                CreateShadowMaps();
            }

            var device = Game.GraphicsDevice;

            device.Clear( csmDepth.Surface, 1, 0 );
            device.Clear( csmColor.Surface, Color4.White );

            Matrix[] shadowViews, shadowProjections;

            ComputeCSMMatricies( view, out shadowViews, out shadowProjections, out csmViewProjections );

            for (int i=0; i<4; i++) {

                var smSize = Config.CSMSize;
                var context = new ShadowRenderContext();
                context.ShadowView			=	shadowViews[i];
                context.ShadowProjection	=	shadowProjections[i];
                context.ShadowViewport		=	new Viewport( smSize * i, 0, smSize, smSize );
                context.FarDistance			=	1;
                context.SlopeBias			=	Config.CSMSlopeBias;
                context.DepthBias			=	Config.CSMDepthBias;
                context.ColorBuffer			=	csmColor.Surface;
                context.DepthBuffer			=	csmDepth.Surface;

                shadowCaster.RenderShadowMapCascade( context );
            }

            //
            //	Spot-Lights :
            //
            device.Clear( spotDepth.Surface, 1, 0 );
            device.Clear( spotColor.Surface, Color4.White );

            for (int i=0; i<spotLights.Count; i++) {

                var spot	= spotLights[i];
                var smSize	= Config.SpotShadowSize;
                var context = new ShadowRenderContext();
                var dx      = i % 4;
                var dy		= i / 4;
                var far		= spot.Projection.GetFarPlaneDistance();

                context.ShadowView			=	spot.SpotView;
                context.ShadowProjection	=	spot.Projection;
                context.ShadowViewport		=	new Viewport( smSize * dx, smSize * dy, smSize, smSize );
                context.FarDistance			=	far;
                context.SlopeBias			=	Config.SpotSlopeBias;
                context.DepthBias			=	Config.SpotDepthBias;
                context.ColorBuffer			=	spotColor.Surface;
                context.DepthBuffer			=	spotDepth.Surface;

                shadowCaster.RenderShadowMapCascade( context );
            }
        }
        public static Color GetShadowTintForBox(Box B, IShadowCaster CallingShadowCaster = null, Enums.ShadowCasterClass ExcludedClasses = Enums.ShadowCasterClass.None)
        {
            float darkestTint = 1f;

            for (int i = 0; i < VisibleShadowCasters.Count; i++)
            {
                IShadowCaster shadowCaster = VisibleShadowCasters[i];
                if (
                    shadowCaster == CallingShadowCaster ||
                    (
                        ExcludedClasses != Enums.ShadowCasterClass.None &&
                        (shadowCaster.ShadowCasterClass() & ExcludedClasses) != Enums.ShadowCasterClass.None
                    )
                    )
                {
                    continue;
                }
                Box shadowVolume = shadowCaster.GetShadowVolume();
                Box?shadowBox    = shadowVolume.GetIntersectionVolume(B);
                if (shadowBox == null)
                {
                    continue;
                }
                Texture2D shadowTexture = shadowCaster.GetShadowTexture();
                int       x1;
                int       y1;
                int       x2;
                int       y2;
                if (shadowCaster.ShouldTile())
                {
                    x1 = (int)(shadowBox.Value.Left - shadowVolume.Left);
                    y1 = (int)(shadowBox.Value.Back - shadowVolume.Back);
                    x2 = x1 + (int)shadowBox.Value.Width;
                    y2 = y1 + (int)shadowBox.Value.Depth;
                }
                else
                {
                    x1 = (int)Math.Floor((shadowBox.Value.Left - shadowVolume.Left) / shadowVolume.Width * shadowTexture.Width);
                    y1 = (int)Math.Floor((shadowBox.Value.Back - shadowVolume.Back) / shadowVolume.Depth * shadowTexture.Height);
                    x2 = x1 + (int)Math.Floor((shadowBox.Value.Width / shadowVolume.Width) * (shadowTexture.Width - 1));
                    y2 = y1 + (int)Math.Floor((shadowBox.Value.Depth / shadowVolume.Depth) * (shadowTexture.Height - 1));
                }
                float a = GetShadowStrengthOverArea(shadowTexture, x1, y1, x2, y2) * (shadowBox.Value.TopDownSurfaceArea / B.TopDownSurfaceArea) * shadowCaster.GetShadowOpacity();
                if (a > 0)
                {
                    a = 1 - a;
                    if (a < darkestTint)
                    {
                        darkestTint = a;
                    }
                }
            }
            if (darkestTint == 1f)
            {
                return(Color.White);
            }
            float invertDarkest = 1 - darkestTint;

            return(new Color(
                       1 - (invertDarkest - GLOBAL_SHADOW_COLOR.R / 255f * invertDarkest),
                       1 - (invertDarkest - GLOBAL_SHADOW_COLOR.G / 255f * invertDarkest),
                       1 - (invertDarkest - GLOBAL_SHADOW_COLOR.B / 255f * invertDarkest)
                       ));
        }
 public void DrawShadows(IShadowCaster sc, Vector2 light, float lightRange, Color color)
 {
     DrawShadows(sc, light, lightRange, 0, color);
 }
 public void DrawShadows(IShadowCaster sc, Vector2 light, float lightRange)
 {
     DrawShadows(sc, light, lightRange, 0, Color.Black);
 }
Example #9
0
        private void DrawShadows()
        {
            if (shadowReceiverMode != ShadowReceiverMode.Exact)
            {
                return;
            }

            DisposableList <IShadowCaster> shadowCasters = ShadowCasterHelper.VisibleShadowCasters;

            for (int i = 0; i < shadowCasters.Count; i++)
            {
                IShadowCaster shadowCaster = shadowCasters[i];
                Box           shadowVolume = shadowCaster.GetShadowVolume();
                Box?          shadowBox    = shadowVolume.GetIntersectionVolume(BackingBox.B);
                if (shadowBox == null || (!BackingBox.B.isRamp && shadowBox.Value.Top < BackingBox.Top))
                {
                    continue;
                }
                Texture2D shadowTexture = shadowCaster.GetShadowTexture();
                int       xIndex;
                int       yIndex;
                int       sourceWidth;
                int       sourceHeight;
                if (shadowCaster.ShouldTile())
                {
                    xIndex       = (int)(shadowBox.Value.Left - shadowVolume.Left);
                    yIndex       = (int)(shadowBox.Value.Back - shadowVolume.Back);
                    sourceWidth  = (int)shadowBox?.Width;
                    sourceHeight = (int)shadowBox?.Depth;
                }
                else
                {
                    xIndex       = (int)Math.Round((shadowBox.Value.Left - shadowVolume.Left) / shadowVolume.Width * shadowTexture.Width);
                    yIndex       = (int)Math.Round((shadowBox.Value.Back - shadowVolume.Back) / shadowVolume.Depth * shadowTexture.Height);
                    sourceWidth  = (int)Math.Round(shadowBox.Value.Width / shadowVolume.Width * shadowTexture.Width);
                    sourceHeight = (int)Math.Round(shadowBox.Value.Depth / shadowVolume.Depth * shadowTexture.Height);
                }
                float opacity = (1f - (shadowVolume.Top - BackingBox.B.Top) / shadowVolume.Height) * shadowCaster.GetShadowOpacity();
                if (!BackingBox.B.isRamp)
                {
                    GameService.GetService <IRenderService>().PushAlphaFragment(
                        RenderService.AlphaStacks.Shadows,
                        shadowTexture,
                        new Rectangle((int)Math.Round(shadowBox.Value.Left), (int)Math.Round(shadowBox.Value.Back - shadowBox.Value.Top), (int)Math.Round(shadowBox.Value.Width), (int)Math.Round(shadowBox.Value.Depth)),
                        new Rectangle(xIndex, yIndex, sourceWidth, sourceHeight),
                        IsTiling: shadowCaster.ShouldTile(),
                        Tint: Color.White * opacity
                        );
                    if (shadowBox.Value.Front == BackingBox.B.Front)
                    {
                        GameService.GetService <IRenderService>().PushAlphaFragment(
                            RenderService.AlphaStacks.Shadows,
                            shadowTexture,
                            new Rectangle((int)Math.Round(shadowBox.Value.Left), (int)Math.Round(shadowBox.Value.Front - shadowBox.Value.Top), (int)Math.Round(shadowBox.Value.Width), (int)Math.Round(shadowBox.Value.Height)),
                            new Rectangle(xIndex, yIndex + sourceHeight - 1, sourceWidth, 1),
                            IsTiling: shadowCaster.ShouldTile(),
                            Tint: Color.White * opacity
                            );
                    }
                }
                else
                {
                    GameService.GetService <IRenderService>().PushAlphaFragment(
                        RenderService.AlphaStacks.Shadows,
                        shadowTexture,
                        new Rectangle((int)Math.Round(shadowBox.Value.Left), ((int)shadowBox.Value.Back - (int)BackingBox.Back) / 2 + (int)Math.Round(shadowBox.Value.Back - BackingBox.B.Top), (int)Math.Round(shadowBox.Value.Width), (int)Math.Round(shadowBox.Value.Depth * 1.5f)),
                        new Rectangle(xIndex, yIndex, sourceWidth, sourceHeight),
                        IsTiling: shadowCaster.ShouldTile(),
                        Tint: Color.White * opacity
                        );
                }
            }
        }
Example #10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="?"></param>
        public void RenderShadows(Matrix view, Matrix projection, IShadowCaster shadowCaster)
        {
            if (Config.SkipShadows)
            {
                return;
            }

            Game.GraphicsDevice.ResetStates();

            if (csmDepth.Height != Config.CSMSize || spotDepth.Height != Config.SpotShadowSize * 4)
            {
                CreateShadowMaps();
            }

            var device = Game.GraphicsDevice;

            device.Clear(csmDepth.Surface, 1, 0);
            device.Clear(csmColor.Surface, Color4.White);

            Matrix[] shadowViews, shadowProjections;

            ComputeCSMMatricies(view, out shadowViews, out shadowProjections, out csmViewProjections);

            for (int i = 0; i < 4; i++)
            {
                var smSize  = Config.CSMSize;
                var context = new ShadowRenderContext();
                context.ShadowView       = shadowViews[i];
                context.ShadowProjection = shadowProjections[i];
                context.ShadowViewport   = new Viewport(smSize * i, 0, smSize, smSize);
                context.FarDistance      = 1;
                context.SlopeBias        = Config.CSMSlopeBias;
                context.DepthBias        = Config.CSMDepthBias;
                context.ColorBuffer      = csmColor.Surface;
                context.DepthBuffer      = csmDepth.Surface;

                shadowCaster.RenderShadowMapCascade(context);
            }


            //
            //	Spot-Lights :
            //
            device.Clear(spotDepth.Surface, 1, 0);
            device.Clear(spotColor.Surface, Color4.White);

            for (int i = 0; i < spotLights.Count; i++)
            {
                var spot    = spotLights[i];
                var smSize  = Config.SpotShadowSize;
                var context = new ShadowRenderContext();
                var dx      = i % 4;
                var dy      = i / 4;
                var far     = spot.Projection.GetFarPlaneDistance();

                context.ShadowView       = spot.SpotView;
                context.ShadowProjection = spot.Projection;
                context.ShadowViewport   = new Viewport(smSize * dx, smSize * dy, smSize, smSize);
                context.FarDistance      = far;
                context.SlopeBias        = Config.SpotSlopeBias;
                context.DepthBias        = Config.SpotDepthBias;
                context.ColorBuffer      = spotColor.Surface;
                context.DepthBuffer      = spotDepth.Surface;

                shadowCaster.RenderShadowMapCascade(context);
            }
        }