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