/// <summary>
        ///
        /// </summary>
        public override void Render(RenderContext renderContext)
        {
            /// --- do not render, if not enabled
            if (!this.IsRendering)
            {
                return;
            }

            if (this.Geometry == null)
            {
                return;
            }

            if (this.Visibility != System.Windows.Visibility.Visible)
            {
                return;
            }

            if (renderHost.RenderTechnique == renderHost.RenderTechniquesManager.RenderTechniques.Get(DeferredRenderTechniqueNames.Deferred) ||
                renderHost.RenderTechnique == renderHost.RenderTechniquesManager.RenderTechniques.Get(DeferredRenderTechniqueNames.GBuffer))
            {
                return;
            }

            if (renderContext.IsShadowPass)
            {
                if (!this.IsThrowingShadow)
                {
                    return;
                }
            }

            /// --- since these values are changed only per window resize, we set them only once here
            //if (this.isResized || renderContext.Camera != this.lastCamera)
            {
                //this.isResized = false;
                //this.lastCamera = renderContext.Camera;

                if (renderContext.Camera is ProjectionCamera)
                {
                    var c = renderContext.Camera as ProjectionCamera;
                    // viewport: W,H,0,0
                    var viewport = new Vector4((float)renderContext.Canvas.ActualWidth, (float)renderContext.Canvas.ActualHeight, 0, 0);
                    var ar       = viewport.X / viewport.Y;
                    this.vViewport.Set(ref viewport);

                    // Actually, we don't really need vFrustum because we already know the depth of the projected line.
                    //var fov = 100.0; // this is a fake value, since the line shader does not use it!
                    //var zn = c.NearPlaneDistance > 0 ? c.NearPlaneDistance : 0.1;
                    //var zf = c.FarPlaneDistance + 0.0;
                    // frustum: FOV,AR,N,F
                    //var frustum = new Vector4((float)fov, (float)ar, (float)zn, (float)zf);
                    //this.vFrustum.Set(ref frustum);
                }
            }
            /// --- set transform paramerers
            var worldMatrix = this.modelMatrix * renderContext.worldMatrix;

            this.effectTransforms.mWorld.SetMatrix(ref worldMatrix);

            /// --- set effect per object const vars
            var lineParams = new Vector4((float)this.Thickness, (float)this.Smoothness, 0, 0);

            this.vLineParams.Set(lineParams);

            /// --- set context
            this.Device.ImmediateContext.InputAssembler.InputLayout = this.vertexLayout;
            this.Device.ImmediateContext.InputAssembler.SetIndexBuffer(this.indexBuffer, Format.R32_UInt, 0);
            this.Device.ImmediateContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.LineList;

            /// --- check instancing
            this.hasInstances = (this.Instances != null) && (this.Instances.Any());
            this.bHasInstances.Set(this.hasInstances);

            /// --- set rasterstate
            this.Device.ImmediateContext.Rasterizer.State = this.rasterState;

            if (this.hasInstances)
            {
                /// --- update instance buffer
                if (this.isChanged)
                {
                    this.instanceBuffer = Buffer.Create(this.Device, this.instanceArray, new BufferDescription(Matrix.SizeInBytes * this.instanceArray.Length, ResourceUsage.Dynamic, BindFlags.VertexBuffer, CpuAccessFlags.Write, ResourceOptionFlags.None, 0));
                    DataStream stream;
                    Device.ImmediateContext.MapSubresource(this.instanceBuffer, MapMode.WriteDiscard, global::SharpDX.Direct3D11.MapFlags.None, out stream);
                    stream.Position = 0;
                    stream.WriteRange(this.instanceArray, 0, this.instanceArray.Length);
                    Device.ImmediateContext.UnmapSubresource(this.instanceBuffer, 0);
                    stream.Dispose();
                    this.isChanged = false;
                }

                /// --- INSTANCING: need to set 2 buffers
                this.Device.ImmediateContext.InputAssembler.SetVertexBuffers(0, new[]
                {
                    new VertexBufferBinding(this.vertexBuffer, VertexSizeInBytes, 0),
                    new VertexBufferBinding(this.instanceBuffer, Matrix.SizeInBytes, 0),
                });

                /// --- render the geometry
                for (int i = 0; i < this.effectTechnique.Description.PassCount; i++)
                {
                    this.effectTechnique.GetPassByIndex(i).Apply(Device.ImmediateContext);
                    this.Device.ImmediateContext.DrawIndexedInstanced(this.Geometry.Indices.Count, this.instanceArray.Length, 0, 0, 0);
                }
            }
            else
            {
                /// --- bind buffer
                this.Device.ImmediateContext.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(this.vertexBuffer, VertexSizeInBytes, 0));

                /// --- render the geometry
                this.effectTechnique.GetPassByIndex(0).Apply(this.Device.ImmediateContext);
                this.Device.ImmediateContext.DrawIndexed(this.Geometry.Indices.Count, 0, 0);
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="host"></param>
        public override void Attach(IRenderHost host)
        {
            /// --- attach
            renderTechnique = host.RenderTechniquesManager.RenderTechniques[DefaultRenderTechniqueNames.Lines];
            base.Attach(host);

            if (Geometry == null)
            {
                return;
            }

            if (renderHost.RenderTechnique == renderHost.RenderTechniquesManager.RenderTechniques.Get(DeferredRenderTechniqueNames.Deferred) ||
                renderHost.RenderTechnique == renderHost.RenderTechniquesManager.RenderTechniques.Get(DeferredRenderTechniqueNames.GBuffer))
            {
                return;
            }

            // --- get device
            vertexLayout    = renderHost.EffectsManager.GetLayout(renderTechnique);
            effectTechnique = effect.GetTechniqueByName(renderTechnique.Name);

            effectTransforms = new EffectTransformVariables(effect);

            // --- get geometry
            var geometry = Geometry as LineGeometry3D;

            // -- set geometry if given
            if (geometry != null)
            {
                /// --- set up buffers
                vertexBuffer = Device.CreateBuffer(BindFlags.VertexBuffer, VertexSizeInBytes, CreateLinesVertexArray());

                /// --- set up indexbuffer
                indexBuffer = Device.CreateBuffer(BindFlags.IndexBuffer, sizeof(int), geometry.Indices.Array);
            }

            /// --- init instances buffer
            hasInstances  = (Instances != null) && (Instances.Any());
            bHasInstances = effect.GetVariableByName("bHasInstances").AsScalar();
            if (hasInstances)
            {
                instanceBuffer = Buffer.Create(Device, instanceArray, new BufferDescription(Matrix.SizeInBytes * instanceArray.Length, ResourceUsage.Dynamic, BindFlags.VertexBuffer, CpuAccessFlags.Write, ResourceOptionFlags.None, 0));
            }

            /// --- set up const variables
            vViewport = effect.GetVariableByName("vViewport").AsVector();
            //this.vFrustum = effect.GetVariableByName("vFrustum").AsVector();
            vLineParams = effect.GetVariableByName("vLineParams").AsVector();

            /// --- set effect per object const vars
            var lineParams = new Vector4((float)Thickness, (float)Smoothness, 0, 0);

            vLineParams.Set(lineParams);

            /// === debug hack
            //{
            //    var texDiffuseMapView = ShaderResourceView.FromFile(device, @"G:\Projects\Deformation Project\FrameworkWPF2012\Externals\HelixToolkit-SharpDX\Source\Examples\SharpDX.Wpf\LightingDemo\TextureCheckerboard2.jpg");
            //    var texDiffuseMap = effect.GetVariableByName("texDiffuseMap").AsShaderResource();
            //    texDiffuseMap.SetResource(texDiffuseMapView);
            //}

            /// --- create raster state
            OnRasterStateChanged(DepthBias);



            //this.rasterState = new RasterizerState(this.device, rasterStateDesc);

            /// --- set up depth stencil state
            //var depthStencilDesc = new DepthStencilStateDescription()
            //{
            //    DepthComparison = Comparison.Less,
            //    DepthWriteMask = global::SharpDX.Direct3D11.DepthWriteMask.All,
            //    IsDepthEnabled = true,
            //};
            //this.depthStencilState = new DepthStencilState(this.device, depthStencilDesc);


            /// --- flush
            Device.ImmediateContext.Flush();
        }