WPF 使用 SharpDX 在 D3DImage 显示

本文介绍了如何使用SharpDX在WPF的D3DImage中进行高性能渲染,解决了不能同时使用WPF控件的问题。通过D3DImage,实现了Direct2D和3D的交互,虽然涉及内存复制,但在某些场景下仍能提高渲染速度。详细步骤包括创建D3D设备、设置指针和实际渲染,最终展示了如何绘制一个矩形并确保其显示。
摘要由CSDN通过智能技术生成

本文告诉大家如何使用 SharpDX 在 D3DImage 显示。在上一篇WPF 使用 SharpDX只是使用窗口,也就是无法使用其它的 WPF 控件。所以这一篇就来告诉大家如何使用 WPF 控件和使用 SharpDX

本文是一个系列,希望大家从第一篇开始看

如果只是使用 SharpDX 使用窗口渲染,就无法使用其它的 WPF 控件,实际使用经常只是使用 SharpDX 加快一些渲染,很多元素都是不需要。

如果拿来 HWND 做渲染,那么 WPF 只是提供一个窗口,这和 WPF 的设计,高效而且灵活不符合,所以本文就来告诉大家如何使用 SharpDx 高性能渲染同时使用 WPF 的元素。

微软为了大家方便使用 Direct2D 就添加了 D3DImage ,虽然这个元素不是很好用。

介绍

先告诉大家什么是 D3DImage ,这是一个可以和 Direct2D、3D 交互的元素,他是一个 ImageSource ,可以放在 Image 控件显示。

使用 D3DImage 会发送一次内存复制,如果在显卡渲染,那么就会先从显卡获得位图,复制到 D3DImage 作为图片显示到 WPF ,也就是同个位图需要现在显卡渲染,然后复制到内存,让 WPF 渲染图片。

一般使用 D3DImage 都不能拿到比原来好的性能。

那么 D3DImage 有什么用?一般渲染是比较慢的,如果需要使用 Dx12 进行加速,而 WPF 无法使用 dx12 那么就需要使用 dx12 渲染。虽然需要使用内存复制,但是经常使用 dx12 渲染的速度比内存复制然后 WPF 显示的速度快。

在 SharpDX 可以使用 D3DImage 进行离屏渲染,本来 WPF 只能有一个渲染线程,但是使用了 SharpDX 就可以有多个渲染线程,这时通过 dx12 加速,一般渲染速度会比不使用 SharpDX 快。

创建控件

首先创建一个 .net framework 4.5 以上的项目。还记得WPF 使用 Direct2D1 画图入门说需要使用 x64 才可以编译,实际上 SharpDX 可以使用 AnyCpu ,而且支持 .net framwork 4.5 和以上的项目。所以使用 SharpDx 就比较简单。

打开主页面,创建一个图片

        <Grid>
            <Image>
                <Image.Source>
                    <interop:D3DImage x:Name="KsyosqStmckfy"></interop:D3DImage>
                </Image.Source>
            </Image>
        </Grid>

从上面可以看到D3DImage的方法,他在 WPF 和其他元素没有不一样的。

因为没有直接从 Direct2D 到 D3D 显示的方法,下面需要告诉大家如何在 D3D11 显示 Direct2D 然后通过相同的格式转 D3D9 最后把缓冲区指针显示。

在这里插入图片描述

D3D 设备

如果需要使用 Direct2D 渲染,需要先创建 D3D11 的设备,因为实际的渲染是通过 3D 渲染。

先引用命名,这样大家直接复制代码就不会不知道使用的是哪个

using D2D = SharpDX.Direct2D1;
using SharpDX.Direct3D;
using SharpDX.Mathematics.Interop;
using DXGI = SharpDX.DXGI;
using D3D11 = SharpDX.Direct3D11;
using D3D9 = SharpDX.Direct3D9;

在使用之前,需要使用 Nuget 安装,安装方法请看WPF 使用 SharpDX

创建设备请看下面

        var device = new D3D11.Device(DriverType.Hardware, D3D11.DeviceCreationFlags.BgraSupport);

因为 D3DImage 需要使用 SetBackBuffer 传入指针,所以通过 D3D11.Texture2D 可以作为指针。

下面来告诉大家如何创建 D3D11.Texture2D ,创建的方法因为需要很多参数,所以代码很多

从 D3D11.Texture2D 的构造函数可以知道,需要传入两个参数 D3D11.Device 和 D3D11.Texture2DDescription ,先创建 D3D11.Texture2DDescription

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

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

参数大家先直接使用,我这里不告诉大家每个参数是怎么计算

现在创建两个参数就可以创建 D3D11.Texture2D ,创建只需要使用下面代码

            var renderTarget = new D3D11.Texture2D(device, renderDesc);

设置指针

创建好了 D3D11.Texture2D 需要让 D3DImage 显示需要使用 SetBackBuffer 设置。

因为传入 D3D11.Texture2D ,但是 D3DImage 是 dx9 的,所以需要转换一下。

首先转换 Format ,因为 D3D11.Texture2D 使用的是 SharpDX.DXGI.Format 需要转换为 D3D9.Format ,请看下面代码

        private static D3D9.Format TranslateFormat(D3D11.Texture2D texture)
        {
   
            switch (texture.Description.Format)
            {
   
                case SharpDX.DXGI.Format.R10G10B10A2_UNorm:
                    return D3D9.Format.A2B10G10R10;
                case SharpDX.DXGI.Format.R16G16B16A16_Float:
                    return D3D9.Format.A16B16G16R16F;
                case SharpDX.DXGI.Format.B8G8R8A8_UNorm:
                    return D3D9.Format.A8R8G8B8;
                default:
                    return D3D9.Format.Unknown;
            }
        }

除了转换还需要拿到指针

        private IntPtr GetSharedHandle(D3D11.Texture2D texture)
        {
   
            using (
  • 10
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值