public override void Render(RenderContext context, DeviceContextProxy deviceContext)
            {
                if (!NeedRender)
                {
                    modelStruct.HasShadowMap = 0;
                    modelCB.Upload(deviceContext, ref modelStruct);
                    return;
                }
                OnUpdateLightSource?.Invoke(this, new UpdateLightSourceEventArgs(context));
                ++currentFrame;
                currentFrame %= Math.Max(1, UpdateFrequency);
                if (!FoundLightSource || currentFrame != 0)
                {
                    return;
                }
                if (resolutionChanged)
                {
                    RemoveAndDispose(ref viewResource);
                    viewResource = new ShaderResourceViewProxy(Device, ShadowMapTextureDesc);
                    viewResource.CreateView(DepthStencilViewDesc);
                    viewResource.CreateView(ShaderResourceViewDesc);
                    resolutionChanged = false;
                }

                deviceContext.ClearDepthStencilView(viewResource, DepthStencilClearFlags.Depth, 1.0f, 0);
                var orgFrustum = context.BoundingFrustum;
                var frustum    = new BoundingFrustum(LightView * LightProjection);

                context.BoundingFrustum = frustum;
#if !TEST
                deviceContext.SetViewport(0, 0, Width, Height);

                deviceContext.SetDepthStencil(viewResource.DepthStencilView);
                modelStruct.HasShadowMap = context.RenderHost.IsShadowMapEnabled ? 1 : 0;
                modelCB.Upload(deviceContext, ref modelStruct);
                for (var i = 0; i < context.RenderHost.PerFrameOpaqueNodes.Count; ++i)
                {
                    //Only support opaque object for throwing shadows.
                    var core = context.RenderHost.PerFrameOpaqueNodes[i];
                    if (core.RenderCore.IsThrowingShadow && core.TestViewFrustum(ref frustum))
                    {
                        core.RenderShadow(context, deviceContext);
                    }
                }
                context.BoundingFrustum = orgFrustum;
                context.RenderHost.SetDefaultRenderTargets(false);
                context.SharedResource.ShadowView = viewResource;
#endif
            }
        protected override bool CanRender(RenderContext context)
        {
#if TEST
            if (base.CanRender(context))
#else
            if (base.CanRender(context) && !context.IsShadowPass)
#endif
            {
                OnUpdateLightSource?.Invoke(this, new UpdateLightSourceEventArgs(context));
                ++currentFrame;
                currentFrame %= Math.Max(1, UpdateFrequency);
                return(FoundLightSource && currentFrame == 0);
            }
            else
            {
                return(false);
            }
        }