public PlanarShadows()
        {
            InitializeComponent();

            _disposables = new DisposeList();

            MainDXViewportView.DXSceneInitialized += delegate(object sender, EventArgs args)
            {
                if (MainDXViewportView.DXScene != null)
                {
                    string textureFileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources/10x10-texture.png");

                    // To load a texture from file, you can use the TextureLoader.LoadShaderResourceView (this supports loading standard image files and also loading dds files).
                    // This method returns a ShaderResourceView and it can also set a textureInfo parameter that defines some of the properties of the loaded texture (bitmap size, dpi, format, hasTransparency).
                    TextureInfo textureInfo;
                    var         loadedShaderResourceView = Ab3d.DirectX.TextureLoader.LoadShaderResourceView(MainDXViewportView.DXScene.Device, textureFileName, out textureInfo);

                    _disposables.Add(loadedShaderResourceView);


                    // Get recommended BlendState based on HasTransparency and HasPreMultipliedAlpha values.
                    // Possible values are: CommonStates.Opaque, CommonStates.PremultipliedAlphaBlend or CommonStates.NonPremultipliedAlphaBlend.
                    var recommendedBlendState = MainDXViewportView.DXScene.DXDevice.CommonStates.GetRecommendedBlendState(textureInfo.HasTransparency, textureInfo.HasPremultipliedAlpha);

                    _planarShadowRenderingProvider = new PlanarShadowRenderingProvider()
                    {
                        ShadowPlaneCenterPosition  = new Vector3(0, 0, 0),
                        ShadowPlaneSize            = new Vector2(400, 400),
                        ShadowPlaneNormalVector    = new Vector3(0, 1, 0),
                        ShadowPlaneHeightDirection = new Vector3(0, 0, -1),

                        ShadowPlaneMaterial = new StandardMaterial()
                        {
                            DiffuseColor      = Color3.White, // When DiffuseTextures are set, then DiffuseColor is used as a color filter (White means no filter)
                            DiffuseTextures   = new ShaderResourceView[] { loadedShaderResourceView },
                            TextureBlendState = recommendedBlendState,
                            HasTransparency   = textureInfo.HasTransparency
                        },

                        ShadowPlaneBackMaterial = new StandardMaterial()
                        {
                            DiffuseColor = Colors.DimGray.ToColor3()
                        },

                        ShadowColor        = Color3.Black,
                        ShadowTransparency = 0.65f,

                        // Because shadow is rendered as standard 3D object, we need to offset it from the shadow plane
                        // to prevent z-fighting problems that occur when two 3D objects are rendered to the same 3D position.
                        // This value need to be very small so that it is not seen that the shadow is above the plane.
                        // Default value is 0.01f.
                        ShadowOffsetFromPlane = 0.01f,

                        // When using PlanarShadowRenderingProvider we do not need PlanarShadowMeshCreator from Ab3d.PowerToys
                        // to prepare a special MeshGeometry3D for us. Also PlanarShadowMeshCreator does not need to manually (on the CPU)
                        // cut the shadow to the plane bounds but this can be done with using hardware accelerated algorithm (using stencil buffer).
                        // But if we still want to use PlanarShadowMeshCreator we can set the following two properties to false
                        // (for example if we wanted to use PlanarShadowRenderingProvider just to provide proper transparent shadows).
                        ApplyShadowMatrix      = true,
                        CutShadowToPlaneBounds = true,

                        // To use a custom light that does not illuminate the 3D scene set the CustomShadowLight.
                        // Otherwise the first light that has DXAttributeType.IsCastingShadow attribute set to true is used.
                        // If no light has IsCastingShadow attribute set, then the first directional or point light is used.
                        //CustomShadowLight = new Ab3d.DirectX.Lights.DirectionalLight(new Vector3(0, -1, 1))
                        //CustomShadowLight = new Ab3d.DirectX.Lights.PointLight(new Vector3(0, 500, 0), 300)
                    };

                    _disposables.Add(_planarShadowRenderingProvider);


                    MainDXViewportView.DXScene.InitializeShadowRendering(_planarShadowRenderingProvider);
                }


                _lightHorizontalAngle = -60;
                _lightVerticalAngle   = 60;
                _lightDistance        = 500;

                _ambientLight = new AmbientLight(System.Windows.Media.Color.FromRgb(40, 40, 40));

                _shadowPointLight       = new PointLight();
                _shadowDirectionalLight = new DirectionalLight();

                Camera1.ShowCameraLight = ShowCameraLightType.Never; // prevent adding camera's light

                SetShadowLight(isDirectionalLight: true);

                UpdateLights();

                CreateSampleObjects();
            };



            this.PreviewKeyDown += OnPreviewKeyDown;

            // This will allow receiving keyboard events
            this.Focusable = true;
            this.Focus();

            this.Unloaded += delegate(object sender, RoutedEventArgs args)
            {
                StopAnimation();

                _disposables.Dispose();
                MainDXViewportView.Dispose();
            };
        }
        public PlanarShadowsCustomization()
        {
            InitializeComponent();

            _disposables = new DisposeList();

            MainDXViewportView.DXSceneInitialized += delegate(object sender, EventArgs args)
            {
                if (MainDXViewportView.DXScene != null)
                {
                    // Load texture file into ShaderResourceView (in our case we load dds file; but we could also load png file)
                    string textureFileName          = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources/GrassTexture.jpg");
                    var    loadedShaderResourceView = Ab3d.DirectX.TextureLoader.LoadShaderResourceView(MainDXViewportView.DXScene.DXDevice.Device, textureFileName);

                    _disposables.Add(loadedShaderResourceView);

                    // Define DXEngine's materials for shadow plane
                    _shadowPlaneMaterial = new StandardMaterial()
                    {
                        DiffuseColor    = Color3.White, // When DiffuseTextures are set, then DiffuseColor is used as a color filter (White means no filter)
                        DiffuseTextures = new ShaderResourceView[] { loadedShaderResourceView }
                    };

                    _shadowPlaneBackMaterial = new StandardMaterial()
                    {
                        DiffuseColor = Colors.DimGray.ToColor3()
                    };

                    _disposables.Add(_shadowPlaneMaterial);
                    _disposables.Add(_shadowPlaneBackMaterial);


                    // Define the PlanarShadowRenderingProvider
                    _planarShadowRenderingProvider = new PlanarShadowRenderingProvider()
                    {
                        // We need to provide information about the position of the plane in 3D space
                        ShadowPlaneCenterPosition  = new Vector3(0, 0, 0),
                        ShadowPlaneSize            = new Vector2(400, 400),
                        ShadowPlaneNormalVector    = new Vector3(0, 1, 0),
                        ShadowPlaneHeightDirection = new Vector3(0, 0, -1),

                        // In case ShadowPlaneMaterial and/or ShadowPlaneBackMaterial are defined
                        // the PlanarShadowRenderingProvider will also render the 3D plane.
                        ShadowPlaneMaterial     = _shadowPlaneMaterial,
                        ShadowPlaneBackMaterial = _shadowPlaneBackMaterial,

                        // Set shadow properties
                        ShadowColor        = Color3.Black,
                        ShadowTransparency = (float)ShadowTransparencySlider.Value / 100.0f, // default value is 0.65f

                        // Because shadow is rendered as standard 3D object, we need to offset it from the shadow plane
                        // to prevent z-fighting problems that occur when two 3D objects are rendered to the same 3D position.
                        // This value need to be very small so that it is not seen that the shadow is above the plane.
                        // Default value is 0.01f.
                        ShadowOffsetFromPlane = 0.01f,

                        // When using PlanarShadowRenderingProvider we do not need PlanarShadowMeshCreator from Ab3d.PowerToys
                        // to prepare a special MeshGeometry3D for us. Also PlanarShadowMeshCreator does not need to manually (on the CPU)
                        // cut the shadow to the plane bounds but this can be done with using hardware accelerated algorithm (using stencil buffer).
                        // But if we still want to use PlanarShadowMeshCreator we can set the following two properties to false
                        // (for example if we wanted to use PlanarShadowRenderingProvider just to provide proper transparent shadows).
                        ApplyShadowMatrix      = true,
                        CutShadowToPlaneBounds = true,

                        IsCheckingIsCastingShadow = false, // Initially do not check for IsCastingShadow values (this is also a default value). See comments in LoadModel for more info.

                        //CustomShadowLight = new Ab3d.DirectX.Lights.DirectionalLight(new Vector3(0, -1, 1))
                        //CustomShadowLight = new Ab3d.DirectX.Lights.PointLight(new Vector3(0, 500, 0), 300)
                    };

                    _disposables.Add(_planarShadowRenderingProvider);


                    MainDXViewportView.DXScene.InitializeShadowRendering(_planarShadowRenderingProvider);
                }


                _lightHorizontalAngle = 30;
                _lightVerticalAngle   = 27;
                _lightDistance        = 500;

                _ambientLight = new AmbientLight(System.Windows.Media.Color.FromRgb(40, 40, 40));

                _shadowPointLight       = new PointLight();
                _shadowDirectionalLight = new DirectionalLight();

                Camera1.ShowCameraLight = ShowCameraLightType.Never; // prevent adding camera's light

                SetShadowLight(isDirectionalLight: true);

                UpdateLights();

                _loadedModel3D = LoadModel3D();
                MainViewport.Children.Add(_loadedModel3D.CreateModelVisual3D());
            };



            this.PreviewKeyDown += OnPreviewKeyDown;

            // This will allow receiving keyboard events
            this.Focusable = true;
            this.Focus();

            this.Unloaded += delegate(object sender, RoutedEventArgs args)
            {
                _disposables.Dispose();
                MainDXViewportView.Dispose();
            };
        }