Windows Phone 上的 WriteableBitmap 高速绘图

WritableBitmap high speed drawing on Windows Phone

我正在 Windows Phone 上试验 WritableBitmapEx。我创建了一个简单的例子,一个上下移动的简单盒子。

有一个绘制函数,可以在每一帧重新绘制矩形:

    int y = 0;
    int dy = 15;
    public void draw()
    {
        y += dy;

        if (y > 500 || y < 0)
            dy = -dy;

        writeableBmp.Clear(System.Windows.Media.Colors.Black);
        writeableBmp.FillRectangle(0, y, 100, y + 100, System.Windows.Media.Colors.Green);
    }

和创建可写位图的 Loaded 事件,并在每个帧上调用 draw()

    WriteableBitmap writeableBmp;
    private async void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
    {
        writeableBmp = BitmapFactory.New((int)ContentPanel.ActualWidth, (int)ContentPanel.ActualHeight);
        image.Source = writeableBmp;
        writeableBmp.GetBitmapContext();
        CompositionTarget.Rendering += CompositionTarget_Rendering;
    }

    private void CompositionTarget_Rendering(object sender, EventArgs e)
    {
        draw();
    }

但这最多给了我 ~30FPS,所以动画不流畅。

知道xaml中有一些更好的创建此类动画的方法(例如创建一个矩形对象并使用xaml动画制作动画) ,但是有一个游戏(用另一种语言)以这种方式重新绘制每一帧,我的最终目标是将该代码移植到 Windows Phone。因此,找到一种足够快的重绘方法可以使移植真正更容易。

那么,有没有办法提高它的性能?还是有更好的方法手动绘制每一帧,但足够快(60fps)?

试用 Microsoft Win2D。您可以在此处使用 NuGet 或他们的 GitHub 获取它:Microsoft Win2D GitHub。它基本上是 Direct2D 的包装器,使用起来非常简单。

特征(复制自:https://github.com/Microsoft/Win2D/wiki/Features

Easy-to-use Windows Runtime API

•Available from .NET and C++

•Supports Windows 10, Windows 8.1, and Windows Phone 8.1

Immediate mode 2D graphics rendering with GPU acceleration

•Implemented as a layer on top of Direct2D, DirectImage, and DirectWrite

•Interop to and from underlying types, so you can mix & match Win2D with native D2D

Bitmap graphics

•Load, save, and draw bitmap images

•Render to texture

•Use bitmaps as opacity masks

•Sprite batch API for efficiently drawing large numbers of bitmaps

•Use block compressed bitmap formats to save memory

•Load, save, and draw virtual bitmaps, which can be larger than the maximum GPU texture size and are automatically split into tiles

Vector graphics

•Draw primitive shapes (lines, rectangles, circles, etc.) or arbitrarily complex geometry

•Fill shapes using solid colors, image brushes, or linear and radial gradients

•Draw lines of any width with flexible stroke styles (dotted, dashed, etc.)

•High quality antialiasing

•Rich geometry manipulation (union, intersect, compute point on path, tessellate, etc.)

•Clip drawing to arbitrary geometric regions

•Capture drawing operations in command lists for later replay

•Rasterize ink strokes (from a stylus)

Powerful image processing effects

•Blurs

•Blends

•Color adjustments (brightness, contrast, exposure, highlights & shadows, etc.)

•Filters (convolve, edge detection, emboss, sharpen)

•Lighting

•Custom pixel shaders

•And many more...

Text

•Fully internationalized Unicode text rendering

•Text layouts can be drawn, measured, or hit-tested against

•Convert text outlines to geometry

•Enumerate fonts and query their metrics

•Draw or manipulate individual glyph runs to create custom text layouts

UI integration

•XAML CanvasControl make it easy to get up and running

•Can also create advanced things like owner-draw XAML controls

•XAML CanvasAnimatedControl provides Update/Draw game loop programming model

•XAML CanvasVirtualControl for drawing to very large virtualized surfaces

•Draw onto Windows.UI.Composition drawing surfaces and swapchains

•Can also draw directly to a CoreWindow

•Printing

感谢 Chubosaurus Software 建议使用 Microsoft Win2D。

我将详细解释一下我在我的案例中所做的事情。

Win2D中有一个叫CanvasAnimatedControl的控件,就是专门为此设计的。

从NuGet获取包并添加到页面后,可以使用DrawUpdate两个事件。

Update 用于逻辑,Draw 用于渲染框架。

所以,这是问题中描述的移动矩形的代码:

    private void Page_Loaded(object sender, RoutedEventArgs e)
    {
        cvs.Update += Cvs_Update;
        cvs.Draw += Cvs_Draw;
    }

    int y = 0;
    int dy = 15;
    private void Cvs_Draw(Microsoft.Graphics.Canvas.UI.Xaml.ICanvasAnimatedControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedDrawEventArgs args)
    {
        args.DrawingSession.Clear(Windows.UI.Colors.Blue);
        args.DrawingSession.FillRectangle(new Rect(0, y, 100, 100), Windows.UI.Colors.Green);
    }

    private void Cvs_Update(Microsoft.Graphics.Canvas.UI.Xaml.ICanvasAnimatedControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedUpdateEventArgs args)
    {
        y += dy;

        if (y > 500 || y < 0)
            dy = -dy;
    }

此代码在我的 phone 上运行良好 (~60fps)。

唯一的缺点是,Win2D 支持 Windows Phone 8.1 及更高版本。因此,通过使用此库,您将失去 Windows Phone 8 兼容性。