protected override void CreateShadowMap(EntityLightShadow light)
        {
            // create the shadow map
            var shadowMap = new ShadowMap
            {
                LightDirection     = light.Light.LightDirection,
                LightPosition      = light.Entity.Transformation.Translation,
                ShadowMapSize      = light.Light.ShadowMapMaxSize,
                ShadowNearDistance = light.Light.ShadowNearDistance,
                ShadowFarDistance  = light.Light.ShadowFarDistance,
                CascadeCount       = light.Light.Type == LightType.Directional ? light.Light.ShadowMapCascadeCount : 1, // cascades are only supported for directional shadow maps
                LightType          = light.Light.Type,
                Fov    = light.Light.SpotFieldAngle,
                Filter = light.Light.ShadowMapFilterType,
                Layers = light.Light.Layers
            };

            // find or create the shadow map texture
            ShadowMapTexture chosenTexture = null;

            chosenTexture = AllocateOrChooseTexture(shadowMap, light.Light.ShadowMapFilterType == ShadowMapFilterType.Variance ? texturesVsm : texturesDefault);

            shadowMap.Texture = chosenTexture;
            InternalShadowMaps.Add(shadowMap);
            light.ShadowMap = shadowMap;
        }
 /// <inheritdoc/>
 protected override void OnEntityRemoved(Entity entity, EntityLightShadow data)
 {
     if (ManageShadows && data.ShadowMap != null)
     {
         RemoveShadowMap(data);
     }
     base.OnEntityRemoved(entity, data);
 }
        protected override void CreateShadowMap(EntityLightShadow light)
        {
            // create the shadow map
            var shadowMap = new ShadowMap
            {
                LightDirection     = light.Light.LightDirection,
                ShadowMapSize      = light.Light.ShadowMapMinSize,
                ShadowNearDistance = light.Light.ShadowNearDistance,
                ShadowFarDistance  = light.Light.ShadowFarDistance,
                CascadeCount       = light.Light.ShadowMapCascadeCount,
                Filter             = light.Light.ShadowMapFilterType,
                Layers             = light.Light.Layers
            };

            InternalShadowMaps.Add(shadowMap);
            light.ShadowMap = shadowMap;
        }
        private bool ChooseShadowMapTexture(EntityLightShadow light, List <ShadowMapTexture> shadowMapTextures, Dictionary <ShadowMapTexture, int> shadowMapRemainingSize)
        {
            var shadowMap     = light.ShadowMap;
            var shadowMapSize = light.Light.ShadowMapMaxSize;

            // find best texture
            while (shadowMapSize > 0)
            {
                if (shadowMapSize < light.Light.ShadowMapMinSize)
                {
                    shadowMapSize = light.Light.ShadowMapMinSize;
                }

                foreach (var shadowMapTexture in shadowMapTextures)
                {
                    if (shadowMapTexture.GuillotinePacker.TryInsert(shadowMapSize, shadowMapSize, shadowMap.CascadeCount))
                    {
                        shadowMap.Texture = shadowMapTexture;
                        shadowMapRemainingSize[shadowMapTexture] = shadowMapRemainingSize[shadowMapTexture] - (shadowMap.CascadeCount * shadowMapSize * shadowMapSize);
                        shadowMap.ShadowMapSize = shadowMapSize;
                        return(true);
                    }
                }

                if (shadowMapSize == light.Light.ShadowMapMinSize)
                {
                    break;
                }
                shadowMapSize /= 2;
            }

            // Issue a warning only once
            if (!shadowMapFullWarningDone)
            {
                shadowMapFullWarningDone = true;
                Logger.Warning("Unable to find a texture to create the shadow map.");
            }

            shadowMap.Texture = null;
            return(false);
        }
        /// <inheritdoc/>
        protected override void OnEntityRemoved(Entity entity, EntityLightShadow data)
        {
            if (ManageShadows && data.ShadowMap != null)
            {
                InternalShadowMaps.Remove(data.ShadowMap);

                List <ShadowMap> shadowMaps = null;
                if (!texturesDefault.TryGetValue(data.ShadowMap.Texture, out shadowMaps))
                {
                    texturesVsm.TryGetValue(data.ShadowMap.Texture, out shadowMaps);
                }

                if (shadowMaps == null)
                {
                    throw new Exception("Untracked shadow map texture");
                }

                shadowMaps.Remove(data.ShadowMap);

                // if no more shadow maps on this texture, delete it.
                if (shadowMaps.Count == 0)
                {
                    InternalShadowMapTextures.Remove(data.ShadowMap.Texture);
                    Utilities.Dispose(ref data.ShadowMap.Texture.ShadowMapDepthBuffer);
                    Utilities.Dispose(ref data.ShadowMap.Texture.ShadowMapDepthTexture);
                    Utilities.Dispose(ref data.ShadowMap.Texture.ShadowMapRenderTarget);
                    Utilities.Dispose(ref data.ShadowMap.Texture.ShadowMapTargetTexture);
                    Utilities.Dispose(ref data.ShadowMap.Texture.IntermediateBlurRenderTarget);
                    Utilities.Dispose(ref data.ShadowMap.Texture.IntermediateBlurTexture);

                    if (!texturesDefault.Remove(data.ShadowMap.Texture))
                    {
                        texturesVsm.Remove(data.ShadowMap.Texture);
                    }
                }
            }
            base.OnEntityRemoved(entity, data);
        }
        // returns shadow0 - shadow1
        private static int CompareShadows(EntityLightShadow shadow0, EntityLightShadow shadow1)
        {
            var lightTypeComparaison = GetLightTypeValue(shadow0.Light.Type) - GetLightTypeValue(shadow1.Light.Type);

            if (lightTypeComparaison != 0)
            {
                return(lightTypeComparaison);
            }

            var shadowMapSizeDiff = shadow0.Light.ShadowMapMaxSize - shadow1.Light.ShadowMapMaxSize;

            if (shadowMapSizeDiff > 0)
            {
                return(-1);
            }
            if (shadowMapSizeDiff < 0)
            {
                return(1);
            }

            // TODO: more comparisons

            return(0);
        }
 private void RemoveShadowMap(EntityLightShadow data)
 {
     InternalShadowMaps.Remove(data.ShadowMap);
     InternalActiveShadowMaps.Remove(data.ShadowMap);
     data.ShadowMap = null;
 }