SharpDX-在循环之间保存已绘制的图元

问题描述

对此有种种麻烦,我觉得这应该很容易。这是我的设置:

  1. 我正在使用SharpDX在带有rendertarget的Direct2d上的d3dimage上绘制图元(有效)
  2. 我正在循环使用计时器重绘此内容

对于我的应用程序,我希望我们的用户能够绘制很多项目(例如50,000行)。因为我不想每次都重新渲染这些内容,所以我正在寻找一种方法将这些行保存到位图,另一个渲染器,缓冲区中,这样我就可以说“绘制整个内容” ”,而不必遍历每个人再次绘制它。

我尝试创建辅助rendertarget并将其通过bitmap.copyFromrendertarget转换为Direct2d1位图,但是它似乎是在复制我的整个图像,而不只是复制该渲染目标上的图像。

除了我正在尝试的方法之外,我对如何解决此问题也持开放态度。这是一些代码

public abstract class D2dControl : System.Windows.Controls.Image {
        private SharpDX.Direct3D11.Device device         ;
        private Texture2D                 rendertarget   ;
        private Dx11ImageSource           d3DSurface     ;
        private rendertarget              d2Drendertarget;
        
        private SharpDX.Direct2D1.Factory d2DFactory     ;

        //background renderer
        private Texture2D bmprendertarget;
        private rendertarget d2dbmprendertarget;
        private SharpDX.Direct2D1.Factory d2DbmpFactory;



        private readonly Stopwatch renderTimer = new Stopwatch();

        protected ResourceCache resCache = new ResourceCache();

        private long lastFrameTime       = 0;
        private long lastRenderTime      = 0;
        private int  frameCount          = 0;
        private int  frameCountHistTotal = 0;
        private Queue<int> frameCountHist = new Queue<int>();
        private object lockObject = new object();

        // - property --------------------------------------------------------------------

        public static bool IsInDesignMode {
            get {
                var prop = DesignerProperties.IsInDesignModeProperty;
                var isDesignMode = (bool)DependencyPropertyDescriptor.FromProperty(prop,typeof(FrameworkElement)).Metadata.DefaultValue;
                return isDesignMode;
            }
        }

        private static readonly DependencyPropertyKey FpsPropertyKey = DependencyProperty.RegisterReadOnly(
            "Fps",typeof(int),typeof(D2dControl),new FrameworkPropertyMetadata(0,FrameworkPropertyMetadataOptions.None)
            );

        public static readonly DependencyProperty FpsProperty = FpsPropertyKey.DependencyProperty;

        public int Fps {
            get { return (int)GetValue( FpsProperty ); }
            protected set { SetValue( FpsPropertyKey,value ); }
        }

        public static DependencyProperty RenderWaitProperty = DependencyProperty.Register(
            "RenderWait",new FrameworkPropertyMetadata( 2,OnRenderWaitChanged )
            );

        public int RenderWait {
            get { return (int)GetValue( RenderWaitProperty ); }
            set { SetValue( RenderWaitProperty,value ); }
        }

        // - public methods --------------------------------------------------------------

        public D2dControl() {
            base.Loaded   += Window_Loaded;
            base.Unloaded += Window_Closing;
            base.Stretch = System.Windows.Media.Stretch.Fill;
        }

        public abstract void Render( rendertarget target );
        public abstract Bitmap RenderBmp(rendertarget target);

        // - event handler ---------------------------------------------------------------

        private void Window_Loaded( object sender,RoutedEventArgs e ) {
            if ( D2dControl.IsInDesignMode ) {
                return;
            }

            StartD3D();
            StartRendering();
        }

        private void Window_Closing( object sender,RoutedEventArgs e ) {
            if ( D2dControl.IsInDesignMode ) {
                return;
            }

            StopRendering();
            EndD3D();
        }
        

        private void OnRendering( object sender,EventArgs e ) {
            if ( !renderTimer.IsRunning ) {
                return;
            }
            if (System.Threading.Monitor.TryEnter(lockObject))
            {
                try
                {
                        PrepareAndCallRender();
                        d3DSurface.Invalidated3dimage(0);
                        lastRenderTime = renderTimer.ElapsedMilliseconds;
                }
                finally
                {
                    System.Threading.Monitor.Exit(lockObject);
                }
            }
        }

        protected override void OnRenderSizeChanged( SizeChangedInfo sizeInfo ) {
            CreateAndBindTargets();
            base.OnRenderSizeChanged( sizeInfo );
        }

        private void OnIsFrontBufferAvailableChanged( object sender,DependencyPropertyChangedEventArgs e ) {
            if ( d3DSurface.IsFrontBufferAvailable ) {
                StartRendering();
            } else {
                StopRendering();
            }
        }

        private static void OnRenderWaitChanged(DependencyObject d,DependencyPropertyChangedEventArgs e) {
            var control = (D2dControl)d;
            control.d3DSurface.RenderWait = (int)e.NewValue;
        }

        // - private methods -------------------------------------------------------------

        private void StartD3D() {
            device = new SharpDX.Direct3D11.Device( DriverType.Hardware,DeviceCreationFlags.BgraSupport );

            d3DSurface = new Dx11ImageSource();
            d3DSurface.IsFrontBufferAvailableChanged += OnIsFrontBufferAvailableChanged;

            CreateAndBindTargets();

            base.source = d3DSurface;
        }

        private void EndD3D() {
            d3DSurface.IsFrontBufferAvailableChanged -= OnIsFrontBufferAvailableChanged;
            base.source = null;

            disposer.Safedispose( ref d2Drendertarget );
            disposer.Safedispose( ref d2DFactory );
            disposer.Safedispose( ref d3DSurface );
            disposer.Safedispose( ref rendertarget );
            disposer.Safedispose( ref device );
        }

        private void CreateAndBindTargets()
        {
            if (d3DSurface == null) {
                return;
            }

            d3DSurface.Setrendertarget( null );

            disposer.Safedispose( ref d2Drendertarget );
            disposer.Safedispose( ref d2DFactory );
            disposer.Safedispose( ref rendertarget );

            var width  = Math.Max((int)ActualWidth,100);
            var height = Math.Max((int)ActualHeight,100);

            var renderDesc = new Texture2DDescription {
                BindFlags = BindFlags.rendertarget | BindFlags.ShaderResource,Format = Format.B8G8R8A8_Unorm,Width = width,Height = height,MipLevels = 1,SampleDescription = new SampleDescription(1,0),Usage = ResourceUsage.Default,OptionFlags = ResourceOptionFlags.Shared,cpuAccessFlags = cpuAccessFlags.None,ArraySize = 1
            };

            rendertarget = new Texture2D( device,renderDesc );
            bmprendertarget = new Texture2D(device,renderDesc);

            var surface = rendertarget.QueryInterface<Surface>();

            d2DFactory = new SharpDX.Direct2D1.Factory();
            d2DbmpFactory = new SharpDX.Direct2D1.Factory();
            var rtp = new rendertargetProperties(new PixelFormat(Format.UnkNown,SharpDX.Direct2D1.AlphaMode.Premultiplied));
            d2Drendertarget = new rendertarget(d2DFactory,surface,rtp);
            d2dbmprendertarget = new rendertarget(d2DFactory,rtp);
            resCache.rendertarget = d2Drendertarget;

            d3DSurface.Setrendertarget( rendertarget );

            device.ImmediateContext.Rasterizer.SetViewport( 0,width,height,0.0f,1.0f );
        }

        private void StartRendering() {
            if ( renderTimer.IsRunning ) {
                return;
            }

            System.Windows.Media.CompositionTarget.Rendering += OnRendering;
            renderTimer.Start();
        }

        private void StopRendering() {
            if ( !renderTimer.IsRunning ) {
                return;
            }

            System.Windows.Media.CompositionTarget.Rendering -= OnRendering;
            renderTimer.Stop();
        }

        private void PrepareAndCallRender() {
            if ( device == null ) {
                return;
            }
            var bitmap = RenderBmp(d2dbmprendertarget);
          
           
            d2Drendertarget.BeginDraw();
            d2Drendertarget.Clear(new SharpDX.Mathematics.Interop.RawColor4(0,1));
            d2Drendertarget.Flush();
            if (bitmap != null)
            {
                d2Drendertarget.DrawBitmap(bitmap,1,BitmapInterpolationMode.Linear);
            }
            
            Render(d2Drendertarget);
            

            d2Drendertarget.EndDraw();

            CalcFps();

            device.ImmediateContext.Flush();
        }

        private void CalcFps() {
            frameCount++;
            if ( renderTimer.ElapsedMilliseconds - lastFrameTime > 1000 ) {
                frameCountHist.Enqueue( frameCount );
                frameCountHistTotal += frameCount;
                if ( frameCountHist.Count > 5 ) {
                    frameCountHistTotal -= frameCountHist.Dequeue();
                }

                Fps = frameCountHistTotal / frameCountHist.Count;

                frameCount = 0;
                lastFrameTime = renderTimer.ElapsedMilliseconds;
            }
        }

这是调用每个渲染循环的特定方法

private void PrepareAndCallRender() {
            if ( device == null ) {
                return;
            }
            RenderBmp(d2dbmprendertarget);
          
            BitmapProperties properties = new BitmapProperties(new SharpDX.Direct2D1.PixelFormat(Format.B8G8R8A8_Unorm,SharpDX.Direct2D1.AlphaMode.Premultiplied),96f,96f);
            var bitmap = new SharpDX.Direct2D1.Bitmap(d2dbmprendertarget,new Size2((int)d2dbmprendertarget.Size.Width,(int)d2dbmprendertarget.Size.Height),properties);
            bitmap.copyFromrendertarget(d2dbmprendertarget);
            d2Drendertarget.BeginDraw();
            d2Drendertarget.Clear(new SharpDX.Mathematics.Interop.RawColor4(0,1));
            d2Drendertarget.Flush();
            d2Drendertarget.DrawBitmap(bitmap,BitmapInterpolationMode.Linear);
            
            Render(d2Drendertarget);
            

            d2Drendertarget.EndDraw();

            CalcFps();

            device.ImmediateContext.Flush();
        }

RenderBmp和Render都转到使用rendertarget进行绘制的方法。 RenderBmp仅在检测到已发生更改时才绘制,而不是在每个循环上绘制。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)