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 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) )); }