/// <summary> /// Draws this pass using the specified drawing context. /// </summary> public override void Draw(DrawingContext context, IList <IDrawableObject> drawables) { if (shadowCasterQuery == null) { shadowCasterQuery = context.CreateSpatialQuery <IDrawableObject>(drawable => drawable.CastShadow); } light.UpdateShadowFrustum(context, shadowCasterQuery); shadowCasterQuery.FindAll(light.ShadowFrustum, shadowCasters); Matrix oldView = context.matrices.view; Matrix oldProjection = context.matrices.projection; Begin(); // Leave the border pixels untouched so the shadow will not be stretched // when using clamped sampling. var viewport = context.graphics.Viewport; context.graphics.Viewport = new Viewport(viewport.X + 1, viewport.Y + 1, viewport.Width - 2, viewport.Height - 2); context.matrices.View = light.ShadowFrustum.Matrix; context.matrices.Projection = Matrix.Identity; context.graphics.SamplerStates[0] = SamplerState.PointClamp; context.graphics.BlendState = BlendState.Opaque; context.graphics.DepthStencilState = DepthStencilState.Default; for (int i = 0; i < shadowCasters.Count; ++i) { var shadowCaster = shadowCasters[i]; if (!shadowCaster.OnAddedToView(context)) { continue; } var material = shadowCaster.Material; if (material == null) { material = depthMaterial; } else { material = material.GetMaterialByUsage(MaterialUsage.Depth); } if (material != null) { shadowCaster.Draw(context, material); } } shadowCasters.Clear(); End(context); context.matrices.View = oldView; context.matrices.Projection = oldProjection; }