Example #1
0
        public OptimizedTubePathSample()
        {
            InitializeComponent();


            _disposables = new DisposeList();

            MainDXViewportView.DXSceneDeviceCreated += delegate(object sender, EventArgs args)
            {
                _solidColorEffect = MainDXViewportView.DXScene.DXDevice.EffectsManager.GetEffect <SolidColorEffect>();
                _disposables.Add(_solidColorEffect);

                _stopwatch = new Stopwatch();
                _stopwatch.Start();

                AddSpirals_MeshObjectNode(10, 10, 5000, useMultiThreading: true);

                // Uncomment to see how the tubes are created in a standard Ab3d.PowerToys way.
                //AddSpirals_TubePathVisual3D(10, 10, 5000);

                // To see how to use instancing to draw tube paths, uncomment the following line.
                // Note: In this case is instancing slower then rendering a fixed geometry because the task for the GPU is much more complicated in case of instancing.
                //AddInstancedSpirals(10, 10, 5000);
            };

            // Subscribe to get event when the first frame is rendered
            MainDXViewportView.SceneRendered += MainDXViewportViewOnSceneRendered;

            this.Unloaded += delegate(object sender, RoutedEventArgs args)
            {
                _disposables.Dispose();
            };
        }
        private void MainDxViewportViewOnDxSceneDeviceCreated(object sender, EventArgs e)
        {
            // Create a SolidColorEffect that will be used to render each objects with a color from object's id
            _solidColorEffect = new SolidColorEffect();
            _solidColorEffect.OverrideModelColor = true; // We will overwrite the object's color with color specified in SolidColorEffect.Color

            _disposables.Add(_solidColorEffect);

            MainDXViewportView.DXScene.DXDevice.EffectsManager.RegisterEffect(_solidColorEffect);


            // Create a custom rendering step that will be used instead of standard rendering step
            _objectIdRenderingStep = new CustomActionRenderingStep("ObjectIdRenderingStep")
            {
                CustomAction = ObjectIdRenderingAction,
                IsEnabled    = false
            };

            MainDXViewportView.DXScene.RenderingSteps.AddAfter(MainDXViewportView.DXScene.DefaultRenderObjectsRenderingStep, _objectIdRenderingStep);

            // In this sample we render Object ids to a custom bitmap,
            // so for standard rendering, we disable our custom rendering.
            // But if you went you can enable it and disabled the standard rendering - this will always render objects ids:
            //_objectIdRenderingStep.IsEnabled = true;
            //MainDXViewportView.DXScene.DefaultRenderObjectsRenderingStep.IsEnabled = false;
        }
Example #3
0
        public SolidColorInstanceRendering()
        {
            InitializeComponent();

            MainDXViewportView.DXSceneDeviceCreated += delegate(object sender, EventArgs args)
            {
                _currentRenderingType = GetCurrentRenderingType();

                CreateInstances();

                ChangeRenderingType();
            };

            // IMPORTANT:
            // It is very important to call Dispose method on DXSceneView after the control is not used any more (see help file for more info)
            this.Unloaded += (sender, args) =>
            {
                if (_solidColorEffectWithOutline != null)
                {
                    _solidColorEffectWithOutline.Dispose();
                    _solidColorEffectWithOutline = null;
                }

                MainDXViewportView.Dispose();
            };
        }
Example #4
0
        private void ChangeRenderingType()
        {
            if (MainDXViewportView.DXScene == null)
            {
                return; // Probably WPF 3D rendering
            }
            var color = GetColorFromComboBox(SolidModelColorComboBox);

            if (_currentRenderingType == RenderingTypes.SolidColorEffect)
            {
                MainDXViewportView.DXScene.DefaultRenderObjectsRenderingStep.OverrideEffect = null;
            }


            _currentRenderingType = GetCurrentRenderingType();

            if (_currentRenderingType == RenderingTypes.SolidColorEffect)
            {
                _solidColorEffectWithOutline = new Ab3d.DirectX.Effects.SolidColorEffect
                {
                    Color = color.ToColor4(),
                    OverrideModelColor = true
                };

                _solidColorEffectWithOutline.InitializeResources(MainDXViewportView.DXScene.DXDevice);

                MainDXViewportView.DXScene.DefaultRenderObjectsRenderingStep.OverrideEffect = _solidColorEffectWithOutline;
            }
            else if (_currentRenderingType == RenderingTypes.UseSingleObjectColor)
            {
                // Set IsSolidColorMaterial to render tube instances with solid color without any shading based on lighting
                _instancedMeshGeometryVisual3D.IsSolidColorMaterial = IsSolidColorMaterialCheckBox.IsChecked ?? false;

                var instancesData  = _instancedMeshGeometryVisual3D.InstancesData;
                int instancesCount = instancesData.Length;

                for (var i = 0; i < instancesCount; i++)
                {
                    instancesData[i].DiffuseColor = color.ToColor4();
                }

                _instancedMeshGeometryVisual3D.Update(0, instancesCount, updateBounds: false);
            }
            else
            {
                CreateInstances();
            }
        }
        private SolidColorEffect EnsureSolidColorEffect()
        {
            if (MainDXViewportView.DXScene == null)
            {
                return(null);
            }

            if (_blackOutlineEffect == null)
            {
                _blackOutlineEffect = new SolidColorEffect()
                {
                    Color = Color4.Black,
                    OverrideModelColor = true, // This will render all objects with Black color; when false then object's color is used
                };

                _disposables.Add(_blackOutlineEffect);
                _blackOutlineEffect.InitializeResources(MainDXViewportView.DXScene.DXDevice);
            }

            return(_blackOutlineEffect);
        }
        private void SetupSolidColorEffectWithOutlines()
        {
            // One way to show object outlines is to render the whole scene with black color (using SolidColorEffect)
            // and with expanding the geometry of each object in the direction of triangle normals (setting SolidColorEffect.OutlineThickness property)
            // Then the standard 3D scene is rendered on top of the black 3D scene.
            var dxScene = MainDXViewportView.DXScene;

            _blackOutlineEffect = EnsureSolidColorEffect();

            // Set _blackOutlineEffect properties based on the user controls
            UpdateBlackOutlineEffectForOutlineThickness();

            // Add another RenderObjectsRenderingStep that will render black scene ...
            _renderObjectOutlinesRenderingStep = EnsureRenderObjectsRenderingStep(dxScene);

            // ... and add it before standard RenderObjectsRenderingStep
            if (dxScene != null && !dxScene.RenderingSteps.Contains(_renderObjectOutlinesRenderingStep))
            {
                dxScene.RenderingSteps.AddBefore(dxScene.DefaultRenderObjectsRenderingStep, _renderObjectOutlinesRenderingStep);
            }
        }
Example #7
0
        private void SetupObjectOutlinesRenderingStep()
        {
            // One way to show object outlines is to render the whole scene with black color (using SolidColorEffect)
            // and with expanding the geometry of each object in the direction of triangle normals (setting SolidColorEffect.OutlineThickness property)
            // Then the standard 3D scene is rendered on top of the black 3D scene.

            _blackOutlineEffect = new SolidColorEffect()
            {
                Color = Color4.Black,
                OverrideModelColor = true,  // This will render all objects with Black color; when false then object's color is used
                OutlineThickness   = 3,

                // Use the following 3 settings to show outline for the whole 3D scene:
                WriteMaxDepthValue      = true,                                                      // the black objects will be written to the back of all the objects (using max depth value).
                OverrideRasterizerState = _mainDXViewportView.DXScene.DXDevice.CommonStates.CullNone // render front and back triangles
            };

            _disposables.Add(_blackOutlineEffect);

            _blackOutlineEffect.InitializeResources(_mainDXViewportView.DXScene.DXDevice);

            // Add another RenderObjectsRenderingStep that will render black scene ...
            _renderObjectOutlinesRenderingStep = new RenderObjectsRenderingStep("RenderObjectOutlinesRenderingStep")
            {
                OverrideEffect = _blackOutlineEffect,
                FilterRenderingQueuesFunction = delegate(RenderingQueue queue)
                {
                    return(queue != _mainDXViewportView.DXScene.LineGeometryRenderingQueue);  // Render all objects except 3D lines
                }
            };

            _disposables.Add(_blackOutlineEffect);

            // ... and add it before standard RenderObjectsRenderingStep
            _mainDXViewportView.DXScene.RenderingSteps.AddBefore(_mainDXViewportView.DXScene.DefaultRenderObjectsRenderingStep, _renderObjectOutlinesRenderingStep);


            // Uncomment the following line to prevent rendering standard 3D objects:
            //MainDXViewportView.DXScene.DefaultRenderObjectsRenderingStep.IsEnabled = false;
        }
Example #8
0
        private void OnDxSceneDeviceCreated(object sender, EventArgs e)
        {
            //
            // !!! IMPORTANT !!!
            //
            // Some rendering queues are being sorted by material.
            // This improves performance by rendering objects with similar material one after another and
            // this reduces number of DirectX state changes.
            // But when using ObjectId map, we need to disable rendering queues by material.
            // If this is not done, the objects rendered in the standard rendering pass and
            // objects rendered for object id map will be rendered in different order.
            // Because of this we would not be able to get the original object id from the back.
            //
            // Therefore go through all MaterialSortedRenderingQueue and disable sorting.
            //
            // Note the we do not need to disable sorting by camera distance (TransparentRenderingQueue)
            // because the object order does not change when rendering object id map.

            foreach (var materialSortedRenderingQueue in MainDXViewportView.DXScene.RenderingQueues.OfType <MaterialSortedRenderingQueue>())
            {
                materialSortedRenderingQueue.IsSortingEnabled = false;
            }



            // Create a SolidColorEffect that will be used to render each objects with a color from object's id
            _solidColorEffect = new SolidColorEffect
            {
                // We will overwrite the object's color with color specified in SolidColorEffect.Color
                OverrideModelColor = true,

                // Always use Opaque blend state even if alpha is less then 1 (usually PremultipliedAlphaBlend is used in this case).
                // This will allow us to also use alpha component for the object id (in our case RenderingQueue id)
                OverrideBlendState = MainDXViewportView.DXScene.DXDevice.CommonStates.Opaque,

                // By default for alpha values less then 1, the color components are multiplied with alpha value to produce pre-multiplied colors.
                // This will allow us to also use alpha component for the object id (in our case RenderingQueue id)
                PremultiplyAlphaColors = false
            };


            _disposables.Add(_solidColorEffect);

            MainDXViewportView.DXScene.DXDevice.EffectsManager.RegisterEffect(_solidColorEffect);


            // Create a custom rendering step that will be used instead of standard rendering step.
            // It will be used in the CreateObjectIdBitmapButton_OnClick method below
            _objectIdRenderingStep = new CustomActionRenderingStep("ObjectIdRenderingStep")
            {
                CustomAction = ObjectIdRenderingAction,
                IsEnabled    = false                    // IMPORTANT: disable this custom rendering step - it will be enabled when rendering to bitmap
            };

            MainDXViewportView.DXScene.RenderingSteps.AddAfter(MainDXViewportView.DXScene.DefaultRenderObjectsRenderingStep, _objectIdRenderingStep);

            // In this sample we render Object ids to a custom bitmap,
            // so for standard rendering, we disable our custom rendering.
            // But if you went you can enable it and disabled the standard rendering - this will always render objects ids:
            //
            //_objectIdRenderingStep.IsEnabled = true;
            //MainDXViewportView.DXScene.DefaultRenderObjectsRenderingStep.IsEnabled = false;
        }
Example #9
0
        private void SetupOutlineRenderingStep()
        {
            _solidColorEffectWithOutline = new SolidColorEffect();

            _solidColorEffectWithOutline.Color = Colors.Orange.ToColor4();
            _solidColorEffectWithOutline.OverrideModelColor = true;
            _solidColorEffectWithOutline.OutlineThickness   = 0;
            _solidColorEffectWithOutline.WriteMaxDepthValue = false;

            _solidColorEffectWithOutline.InitializeResources(MainDXViewportView.DXScene.DXDevice);

            _disposables.Add(_solidColorEffectWithOutline);


            _backgroundColor = new Color4(1, 1, 1, 0);


            var stencilSetToOneDescription = new DepthStencilStateDescription()
            {
                IsDepthEnabled = true,
                DepthWriteMask = DepthWriteMask.All,

                DepthComparison  = Comparison.LessEqual,
                IsStencilEnabled = true,
                StencilReadMask  = 0xFF,
                StencilWriteMask = 0xFF,
                FrontFace        =
                {
                    Comparison         = Comparison.Always,
                    DepthFailOperation = StencilOperation.Keep,
                    FailOperation      = StencilOperation.Keep,
                    PassOperation      = StencilOperation.Replace // The value that is set as reference is set in the ContextStateManger when _deviceContext.OutputMerger.SetDepthStencilState is called - the value is set to 1.
                }
            };

            stencilSetToOneDescription.BackFace = stencilSetToOneDescription.FrontFace;

            _stencilSetToOneDepthStencilState = new DepthStencilState(MainDXViewportView.DXScene.Device, stencilSetToOneDescription);

            if (MainDXViewportView.DXScene.DXDevice.IsDebugDevice)
            {
                _stencilSetToOneDepthStencilState.DebugName = "StencilSetToOneDepthStencilState";
            }

            _disposables.Add(_stencilSetToOneDepthStencilState);


            var renderWhenStencilIsNotOneDescription = new DepthStencilStateDescription()
            {
                IsDepthEnabled = true,
                DepthWriteMask = DepthWriteMask.All,

                DepthComparison  = Comparison.LessEqual,
                IsStencilEnabled = true,
                StencilReadMask  = 0xFF,
                StencilWriteMask = 0xFF,
                FrontFace        =
                {
                    Comparison         = Comparison.Greater, // render only when 1 is greater then stencil value
                    DepthFailOperation = StencilOperation.Keep,
                    FailOperation      = StencilOperation.Keep,
                    PassOperation      = StencilOperation.Keep
                }
            };

            renderWhenStencilIsNotOneDescription.BackFace = stencilSetToOneDescription.FrontFace;

            _renderWhenStencilIsNotOneState = new DepthStencilState(MainDXViewportView.DXScene.Device, renderWhenStencilIsNotOneDescription);

            if (MainDXViewportView.DXScene.DXDevice.IsDebugDevice)
            {
                _renderWhenStencilIsNotOneState.DebugName = "RenderWhenStencilIsNotOneState";
            }

            _disposables.Add(_renderWhenStencilIsNotOneState);


            var renderingStepsGroup = new RenderingStepsGroup("Render outline group", MainDXViewportView.DXScene.RenderingSteps);

            renderingStepsGroup.BeforeRunningStep += (object sender, DirectX.RenderingEventArgs args) =>
            {
                var renderingContext = args.RenderingContext;

                // Set new back buffer where we will render outline objects
                SetupOutlineBackBuffers(renderingContext);

                // Set new DepthStencilState that will also set stencil value to 1 for each rendered pixel
                renderingContext.ContextStatesManager.DepthStencilState = _stencilSetToOneDepthStencilState;

                _addOutlineRenderingStep.SourceTexture = _outlineShaderResourceView;
            };

            renderingStepsGroup.AfterRunningStep += (object sender, DirectX.RenderingEventArgs args) =>
            {
                var renderingContext = args.RenderingContext;

                // Reset the saved back buffer
                RestoreBackBuffers(renderingContext);
            };


            // The first step in rendering outlines is to render selected objects with the selected solid color.
            // This is done with creating a custom RenderObjectsRenderingStep
            // and overriding the OverrideEffect to use SolidColorEffect and _stencilSetToOneDepthStencilState.
            // We also render only the selected objects - this is done with using FilterObjectsFunction.
            var renderOutlinesObjectsRenderingStep = new RenderObjectsRenderingStep("Render outlined objects")
            {
                OverrideEffect            = _solidColorEffectWithOutline,
                OverrideDepthStencilState = _stencilSetToOneDepthStencilState,

                FilterObjectsFunction = delegate(RenderablePrimitiveBase objectToRender)
                {
                    // IMPORTANT:
                    // This delegate is highly performance critical because it is called for each object in each frame.
                    // Therefore do not access any WPF's DependencyProperties there.

                    var wpfGeometryModel3DNode = objectToRender.OriginalObject as WpfGeometryModel3DNode;

                    if (wpfGeometryModel3DNode == null)
                    {
                        return(false);
                    }

                    // NOTE:
                    // Here we do a simple check for object name in a List<string>.
                    // If you have a lot of selected objects, use HashSet<string> instead.
                    //
                    // The reason why the check is done by the object name is that this way
                    // we can simply connect the WPF object (that is selected) and the SceneNode object that is created from the WPF object.
                    // So if we define the name for the WPF objects, then the SceneNode objects that are created from them will also have the same name.
                    //
                    // But if it is not possible to name WPF objects of if you have duplicate names,
                    // then you will need to store SceneNode objects in HashSet instead of object names.
                    //
                    // To use this we need to get the SceneNode instances that are created from WPF objects.
                    // One option is to call MainDXViewportView.GetSceneNodeForWpfObject(wpfObject) for each WPF object (this must be called after the SceneNodes are initialized - for example in DXSceneInitialized).
                    // Another option is to wait until SceneNodes are created from WPF objects (in DXSceneInitialized event handler or if the scene was already created after calling MainDXViewportView.Update()).
                    // Then go through all SceneNodes in the hierarchy (you can use MainDXViewportView.DXScene.RootNode.ForEachChildNode method)
                    // and for each WpfGeometryModel3DNode gets its GeometryModel3D and build a Dictionary with WPF (GeometryModel3D) and SceneNode (WpfGeometryModel3DNode) objects.
                    // Then when you select for which WPF objects you want to draw outline, create a HashSet<WpfGeometryModel3DNode> with list of WpfGeometryModel3DNode objects.

                    return(_selectedObjectNames.Contains(wpfGeometryModel3DNode.Name));
                }
            };

            renderingStepsGroup.Children.Add(renderOutlinesObjectsRenderingStep);


            // Add two ExpandPostProcess that will make the outline bigger
            int outlineWidth = (int)OutlineSizeSlider.Value;

            _horizontalExpandPostProcess = new Ab3d.DirectX.PostProcessing.ExpandPostProcess(isVerticalRenderingPass: false, expansionWidth: outlineWidth, backgroundColor: _backgroundColor);
            _verticalExpandPostProcess   = new Ab3d.DirectX.PostProcessing.ExpandPostProcess(isVerticalRenderingPass: true, expansionWidth: outlineWidth, backgroundColor: _backgroundColor);

            _disposables.Add(_horizontalExpandPostProcess);
            _disposables.Add(_verticalExpandPostProcess);

            var expandPostProcesses = new List <PostProcessBase>();

            expandPostProcesses.Add(_horizontalExpandPostProcess);
            expandPostProcesses.Add(_verticalExpandPostProcess);


            // We could also blur the outline to make it bigger, but Expand creates better results
            //var horizontalBlurPostProcess = new Ab3d.DirectX.PostProcessing.SimpleBlurPostProcess(isVerticalBlur: false, filterWidth: 5);
            //var verticalBlurPostProcess   = new Ab3d.DirectX.PostProcessing.SimpleBlurPostProcess(isVerticalBlur: true, filterWidth: 5);
            //horizontalBlurPostProcess.InitializeResources(MainDXViewportView.DXScene.DXDevice);
            //verticalBlurPostProcess.InitializeResources(MainDXViewportView.DXScene.DXDevice);

            //blurPostProcesses.Add(horizontalBlurPostProcess);
            //blurPostProcesses.Add(verticalBlurPostProcess);


            _expandObjectsPostProcessesRenderingSteps = new RenderPostProcessingRenderingStep("Expand objects rendering step", expandPostProcesses);
            renderingStepsGroup.Children.Add(_expandObjectsPostProcessesRenderingSteps);


            MainDXViewportView.DXScene.RenderingSteps.AddAfter(MainDXViewportView.DXScene.DefaultInitializeRenderingStep, renderingStepsGroup);


            _addOutlineRenderingStep = new RenderTextureRenderingStep(RenderTextureRenderingStep.TextureChannelsCount.FourChannels, "Render outline over 3D scene")
            {
                Offsets                 = new Vector4(0, 0, 0, 0),                                                     // preserve original colors
                Factors                 = new Vector4(1, 1, 1, 1),
                TargetViewport          = new ViewportF(0, 0, 1f, 1f),                                                 // render to full screen
                CustomBlendState        = MainDXViewportView.DXScene.DXDevice.CommonStates.NonPremultipliedAlphaBlend, // alpha blend
                CustomDepthStencilState = _renderWhenStencilIsNotOneState,                                             // only render when stencil value is less then 1 (not where the objects are rendered)
            };

            _addOutlineRenderingStep.BeforeRunningStep += delegate(object sender, DirectX.RenderingEventArgs args)
            {
                var renderingContext = args.RenderingContext;

                renderingContext.SetBackBuffer(renderingContext.CurrentBackBuffer, renderingContext.CurrentBackBufferDescription, renderingContext.CurrentRenderTargetView, _outlineDepthStencilView, false);
                //renderingContext.DeviceContext.OutputMerger.SetTargets(_outlineDepthStencilView, renderingContext.CurrentRenderTargetView);
            };

            MainDXViewportView.DXScene.RenderingSteps.AddBefore(MainDXViewportView.DXScene.DefaultCompleteRenderingStep, _addOutlineRenderingStep);
        }
        private void SetupExpandPostProcessOutlines()
        {
            var dxScene = MainDXViewportView.DXScene;

            _blackOutlineEffect = EnsureSolidColorEffect();

            if (_blackOutlineEffect == null)
            {
                return;
            }

            // Reset values that may be changed when using SolidColorEffectWithOutlines
            _blackOutlineEffect.DepthBias = 0;
            _blackOutlineEffect.OverrideRasterizerState = null;
            _blackOutlineEffect.OutlineThickness        = 0;
            _blackOutlineEffect.WriteMaxDepthValue      = true;

            _renderObjectOutlinesRenderingStep = EnsureRenderObjectsRenderingStep(dxScene);

            if (!dxScene.RenderingSteps.Contains(_renderObjectOutlinesRenderingStep))
            {
                dxScene.RenderingSteps.AddBefore(dxScene.DefaultRenderObjectsRenderingStep, _renderObjectOutlinesRenderingStep);
            }


            int outlineWidth = (int)OutlineWidthComboBox.SelectedItem;

            if (_prepareExpandObjectsPostProcessingRenderingStep == null)
            {
                // Expand post process is done in two passes (one horizontal and one vertical)
                _horizontalExpandPostProcess = new Ab3d.DirectX.PostProcessing.ExpandPostProcess(isVerticalRenderingPass: false, expansionWidth: outlineWidth, backgroundColor: dxScene.BackgroundColor);
                _verticalExpandPostProcess   = new Ab3d.DirectX.PostProcessing.ExpandPostProcess(isVerticalRenderingPass: true, expansionWidth: outlineWidth, backgroundColor: dxScene.BackgroundColor);

                _disposables.Add(_horizontalExpandPostProcess);
                _disposables.Add(_verticalExpandPostProcess);

                var expandPostProcesses = new PostProcessBase[]
                {
                    _horizontalExpandPostProcess,
                    _verticalExpandPostProcess
                };

                // To execute the post processes we need to rendering steps:
                // 1) PreparePostProcessingRenderingStep that creates required RenderTargets and ShaderResourceViews and sets that to the RenderPostProcessingRenderingStep
                // 2) RenderPostProcessingRenderingStep that actually executed all the post-processes

                // Because we will execute post-processes before the standard scene rendering,
                // we also need to make sure that the Destination buffer is correctly set (see _prepareExandObjectsPostProcessingRenderingStep.BeforeRunningStep)
                // and that the DepthStencilView is reset after the post-processes are rendered (see _expandObjectsPostProcessesRenderingSteps.AfterRunningStep).

                // First create the RenderPostProcessingRenderingStep because it is needed in the constructor of the PreparePostProcessingRenderingStep
                _expandObjectsPostProcessesRenderingSteps = new RenderPostProcessingRenderingStep("Expand objects rendering step", expandPostProcesses);
                _expandObjectsPostProcessesRenderingSteps.AfterRunningStep += delegate(object sender, RenderingEventArgs args)
                {
                    // Post-processes are usually executed at the end of rendering process and work on 2D textures so they do not require DepthStencil.
                    // The CurrentBackBuffer / Description and RenderTargetView are already correct because they are sent by PreparePostProcessingRenderingStep,
                    // but we need to set the _savedDepthStencilView and SupersamplingCount.
                    args.RenderingContext.SetBackBuffer(args.RenderingContext.CurrentBackBuffer,
                                                        args.RenderingContext.CurrentBackBufferDescription,
                                                        args.RenderingContext.CurrentRenderTargetView,
                                                        _savedDepthStencilView,
                                                        dxScene.SupersamplingCount,
                                                        bindNewRenderTargetsToDeviceContext: true);
                };

                _disposables.Add(_expandObjectsPostProcessesRenderingSteps);


                _prepareExpandObjectsPostProcessingRenderingStep = new PreparePostProcessingRenderingStep(_expandObjectsPostProcessesRenderingSteps, "Prepare expand post process");
                _prepareExpandObjectsPostProcessingRenderingStep.BeforeRunningStep += delegate(object sender, RenderingEventArgs args)
                {
                    // Because after the post-processes are executed we will continue with rendering the scene,
                    // we need to set the DestinationBackBuffer (there will be the final result of the post-processes)
                    // to the currently used BackBuffer. If this is not done, then RenderingContext.FinalBackBuffer is used as destination back buffer.
                    _prepareExpandObjectsPostProcessingRenderingStep.SetCustomDestinationBackBuffer(args.RenderingContext.CurrentBackBuffer,
                                                                                                    args.RenderingContext.CurrentBackBufferDescription,
                                                                                                    args.RenderingContext.CurrentRenderTargetView);

                    // Save CurrentDepthStencilView
                    _savedDepthStencilView = args.RenderingContext.CurrentDepthStencilView;
                };

                _disposables.Add(_prepareExpandObjectsPostProcessingRenderingStep);
            }
            else
            {
                _horizontalExpandPostProcess.ExpansionWidth = outlineWidth;
                _verticalExpandPostProcess.ExpansionWidth   = outlineWidth;
            }


            if (!dxScene.RenderingSteps.Contains(_prepareExpandObjectsPostProcessingRenderingStep))
            {
                dxScene.RenderingSteps.AddAfter(_renderObjectOutlinesRenderingStep, _prepareExpandObjectsPostProcessingRenderingStep);
                dxScene.RenderingSteps.AddAfter(_prepareExpandObjectsPostProcessingRenderingStep, _expandObjectsPostProcessesRenderingSteps);
            }
        }