private static void GenerateSplit(EEDCamera Camera, DVector3 ShadowVector)
        {
            Vector3 Up = new Vector3(0, 1, 0);
            NewShadowPos = Camera.position;
            DVector3.Normalize(ShadowVector);
            float d = Vector3.Dot(ShadowVector, Up);
            if (d == 1 || d == -1)
            {
                Up = new Vector3(1, 0, 0);
            }
            NewShadowPos -= ShadowDistance * ShadowVector;

            const int ShadowStep = 50;
            NewShadowPos.X = ((int)NewShadowPos.X) / ShadowStep * ShadowStep;
            NewShadowPos.Y = ((int)NewShadowPos.Y) / ShadowStep * ShadowStep;
            NewShadowPos.Z = ((int)NewShadowPos.Z) / ShadowStep * ShadowStep;

            double Coff = 0.125f;
            for (int i = 0; i < SplitsNumber + 1; i++)
            {
                SplitSlices[i] = (Camera.nearClip + (Camera.farClip - Camera.nearClip) * (float)i / (float)SplitsNumber) * (Coff);
                SplitSlices[i] += (Camera.nearClip * System.Math.Pow(Camera.farClip / Camera.nearClip, (float)i / (float)SplitsNumber)) * (1 - Coff);
                SplitSlices[i] /= Camera.farClip;
                SplitSlices[i] *= ShadowDistance;

                CamFrustumPos[i, 0] = Camera.position + (Camera.FarT1 - Camera.position) * (SplitSlices[i] / Camera.farClip);
                CamFrustumPos[i, 1] = Camera.position + (Camera.FarT2 - Camera.position) * (SplitSlices[i] / Camera.farClip);
                CamFrustumPos[i, 2] = Camera.position + (Camera.FarT3 - Camera.position) * (SplitSlices[i] / Camera.farClip);
                CamFrustumPos[i, 3] = Camera.position + (Camera.FarT4 - Camera.position) * (SplitSlices[i] / Camera.farClip);
            }

            Matrix ProjShadowMatrix = Matrix.OrthoRH(100f, 100f, (float)ShadowDistance / 1000f, (float)ShadowDistance * 2f);
            Matrix ViewShadowMatrix = Matrix.LookAtRH(new Vector3(0, 0, 0), Conversion.ToVector3(ShadowVector), Vector3.Cross(Camera.direction, ShadowVector));
            LightViewProjMatrix = ViewShadowMatrix * ProjShadowMatrix;

            for (int i = 0; i < SplitsNumber; i++)
            {

                Vector3[] TransformSplit = new Vector3[8];
                for (int t = 0; t < 4; t++)
                {
                    TransformSplit[t] = Conversion.ToVector3(Vector3.Transform(Conversion.ToVector3(CamFrustumPos[i, t] - NewShadowPos), LightViewProjMatrix));
                    TransformSplit[t + 4] = Conversion.ToVector3(Vector3.Transform(Conversion.ToVector3(CamFrustumPos[i + 1, t] - NewShadowPos), LightViewProjMatrix));
                }

                Vector3 AABBMax = TransformSplit[0];
                Vector3 AABBMin = TransformSplit[0];

                for (int y = 0; y < 8; y++)
                {
                    if (AABBMax.X < TransformSplit[y].X) AABBMax.X = TransformSplit[y].X;
                    if (AABBMax.Y < TransformSplit[y].Y) AABBMax.Y = TransformSplit[y].Y;
                    if (AABBMax.Z < TransformSplit[y].Z) AABBMax.Z = TransformSplit[y].Z;

                    if (AABBMin.X > TransformSplit[y].X) AABBMin.X = TransformSplit[y].X;
                    if (AABBMin.Y > TransformSplit[y].Y) AABBMin.Y = TransformSplit[y].Y;
                    if (AABBMin.Z > TransformSplit[y].Z) AABBMin.Z = TransformSplit[y].Z;
                }
                /*
                AABBMax += new Vector3(0.05f);
                AABBMin -= new Vector3(0.05f);
                */

                // Create the crop matrix
                float scaleX, scaleY, scaleZ;
                float offsetX, offsetY, offsetZ;
                // Use default near-plane value
                AABBMin.Z = 0.0f;

                scaleX = 2.0f / (AABBMax.X - AABBMin.X);
                scaleY = 2.0f / (AABBMax.Y - AABBMin.Y);
                offsetX = -0.5f * (AABBMax.X + AABBMin.X) * scaleX;
                offsetY = -0.5f * (AABBMax.Y + AABBMin.Y) * scaleY;
                scaleZ = 1.0f / ((AABBMax.Z - AABBMin.Z));
                offsetZ = -AABBMin.Z * scaleZ;

                const int CoffShadowStep = 5;
                const float CoffMulti = 100f;
                const float CoffMultiScale = 1000f;

                offsetX = ((float)(((int)(offsetX * CoffMulti)) / CoffShadowStep * CoffShadowStep)) / CoffMulti;
                offsetY = ((float)(((int)(offsetY * CoffMulti)) / CoffShadowStep * CoffShadowStep)) / CoffMulti;
                offsetZ = ((float)(((int)(offsetZ * CoffMulti)) / CoffShadowStep * CoffShadowStep)) / CoffMulti;

                scaleX = ((float)(((int)(scaleX * CoffMultiScale)) / CoffShadowStep * CoffShadowStep)) / CoffMultiScale;
                scaleY = ((float)(((int)(scaleY * CoffMultiScale)) / CoffShadowStep * CoffShadowStep)) / CoffMultiScale;
                scaleZ = ((float)(((int)(scaleZ * CoffMultiScale)) / CoffShadowStep * CoffShadowStep)) / CoffMultiScale;

                CropMatrices[i] = new Matrix(scaleX, 0.0f, 0.0f, 0.0f, 0.0f, scaleY, 0.0f, 0.0f, 0.0f, 0.0f, scaleZ, 0.0f, offsetX, offsetY, offsetZ, 1.0f);

                DMatrix Inv = DMatrix.Invert(Conversion.ToDoubleMatrix(LightViewProjMatrix * CropMatrices[i]));

                DVector3 LocPos = DVector3.Transform(new DVector3(), Inv);
                NewCamPositions[i] = NewShadowPos + LocPos;
            }
        }
        public static void RenderObj(float TimeMili, Device device, EEDCamera Camera, Vector3 LightDirection, Vector3 LightColor, List<GameObject> GOs)
        {
            Matrix[] S_VP = new Matrix[SplitsNumber];
            float[] SplitDistances = new float[SplitsNumber];
            for (int i = 0; i < SplitsNumber; i++)
            {
                S_VP[i] = LightViewProjMatrix * CropMatrices[i];
                SplitDistances[i] = (float)SplitSlices[i + 1];///Camera.farClip;
            }
            DMatrix W_S_CAM = DMatrix.CreateTranslation(-NewShadowPos);

            Matrix[] S_WVP = new Matrix[SplitsNumber];
            for (int i = 0; i < GOs.Count; i++)
                if (GOs[i] != null)
                {
                    for (int y = 0; y < SplitsNumber; y++)
                    {
                        S_WVP[y] = Conversion.ToMatrix(GOs[i].Transformation * DMatrix.CreateTranslation(-NewShadowPos)) * S_VP[y];
                    }

                    if (GOs[i].StopSplit > -1)
                        GOs[i].DrawPSSM(device, TimeMili, Camera, LightDirection, LightColor, S_WVP, SplitDistances);
                    else
                        GOs[i].Draw(device, Camera, LightColor, LightDirection);
                }
        }
        public void DrawSplitShadows(float TimeMili, Matrix Transform, Matrix VP, Vector3 LightDirection, Vector3 LightColor,
            Matrix[] SMatrixs, float[] SplitDistances)
        {
            constants.WVP = Matrix.Transpose(Transform * VP);
            constants.World = Matrix.Transpose(Transform);
            constants.LightPosition = Conversion.ToVector4(LightDirection);//LShadow.Position - Camera.position);
            constants.H = new Vector4(PSSMsHelper.SplitShadowsSize, 0, 0, 0);

            unsafe
            {
                fixed (float* buffer = constants.cropMatrix)
                {
                    for (int x = 0; x < PSSMsHelper.SplitsNumber; x++)
                    {
                        buffer[x * 16 + 0] = SMatrixs[x].M11;
                        buffer[x * 16 + 1] = SMatrixs[x].M21;
                        buffer[x * 16 + 2] = SMatrixs[x].M31;
                        buffer[x * 16 + 3] = SMatrixs[x].M41;

                        buffer[x * 16 + 4] = SMatrixs[x].M12;
                        buffer[x * 16 + 5] = SMatrixs[x].M22;
                        buffer[x * 16 + 6] = SMatrixs[x].M32;
                        buffer[x * 16 + 7] = SMatrixs[x].M42;

                        buffer[x * 16 + 8] = SMatrixs[x].M13;
                        buffer[x * 16 + 9] = SMatrixs[x].M23;
                        buffer[x * 16 + 10] = SMatrixs[x].M33;
                        buffer[x * 16 + 11] = SMatrixs[x].M43;

                        buffer[x * 16 + 12] = SMatrixs[x].M14;
                        buffer[x * 16 + 13] = SMatrixs[x].M24;
                        buffer[x * 16 + 14] = SMatrixs[x].M34;
                        buffer[x * 16 + 15] = SMatrixs[x].M44;
                    }
                }

                fixed (float* buffer = constants.SplitPlane)
                {
                    for (int x = 0; x < PSSMsHelper.SplitsNumber; x++)
                        buffer[x*4] = SplitDistances[x];
                }
            }

            Program.context.InputAssembler.InputLayout = Materials[0].Effect.layout;
            Program.context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
            Program.context.InputAssembler.SetVertexBuffers(0, binding);
            Program.context.InputAssembler.SetIndexBuffer(Indices, Format.R32_UInt, 0);

            DifuseName = "";
            SpecularMapName = "";
            NormalMapName = "";
            SelfMapName = "";
            UV2DifuseName = "";
            ShaderName = "";

            //NoDoubleSide
            for (int i = 0; i < Materials.Length; i++)
            {
                if (!Materials[i].DoubleSide)
                {
                    if (ShaderName != Materials[i].Effect.Name)
                    {
                        Materials[i].Effect.renderTechniques[2].GetPassByIndex(0).Apply(Program.context);
                        ShaderName = Materials[i].Effect.Name;
                        DifuseName = ""; SpecularMapName = ""; NormalMapName = "";
                        SelfMapName = ""; UV2DifuseName = ""; ShaderName = "";
                        Program.context.PixelShader.SetShaderResource(5, Program.MyScene.SkyBox.CubeSRV);
                        Program.context.PixelShader.SetSampler(5, DrawHelper.SamplLinWrapMip);
                        Program.context.PixelShader.SetShaderResource(6, PSSMsHelper.SMArraySRV);

                    }

                    CahseSetTexture(Materials[i]);

                    constants.Color = Conversion.ToVector4(LightColor, Materials[i].Alpha / 255f);

                    SetConstants(false);

                    Program.context.DrawIndexed(Meshes[i].IndexCount, Meshes[i].StartIndex, 0);
                }
            }
            DifuseName = "";
            SpecularMapName = "";
            NormalMapName = "";
            SelfMapName = "";
            UV2DifuseName = "";
            ShaderName = "";
            //DoubleSide
            for (int i = 0; i < Materials.Length; i++)
            {
                if (Materials[i].DoubleSide)
                {
                    if (ShaderName != Materials[i].Effect.Name)
                    {
                        Materials[i].Effect.renderTechniques[2].GetPassByIndex(1).Apply(Program.context);
                        ShaderName = Materials[i].Effect.Name;
                        DifuseName = ""; SpecularMapName = ""; NormalMapName = "";
                        SelfMapName = ""; UV2DifuseName = ""; ShaderName = "";
                        Program.context.PixelShader.SetShaderResource(5, Program.MyScene.SkyBox.CubeSRV);
                        Program.context.PixelShader.SetSampler(5, DrawHelper.SamplLinWrapMip);
                        Program.context.PixelShader.SetShaderResource(6, PSSMsHelper.SMArraySRV);
                    }

                    CahseSetTexture(Materials[i]);
                    constants.Color = Conversion.ToVector4(LightColor, Materials[i].Alpha / 255f);

                    SetConstants(false);

                    Program.context.DrawIndexed(Meshes[i].IndexCount, Meshes[i].StartIndex, 0);
                }
            }
        }
        public void DrawSplit(float TimeMili, Matrix MainWVP, Matrix[] CropMatrix, int StartIndex, int StopIndex)
        {
            constants.WVP = Matrix.Transpose(MainWVP);
            constants.Color = Conversion.ToVector4(new Vector3(), 0);
            constants.StartSplit = StartIndex;
            constants.StopSplit = StopIndex;

            unsafe
            {
                fixed (float* buffer = constants.cropMatrix)
                {
                    for (int x = 0; x < PSSMsHelper.SplitsNumber; x++)
                    {
                        buffer[x * 16 + 0 ] = CropMatrix[x].M11;
                        buffer[x * 16 + 1 ] = CropMatrix[x].M21;
                        buffer[x * 16 + 2 ] = CropMatrix[x].M31;
                        buffer[x * 16 + 3 ] = CropMatrix[x].M41;

                        buffer[x * 16 + 4 ] = CropMatrix[x].M12;
                        buffer[x * 16 + 5 ] = CropMatrix[x].M22;
                        buffer[x * 16 + 6 ] = CropMatrix[x].M32;
                        buffer[x * 16 + 7 ] = CropMatrix[x].M42;

                        buffer[x * 16 + 8 ] = CropMatrix[x].M13;
                        buffer[x * 16 + 9 ] = CropMatrix[x].M23;
                        buffer[x * 16 + 10] = CropMatrix[x].M33;
                        buffer[x * 16 + 11] = CropMatrix[x].M43;

                        buffer[x * 16 + 12] = CropMatrix[x].M14;
                        buffer[x * 16 + 13] = CropMatrix[x].M24;
                        buffer[x * 16 + 14] = CropMatrix[x].M34;
                        buffer[x * 16 + 15] = CropMatrix[x].M44;
                    }
                }
            }

            Program.context.InputAssembler.InputLayout = Materials[0].Effect.layout;
            Program.context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
            Program.context.InputAssembler.SetVertexBuffers(0, binding);
            Program.context.InputAssembler.SetIndexBuffer(Indices, Format.R32_UInt, 0);

            //NoDoubleSide&NoAlphaTest
            {
                Materials[0].Effect.renderTechniques[1].GetPassByIndex(0).Apply(Program.context);

                SetConstants(true);

                for (int i = 0; i < Materials.Length; i++)
                {
                    if (!Materials[i].DoubleSide && Materials[i].Alpha < 1)
                    {
                        Program.context.DrawIndexed(Meshes[i].IndexCount, Meshes[i].StartIndex, 0);
                    }
                }
            }
            DifuseName = "";

            //NoDoubleSide&AlphaTest
            for (int i = 0; i < Materials.Length; i++)
            {
                if (!Materials[i].DoubleSide && Materials[i].Alpha >= 1)
                {
                    if (ShaderName != Materials[i].Effect.Name)
                    {
                        Materials[i].Effect.renderTechniques[1].GetPassByIndex(0).Apply(Program.context);
                        ShaderName = Materials[i].Effect.Name;
                        DifuseName = "";
                    }
                    if (DifuseName != Materials[i].Diffuse.Name)
                    {
                        Program.context.PixelShader.SetShaderResource(0, Materials[i].Diffuse.TextureResource);
                        Program.context.PixelShader.SetSampler(0, Materials[i].DiffuseSamplerState);
                        DifuseName = Materials[i].Diffuse.Name;
                    }

                    constants.Color = Conversion.ToVector4(new Vector3(), Materials[i].Alpha / 255f);

                    SetConstants(true);

                    Program.context.DrawIndexed(Meshes[i].IndexCount, Meshes[i].StartIndex, 0);
                }
            }

            //DoubleSide&AlphaTest
            for (int i = 0; i < Materials.Length; i++)
            {
                if (Materials[i].DoubleSide)
                {
                    if (ShaderName != Materials[i].Effect.Name)
                    {
                        Materials[i].Effect.renderTechniques[1].GetPassByIndex(1).Apply(Program.context);
                        ShaderName = Materials[i].Effect.Name;
                        DifuseName = "";
                    }
                    if (DifuseName != Materials[i].Diffuse.Name)
                    {
                        Program.context.PixelShader.SetShaderResource(0, Materials[i].Diffuse.TextureResource);
                        Program.context.PixelShader.SetSampler(0, Materials[i].DiffuseSamplerState);
                        DifuseName = Materials[i].Diffuse.Name;
                    }

                    constants.Color = Conversion.ToVector4(new Vector3(), Materials[i].Alpha / 255f);

                    SetConstants(true);

                    Program.context.DrawIndexed(Meshes[i].IndexCount, Meshes[i].StartIndex, 0);
                }
            }
        }
        public void DrawNoShadows(float TimeMili, Matrix Transform, Matrix VP, Vector3 LightDirection, Vector3 LightColor)
        {
            constants.WVP = Matrix.Transpose(Transform * VP);
            constants.World = Matrix.Transpose(Transform);
            constants.LightPosition = Conversion.ToVector4(LightDirection);//LShadow.Position - Camera.position);

            Program.context.InputAssembler.InputLayout = Materials[0].Effect.layout;
            Program.context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
            Program.context.InputAssembler.SetVertexBuffers(0, binding);
            Program.context.InputAssembler.SetIndexBuffer(Indices, Format.R32_UInt, 0);

            DifuseName = "";
            SpecularMapName = "";
            NormalMapName = "";
            SelfMapName = "";
            UV2DifuseName = "";
            ShaderName = "";

            //NoDoubleSide
            for (int i = 0; i < Materials.Length; i++)
            {
                if(!Materials[i].DoubleSide)
                {
                    if (ShaderName != Materials[i].Effect.Name)
                    {
                        Materials[i].Effect.renderTechniques[0].GetPassByIndex(0).Apply(Program.context);
                        ShaderName = Materials[i].Effect.Name;
                        DifuseName = ""; SpecularMapName = ""; NormalMapName = "";
                        SelfMapName = ""; UV2DifuseName = ""; ShaderName = "";
                        Program.context.PixelShader.SetShaderResource(5, Program.MyScene.SkyBox.CubeSRV);
                        //Program.context.PixelShader.SetShaderResource(5, PSSMsHelper.SMArraySRV);

                        Program.context.PixelShader.SetSampler(5, DrawHelper.SamplLinWrapMip);
                    }

                    CahseSetTexture(Materials[i]);
                    constants.Color = Conversion.ToVector4(LightColor, Materials[i].Alpha / 255f);
                    SetConstants(false);
                    Program.context.DrawIndexed(Meshes[i].IndexCount, Meshes[i].StartIndex, 0);
                }
            }
            DifuseName = "";
            SpecularMapName = "";
            NormalMapName = "";
            SelfMapName = "";
            UV2DifuseName = "";
            ShaderName = "";
            //DoubleSide
            for (int i = 0; i < Materials.Length; i++)
            {
                if (Materials[i].DoubleSide)
                {
                    if (ShaderName != Materials[i].Effect.Name)
                    {
                        Materials[i].Effect.renderTechniques[0].GetPassByIndex(1).Apply(Program.context);
                        ShaderName = Materials[i].Effect.Name;
                        DifuseName = ""; SpecularMapName = ""; NormalMapName = "";
                        SelfMapName = ""; UV2DifuseName = ""; ShaderName = "";
                        Program.context.PixelShader.SetShaderResource(5, Program.MyScene.SkyBox.CubeSRV);
                        Program.context.PixelShader.SetSampler(5, DrawHelper.SamplLinWrapMip);
                    }

                    CahseSetTexture(Materials[i]);
                    constants.Color = Conversion.ToVector4(LightColor, Materials[i].Alpha / 255f);
                    SetConstants(false);
                    Program.context.DrawIndexed(Meshes[i].IndexCount, Meshes[i].StartIndex, 0);
                }
            }
        }
        public void DrawDepth(float TimeMili, Matrix MainWVP, EEDCamera Camera)
        {
            constants.WVP = Matrix.Transpose(MainWVP);
            constants.Color = new Vector4(0, 0, 0, 0);
            constants.CamPosition.Z = Camera.farClip;
            constants.CamPosition.W = Camera.nearClip;
            Program.context.InputAssembler.InputLayout = Materials[0].Effect.layout;
            Program.context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
            Program.context.InputAssembler.SetVertexBuffers(0, binding);
            Program.context.InputAssembler.SetIndexBuffer(Indices, Format.R32_UInt, 0);

            //NoDoubleSide&NoAlphaTest
            {
                Materials[0].Effect.renderTechniques[1].GetPassByIndex(2).Apply(Program.context);

                SetConstants(false);

                for (int i = 0; i < Materials.Length; i++)
                {
                    if (!Materials[i].DoubleSide && Materials[i].Alpha < 1)
                        Program.context.DrawIndexed(Meshes[i].IndexCount, Meshes[i].StartIndex, 0);
                }
            }
            DifuseName = "";

            //NoDoubleSide&AlphaTest
            for (int i = 0; i < Materials.Length; i++)
            {
                if (!Materials[i].DoubleSide && Materials[i].Alpha >= 1)
                {
                    if (ShaderName != Materials[i].Effect.Name)
                    {
                        Materials[i].Effect.renderTechniques[1].GetPassByIndex(2).Apply(Program.context);
                        ShaderName = Materials[i].Effect.Name;
                        DifuseName = "";
                    }
                    if (DifuseName != Materials[i].Diffuse.Name)
                    {
                        Program.context.PixelShader.SetShaderResource(0, Materials[i].Diffuse.TextureResource);
                        Program.context.PixelShader.SetSampler(0, Materials[i].DiffuseSamplerState);
                        DifuseName = Materials[i].Diffuse.Name;
                    }

                    constants.Color = Conversion.ToVector4(new Vector3(), Materials[i].Alpha / 255f);
                    SetConstants(false);
                    Program.context.DrawIndexed(Meshes[i].IndexCount, Meshes[i].StartIndex, 0);
                }
            }

            //DoubleSide&AlphaTest
            for (int i = 0; i < Materials.Length; i++)
            {
                if (Materials[i].DoubleSide)
                {
                    if (ShaderName != Materials[i].Effect.Name)
                    {
                        Materials[i].Effect.renderTechniques[1].GetPassByIndex(3).Apply(Program.context);
                        ShaderName = Materials[i].Effect.Name;
                        DifuseName = "";
                    }
                    if (DifuseName != Materials[i].Diffuse.Name)
                    {
                        Program.context.PixelShader.SetShaderResource(0, Materials[i].Diffuse.TextureResource);
                        Program.context.PixelShader.SetSampler(0, Materials[i].DiffuseSamplerState);
                        DifuseName = Materials[i].Diffuse.Name;
                    }

                    constants.Color = Conversion.ToVector4(new Vector3(), Materials[i].Alpha / 255f);
                    SetConstants(false);
                    Program.context.DrawIndexed(Meshes[i].IndexCount, Meshes[i].StartIndex, 0);
                }
            }
        }