WPF 使用 SharpDX

本文告诉大家如何在 WPF 使用 SharpDX ,只是入门。

本文是一个系列

先介绍一下 SharpDx ,一个底层封装的 DirectX 库,支持 AnyCpu ,支持 Direct3D9, Direct3D11, Direct3D12,Direct2D1。支持 win32 程序和商店程序。

环境

需要 .NET 4.5 和以上的环境才可以使用。

安装

首先安装 SharpDX 的库,需要安装下面几个库

创建工厂

使用 SharpDX 和 DirectX 一样,开始都需要创建工厂,然后创建RenderTarget,之后才可以显示基础图形。

先引用命名

using D2D = SharpDX.Direct2D1;
using WIC = SharpDX.WIC;
using DW = SharpDX.DirectWrite;
using DXGI = SharpDX.DXGI;

需要在 Loaded 之后添加代码

                var factory = new D2D.Factory();

创建 RenderTarget

创建 RenderTarget 可以尝试 WindowRenderTarget ,因为是入门博客,我不告诉大家如何使用其他几个 RenderTarget ,如果想知道,请自己多去看博客。

创建 WindowRenderTarget 需要参数 RenderTargetProperties ,HwndRenderTargetProperties。所以需要先创建这两个。

创建 RenderTargetProperties 需要参数 PixelFormat ,请看下面

                var pixelFormat = new D2D.PixelFormat(DXGI.Format.B8G8R8A8_UNorm, D2D.AlphaMode.Straight);

                var renderTargetProperties = new D2D.RenderTargetProperties(D2D.RenderTargetType.Default, pixelFormat,
                    96, 96, D2D.RenderTargetUsage.None, D2D.FeatureLevel.Level_DEFAULT);

RenderTargetProperties 需要的参数是 RenderTargetType ,PixelFormat,dpiX,dpiY,RenderTargetUsage,FeatureLevel,参数大家看命名就知道是做什么的,在这里就不告诉大家。

创建 HwndRenderTargetProperties 请看下面代码

                var hwndRenderTargetProperties = new D2D.HwndRenderTargetProperties();
                hwndRenderTargetProperties.Hwnd = new WindowInteropHelper(this).Handle;

现在尝试创建 RenderTarget 请看代码

               var renderTarget = new D2D.WindowRenderTarget(factory, renderTargetProperties, hwndRenderTargetProperties);

因为需要拿到 RenderTarget 进行画基础图形,一般把 RenderTarget 放在字段。

        public MainWindow()
        {
            InitializeComponent();

            Loaded += (s, e) =>
            {
                var factory = new D2D.Factory();

                var pixelFormat = new D2D.PixelFormat(DXGI.Format.B8G8R8A8_UNorm, D2D.AlphaMode.Straight);

                var hwndRenderTargetProperties = new D2D.HwndRenderTargetProperties();
                hwndRenderTargetProperties.Hwnd = new WindowInteropHelper(this).Handle;
                hwndRenderTargetProperties.Hwnd = new WindowInteropHelper(this).Handle;
                hwndRenderTargetProperties.PixelSize = new Size2((int)ActualWidth, (int)ActualHeight);

                var renderTargetProperties = new D2D.RenderTargetProperties(D2D.RenderTargetType.Default, pixelFormat,
                    96, 96, D2D.RenderTargetUsage.None, D2D.FeatureLevel.Level_DEFAULT);

                _renderTarget = new D2D.WindowRenderTarget(factory, renderTargetProperties, hwndRenderTargetProperties);
            };
        }

        private D2D.RenderTarget _renderTarget;

这里的 PixelFormat 使用 B8G8R8A8_UNorm 的意思是每个元素包含4个8位无符号分量,分量的取值范围在[0,1]区间内的浮点数,因为不是任何类型的数据都能存储到纹理中的,纹理只支持特定格式的数据存储。这里的 BGRA 的意思分别是 蓝色(Blue)、绿色(Green)、红色(Red)和 alpha(透明度),其他可以选的格式

  • DXGI_FORMAT_R32G32B32_FLOAT:每个元素包含3个32位浮点分量。
  • DXGI_FORMAT_R16G16B16A16_UNORM:每个元素包含4个16位分量,分量的取值范围在[0,1]区间内。
  • DXGI_FORMAT_R32G32_UINT:每个元素包含两个32位无符号整数分量。
  • DXGI_FORMAT_R8G8B8A8_UNORM:每个元素包含4个8位无符号分量,分量的取值范围在[0,1]区间内的浮点数。
  • DXGI_FORMAT_R8G8B8A8_SNORM:每个元素包含4个8位有符号分量,分量的取值范围在[−1,1] 区间内的浮点数。
  • DXGI_FORMAT_R8G8B8A8_SINT:每个元素包含4个8位有符号整数分量,分量的取值范围在[−128, 127] 区间内的整数。
  • DXGI_FORMAT_R8G8B8A8_UINT:每个元素包含4个8位无符号整数分量,分量的取值范围在[0, 255]区间内的整数

更多概念请看DirectX11 Direct3D基本概念 - CSDN博客

画圈

现在就和 WPF 使用 Direct2D1 画图入门 差不多方法来画圈,如何可以画出来,那么就是成功使用 SharpDX 。不要问我为什么用画圈来判断是否可以使用 SharpDX,因为在所有基础的 draw 只有椭圆最耗性能。

还是使用 CompositionTarget 来知道什么时候刷新,在函数添加下面代码

            CompositionTarget.Rendering += CompositionTarget_Rendering;

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

因为画椭圆需要三个参数,第一个是 D2D.Ellipse ,第二个是 Brush ,第三个是线条宽度。

因为 Brush 需要使用刚才的工厂创建,如果不使用工厂创建会异常

先创建 SolidColorBrush 然后创建 D2D.Ellipse

            var ellipse = new D2D.Ellipse(new RawVector2(100,100),10,10 );

            var brush = new D2D.SolidColorBrush(_renderTarget, new RawColor4(1, 0, 0, 1));

Ellipse 的三个参数是圆心和两个半径,上面是画出半径是 10 的圆。

RawColor4 就是 rgba ,颜色是从 0 到 1 ,对应 WPF 的 RGB 从 0 到 255 ,所以需要转换。

准备好几个参数,可以尝试画出来,在画之前需要使用 BeginDraw 。为什么需要调用这个函数,因为实际上调用 Draw 是不会立刻画出来,而是创建绘制命令,如果渲染是 CPU 渲染,那么就会根据命令让 CPU 在内存渲染。如果渲染 GPU 渲染,就会把命令发到 GPU ,让他渲染。

        private void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            var ellipse = new D2D.Ellipse(new RawVector2(100, 100), 10, 10);

            var brush = new D2D.SolidColorBrush(_renderTarget, new RawColor4(1, 0, 0, 1));
            _renderTarget.BeginDraw();

            _renderTarget.DrawEllipse(ellipse, brush, 1);

            _renderTarget.EndDraw();
        }

重新告诉大家如何画出。首先拿到窗口,在 WPF 能创建的 WindowRenderTarget 最简单是拿到窗口。因为通过几个属性设置如何渲染,在哪渲染,所以还需要多使用几个属性才可以创建 D2D.WindowRenderTarget 。因为需要一个时机对 WindowRenderTarget 画出,所以我就使用 CompositionTarget 对他进行画出。


本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • win10 uwp 活动磁贴

    本文翻译:https://mobileprogrammerblog.wordpress.com/2015/12/23/live-tiles-and-notifi...

    林德熙
  • WPF 使用 SharpDx 异步渲染 使用方法绑定渲染为什么空白等待画完异步渲染多线程渲染

    本文告诉大家如何通过 SharpDx 进行异步渲染,但是因为在 WPF 是需要使用 D3DImage 画出来,所以渲染只是画出图片,最后的显示还是需要 WPF ...

    林德熙
  • win10 uwp 气泡 WPF 气泡

    假设尖头宽度 10 高度 5 ,那么可以看到第一个点是 (0,5) 第二个点是 (5,0) 第三个点是 (10,5)

    林德熙
  • win10 uwp 活动磁贴

    本文翻译:https://mobileprogrammerblog.wordpress.com/2015/12/23/live-tiles-and-notifi...

    林德熙
  • 巧用Openlayers4的Style

    非常细化Openlayers4中的StyleFunction,因为它可以让我非常方便的实现各种效果,本文带你一起一探究竟。

    lzugis
  • storm 1.0版本滑动窗口的实现及原理

    滑动窗口在监控和统计应用的场景比较广泛,比如每隔一段时间(10s)统计最近30s的请求量或者异常次数,根据请求或者异常次数采取相应措施。在storm1.0版本之...

    intsmaze-刘洋
  • (57) 二进制文件和字节流 / 计算机程序的思维逻辑

    查看历史文章,请点击上方链接关注公众号。 本节我们介绍在Java中如何以二进制字节的方式来处理文件,上节我们提到Java中有流的概念,以二进制方式读写的主要流有...

    swiftma
  • IdentityServer4 手动验签及日志记录

    IdentityServer4的基础知识和使用方式网上有很多特别优秀的文章,如果有对其不了解的推荐阅读一下下面的两篇文章

    蓝夏
  • 最好的.NET开源免费ZIP库DotNetZip(.NET组件介绍之三)

       在项目开发中,除了对数据的展示更多的就是对文件的相关操作,例如文件的创建和删除,以及文件的压缩和解压。文件压缩的好处有很多,主要就是在文件传输的方面,文件...

    彭泽0902
  • AI再乱围棋圈:“食言之战”柯洁落败;首例素人作弊引风波

    去年12月底,曾经放言不再与AI进行正式比赛的柯洁,公开宣布“食言”。现在,这场柯洁的“实验之战”胜负已分。

    量子位

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动