dotnet C# 通过 Vortice 使用 Direct2D 特效入门

这篇具有很好参考价值的文章主要介绍了dotnet C# 通过 Vortice 使用 Direct2D 特效入门。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文将告诉大家如何通过 Vortice 使用 D2D 的特效

本文属于 DirectX 系列博客,更多 DirectX 和 D2D 以及 Vortice 库的博客,请参阅我的 博客导航

上一篇: DirectX 使用 Vortice 从零开始控制台创建 Direct2D1 窗口修改颜色

在上一篇博客里面,咱创建了一个 Win32 空窗口,接着给他挂上了 DirectX 交换链。使用以下代码从交换链里面拿到了 DXGI 平面,拿到的的 DXGI 平面即可被绘制 2D 内容在上面,从而将内容绘制输出到窗口上

        DXGI.IDXGISwapChain1 swapChain = ... // 忽略交换链之前的代码

        D3D11.ID3D11Texture2D backBufferTexture = swapChain.GetBuffer<D3D11.ID3D11Texture2D>(0);

        // 获取到 dxgi 的平面,这个屏幕就约等于窗口渲染内容
        DXGI.IDXGISurface dxgiSurface = backBufferTexture.QueryInterface<DXGI.IDXGISurface>();

接下来咱将创建 D2D 设备,再通过 D2D 设备,从而拿到 ID2D1DeviceContext 对象,设置 DXGI 平面作为 ID2D1DeviceContext 输出,如此即可使用继承自 ID2D1RenderTarget 的 ID2D1DeviceContext 进行绘制界面。此步骤更详细的内容,请参阅 dotnet DirectX 通过 Vortice 控制台使用 ID2D1DeviceContext 绘制画面

        DXGI.IDXGIDevice dxgiDevice = d3D11Device.QueryInterface<DXGI.IDXGIDevice>();
        ID2D1Device d2dDevice = d2DFactory.CreateDevice(dxgiDevice);
        ID2D1DeviceContext d2dDeviceContext = d2dDevice.CreateDeviceContext();

        // 设置 DXGI 平面作为 ID2D1DeviceContext 输出
        ID2D1Bitmap1 d2dBitmap = d2dDeviceContext.CreateBitmapFromDxgiSurface(dxgiSurface);
        d2dDeviceContext.Target = d2dBitmap;

使用 Direct2D 特效之前,需要先了解一些概念。在 Direct2D 里面,可使用 ID2D1Effect 特效,特效的常用方法就是先使用 SetInput 方法将某个 ID2D1Bitmap 设置为输入源,再通过 SetValue 设置一些参数。最后将特效放入到 ID2D1DeviceContext 的 DrawImage 方法绘制出来

在 Direct2D 里面有许多内建特效,作为入门的博客,咱随便选一个简单的 GaussianBlur 特效作为例子。先通过 ID2D1DeviceContext 创建出特效,代码如下

                var gaussianBlurEffect = d2dDeviceContext.CreateEffect(EffectGuids.GaussianBlur);
                using ID2D1Effect d2dEffect = new ID2D1Effect(gaussianBlurEffect);

创建出来的特效现在是缺少输入源的,接下来咱随便写一点代码创建一个 ID2D1Bitmap 作为输入源。为了方便编写例子,我这里采用的是创建放在内存里的 IWICBitmap 作为画布,通过自己绘制的内容作为 ID2D1Bitmap 输出,方法如下

        ID2D1Bitmap CreateBitmap()
        {
            using var wicImagingFactory = new IWICImagingFactory();
            using IWICBitmap wicBitmap =
                wicImagingFactory.CreateBitmap(1000, 1000, Win32.Graphics.Imaging.Apis.GUID_WICPixelFormat32bppPBGRA);
            var renderTargetProperties = new D2D.RenderTargetProperties(Vortice.DCommon.PixelFormat.Premultiplied);
            using D2D.ID2D1RenderTarget wicBitmapRenderTarget =
                d2DFactory.CreateWicBitmapRenderTarget(wicBitmap, renderTargetProperties);
            wicBitmapRenderTarget.BeginDraw();
            using var brush = wicBitmapRenderTarget.CreateSolidColorBrush(color);
            wicBitmapRenderTarget.FillEllipse(new Ellipse(new System.Numerics.Vector2(200, 200), 100, 100), brush);
            wicBitmapRenderTarget.EndDraw();

            ID2D1Bitmap1 intputBitmap = renderTarget.CreateBitmapFromWicBitmap(wicBitmap);
            return intputBitmap;
        }

以上代码不是本文的重点,大家也可以采用加载本地图片等方式获取到 ID2D1Bitmap 对象。如何加载本机图片,请参阅 WPF 对接 Vortice 在 Direct2D 绘制从 WIC 加载的图片

获取到 ID2D1Bitmap 对象,即可调用 SetInput 方法设置输入源,代码如下

                using ID2D1Bitmap intputBitmap = CreateBitmap();

                d2dEffect.SetInput(0, intputBitmap, new RawBool(true));

接着使用 SetValue 方法设置特效的一些参数,特效的参数都是灵活的。此 SetValue 方法的第一个参数表示的是将要设置特效的哪个参数,第二个参数才是特效参数的值,例如以下代码,设置模糊度

                const int D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION = 0;
                d2dEffect.SetValue(D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION, 2.5f);

完成特效的设置之后,即可调用 DrawImage 方法将特效结果绘制出来,代码如下

                renderTarget.DrawImage(d2dEffect);

以上就是特效的入门玩法,可以通过高性能的 Direct2D 特效,绘制出绚丽的界面

下面是特效使用部分的代码

        // 创建 D2D 设备,通过设置 ID2D1DeviceContext 的 Target 输出为 dxgiSurface 从而让 ID2D1DeviceContext 渲染内容渲染到窗口上
        // 如 https://learn.microsoft.com/en-us/windows/win32/direct2d/images/devicecontextdiagram.png 图
        // 获取 DXGI 设备,用来创建 D2D 设备
        DXGI.IDXGIDevice dxgiDevice = d3D11Device.QueryInterface<DXGI.IDXGIDevice>();
        ID2D1Device d2dDevice = d2DFactory.CreateDevice(dxgiDevice);
        ID2D1DeviceContext d2dDeviceContext = d2dDevice.CreateDeviceContext();

        ID2D1Bitmap1 d2dBitmap = d2dDeviceContext.CreateBitmapFromDxgiSurface(dxgiSurface);
        d2dDeviceContext.Target = d2dBitmap;

        var renderTarget = d2dDeviceContext;

        var stopwatch = Stopwatch.StartNew();
        var count = 0;

        // 随意创建颜色
        var color = new Color4((byte) Random.Shared.Next(255), (byte) Random.Shared.Next(255),
            (byte) Random.Shared.Next(255));

        Task.Factory.StartNew(() =>
        {
            while (true)
            {
                // 开始绘制逻辑
                renderTarget.BeginDraw();

                // 清空画布
                renderTarget.Clear(new Color4(0xFF,0xFF,0xFF));

                // 随便创建一张图片
                using var inputBitmap = CreateBitmap();

                var gaussianBlurEffect = d2dDeviceContext.CreateEffect(EffectGuids.GaussianBlur);
                using ID2D1Effect d2dEffect = new ID2D1Effect(gaussianBlurEffect);

                d2dEffect.SetInput(0, inputBitmap, new RawBool(true));
                const int D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION = 0;
                d2dEffect.SetValue(D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION, count / 60f * 3f);

                renderTarget.DrawImage(d2dEffect);

                renderTarget.EndDraw();

                swapChain.Present(1, DXGI.PresentFlags.None);
                // 等待刷新
                d3D11DeviceContext.Flush();

                // 统计刷新率
                count++;
                if (stopwatch.Elapsed >= TimeSpan.FromSeconds(1))
                {
                    Console.WriteLine($"FPS: {count / stopwatch.Elapsed.TotalSeconds}");
                    stopwatch.Restart();
                    count = 0;
                }
            }
        }, TaskCreationOptions.LongRunning);

        ID2D1Bitmap CreateBitmap()
        {
            using var wicImagingFactory = new IWICImagingFactory();
            using IWICBitmap wicBitmap =
                wicImagingFactory.CreateBitmap(1000, 1000, Win32.Graphics.Imaging.Apis.GUID_WICPixelFormat32bppPBGRA);
            var renderTargetProperties = new D2D.RenderTargetProperties(Vortice.DCommon.PixelFormat.Premultiplied);
            using D2D.ID2D1RenderTarget wicBitmapRenderTarget =
                d2DFactory.CreateWicBitmapRenderTarget(wicBitmap, renderTargetProperties);
            wicBitmapRenderTarget.BeginDraw();
            using var brush = wicBitmapRenderTarget.CreateSolidColorBrush(color);
            wicBitmapRenderTarget.FillEllipse(new Ellipse(new System.Numerics.Vector2(200, 200), 100, 100), brush);
            wicBitmapRenderTarget.EndDraw();

            ID2D1Bitmap1 inputBitmap = renderTarget.CreateBitmapFromWicBitmap(wicBitmap);
            return inputBitmap;
        }

以上代码将可以动态绘制一个模糊度不断变化的圆,代码省略和没有写的部分,我放在了 github 和 gitee 上,可以通过以下方式获取整个项目的代码

先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 615c235ce34b8c38abe1e99e65a5e34ddc9addb0

以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin 615c235ce34b8c38abe1e99e65a5e34ddc9addb0

获取代码之后,进入 VorticeD2DEffect1 文件夹

有伙伴好奇为什么我最近写的是通过 Vortice 调用 DirectX 的博客,而不是通过 SharpDx 或 Silk.NET 调用 DirectX 的博客。这不是我收了 Vortice 的钱或者是和 Vortice 有什么 py 交易哈。其原因是 SharpDx 不维护了,作为 SharpDx 的接任者 Vortice 的行为和 API 都会靠近 SharpDx 许多,我编写起来比较顺手。而 Silk.NET 是对 DirectX 的底层封装,由于是直接底层封装,导致使用 Silk.NET 比较繁琐。尽管使用 Silk.NET 的性能从理论分析上能够比 Vortice 和 SharpDx 更好,但从定量上说,其实好不了多少。我所遇到的几乎所有性能问题,基本都卡在渲染上,而不是调用上,调用上的损耗基本可以忽略。那 Silk.NET 是不是就无用武之地?其实不然,在一些情况下,机器的性能不够业务的需求情况下,能省多少就应该省多少。而且在熟悉整个过程之后,即使将 Vortice 换成 Silk.NET 也只不过是一个体力活而已,将各个 API 进行替换即可。而且有趣的是,可以混合着 Vortice 和 Silk.NET 一起用,只有某些模块才使用 Silk.NET 编写

我创建了专门聊 Vortice 的 QQ 群: 622808968 欢迎加入交流技术文章来源地址https://www.toymoban.com/news/detail-583115.html

到了这里,关于dotnet C# 通过 Vortice 使用 Direct2D 特效入门的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 在direct3D中,透明度处理和D2D1_ALPHA_MODE_PREMULTIPLIED含义?

    D2D1_ALPHA_MODE_PREMULTIPLIED 是 Direct2D 中定义的一种 Alpha 模式,用于描述像素颜色值和其 Alpha 通道(透明度)之间的关系。 在非预乘 Alpha (Straight or Unpremultiplied Alpha) 图像中,每个颜色分量(红、绿、蓝)是独立于 Alpha 值的。而在预乘 Alpha 图像中,每个颜色分量已经被其对应的

    2024年01月25日
    浏览(35)
  • 【linux下安装运行C#程序环境】linux下安装运行C#(dotnet)程序环境

    若yum的数据源不是国内的,速度原因,建议换yum数据源:yum换源操作 先查看系统版本号: 结果: 先添加配置对应的centos版本的C#数据源(此处为7) 可点击链接找到自己需要的系统及版本 https://packages.microsoft.com/config/ 查找需要安装的dotnet-sdk版本 结果: yum安装C#依赖包(此处

    2024年02月14日
    浏览(33)
  • c#,dotnet, DataMatrix 类型二维码深度识别,OCR,(基于 Halcon)

    代码中部分调用的 c++ 函数参数,具体说明自行研究~(我也是参考的其他资源,还没研究透彻) 例如:HOperatorSet.GenRectangle2() , 2000, 2000, 0, 2000, 2000 这些数字应该是选取的图片解析范围、尺寸(长、宽),2000 更改成 100 后可能只会识别到部分二维码。 效果图: 链接:https:

    2024年02月20日
    浏览(31)
  • Baumer工业相机堡盟工业相机如何通过BGAPISDK使用HDR功能(C#)

    Baumer工业相机堡盟相机是一种高性能、高质量的工业相机,可用于各种应用场景,如物体检测、计数和识别、运动分析和图像处理。 Baumer的万兆网相机拥有出色的图像处理性能,可以实时传输高分辨率图像。此外,该相机还具有快速数据传输、低功耗、易于集成以及高度可扩

    2024年02月09日
    浏览(34)
  • DotNet VOL.Core框架学习使用笔记(持续更新)

     2023-6-8 下拉框绑定数据源的增加设置在 系统设置-下拉框绑定设置里面,重点是根据需要用sql查出数据源。 2023-6-12 从控制器外层的sys_regionController部分类调试来看 _isys_RegionRepository 注入了总是提示为空。 后来了解到了框架约束好像所有的业务都要写到partial文件夹的部分类里

    2024年02月10日
    浏览(28)
  • Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用短曝光功能(C#)

    Baumer工业相机堡盟相机是一种高性能、高质量的工业相机,可用于各种应用场景,如物体检测、计数和识别、运动分析和图像处理。 Baumer的万兆网相机拥有出色的图像处理性能,可以实时传输高分辨率图像。此外,该相机还具有快速数据传输、低功耗、易于集成以及高度可扩

    2024年01月18日
    浏览(35)
  • rabbitmq使用springboot实现direct模式

    类型:direct 特点:Direct模式是fanout模式上的一种叠加,增加了路由RoutingKey的模式。 Ⅰ 生产者  1、引入相应的pom文件 pom.xml 2、配置文件 application.properties 3、写一个生产者   DirectOrderService.java (从代码中可以看到,direct_order_exchange交换机分别给绑定的路由key为sms和email的消息

    2024年02月15日
    浏览(21)
  • Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用相机日志跟踪功能(C#)

    Baumer工业相机堡盟相机是一种高性能、高质量的工业相机,可用于各种应用场景,如物体检测、计数和识别、运动分析和图像处理。 Baumer的万兆网相机拥有出色的图像处理性能,可以实时传输高分辨率图像。此外,该相机还具有快速数据传输、低功耗、易于集成以及高度可扩

    2024年01月18日
    浏览(32)
  • dotnet 推荐一个使用 Json 直接路由通讯的 IPC 库

    本文将和大家推荐一个我所在团队开源的本机多进程通讯 IPC 库,此 IPC 支持使用 JSON 格式进行直接路由通讯,具有使用方便,稳定性高,性能好的优点 这是我所在的团队在 GitHub 上使用最友好的 MIT 协议完全开源的项目:https://github.com/dotnet-campus/dotnetCampus.Ipc 这个开源项目开

    2024年02月08日
    浏览(25)
  • dotnet 使用 MSTestRunner 将单元测试制作为独立可执行文件

    以往的单元测试都是不能单独作为一个独立的可执行文件跑的,需要在 VisualStudio 或 VSTest 或 dotnet test 里面运行。这就限制了运行单元测试的环境了,有时候开发者可能期望在无 SDK 或开发环境下执行单元测试,这时就可以用到本文介绍的 MSTestRunner 功能,将单元测试制作为独

    2024年04月26日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包