【DirectX11】【学习笔记(11)】显示文本

之前我们已经学过关于DirectX11的各种简单效果了,包括RSstate,transform,OMdepthandstencil,texture,blendstate(凭记忆写的,不分前后

接下来我们要学习如何在DirectX11里显示字。(毕竟一个没有字的游戏不算是游戏——小明)

前方高能(本节课程可能很冗长,也很无聊)

Font Rendering in Direct3D 11 (Using Direct2D with Direct3D 11)

首先我们要在initializeD3D函数中做一些修改,这个函数将主要用于初始化direct3d 10.1device,direct2d和directdraw对象

顺带我们还会用到direct3d10.1和direct2d渲染一个shared surface到一个方形上,这个方形会覆盖整个屏幕。(听起来很困惑,我们接下来一步一步讲解)

Synchronized Surface Sharing(同步曲面共享)

D3D11,DED10.1和D2D都使用DXGI接口,所以我们可以用DXGI接口创建一个render target,被三个API同时调用

The Adapter

使用同步曲面共享技术,我们必须要在创建设备的时候指定一个容器,我们可以用IDXGIFactory1接口的EnumAdapters1()方法得到可用的容器。

Creating the D3D 10.1 and 11 Devices

接下来创建设备。首先创建D3D11设备和swapchain,我们之前已经讲过,唯一的小改动是我们会把第一个参数设置成我们上一步创建的IDXGIAdapter1 对象中的容器。

第二个参数,驱动器类型,对于D3D11我们指定为D3D_DRIVER_TYPE_UNKNOWN,

D3D10.1我们指定为D3D10_DRIVER_TYPE_HARDWARE

第四个参数,我们要指定D3D11_CREATE_DEVICE_BGRA_SUPPORT,用来使用direct2d,我们可以使用D3D11_CREATE_DEVICE_DEBUG,来得到很多有用的调试信息,他会出现在visual studio的底部(碰巧我用的是VS,其它的编译器我也不是很了解拉)

第五个参数,我们把d3d10.1的指定为D3D10_FEATURE_LEVEL_9_3。其他的不work,感兴趣的同学也可以看看realtimerender这本书,上面有feature level的详解(我记得好像是

D3D 11 Shared Texture

现在我们用D3D11设备创建一个shared texture,用来给D3D10.1渲染。

在创建纹理的时候,有几点要注意:

格式指定为DXGI_FORMAT_B8G8R8A8_UNORM

MiscFlags 指定为D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX ,这样D3D11和D3D10.1都可以使用。当指定比较的时候,它必须支持IDXGIKeyedMutex 接口。我们可以分别调用IDXGIKeyedMutex::AcquireSync and IDXGIKeyedMutex::ReleaseSync  来看哪个设备正在使用texture

D3D 11 Keyed Mutex

要使用keyed Mutex,我们需要创建一个IDXGIKeyedMutex 对象,这个对象有两个方法,IDXGIKeyedMutex::AcquireSync and IDXGIKeyedMutex::ReleaseSync

我们可以从我们创建的贴图上调用IUnknown::QueryInterface方法请求KeyedMutex对象,第一个参数是我们需要的接口IDXGIKeyedMutex,第二个参数是IDXGIKeyedMutex接口对象,这个对象会持有一个到贴图的指针。

我们可以直接用D3D11创建一个贴图的keyed mutex,为了让D3D10.1也能渲染,我们需要创建一个贴图的shared resoutceIDXGIResource ,然后创建一个IDXGISurface1来处理resource,最后创建IDXGISurface1对象 的keyed mutex,因为我们不能直接用D3D10.1来创建到贴图的keyed mutex

Shared Resource from the Texture

因为我i们不能直接创建贴图的keyed mutex,所以我们需要创建一个shared resource对象,从这个对象,我们可以得到这个句柄,用这个句柄我们可以创建一个shared surface 对象,这样D3D10.1就可以获得到贴图的权限。

其实我们就是在为D3D10.1创建一个到贴图的指针,这个指针存在shared resource里。

为了创建这个shared resource,我们需要调用QueryInterface,把第二个参数设成我们想要存储指针的接口对象。

这里我们设成IDXGIResource。

Shared Handle to the Texture

上一段的句柄创建好了,我们就可以从D3D10.1打开shared resource了,然后我们创建IDXGISurface1对象,来存储shared resource的指针,这样,D3D10.1创渲染到这个表面的东西,就会被连接到D3D11贴图上。

为了创建这个句柄,我们可以调用ID3D10Device1的OpenSharedResource方法。第一个参数是句柄,第二个参数是存储指针的resource

D3D 10.1 Keyed Mutex

最终我们可以通过指到D3D11 贴图的shared resource为D3D10.1创建keyed mutex,

调用IDXGISurface1对象下的QueryInterface来创建

Initializing D2D

现在我们已经有了D3D11和D3D10.1的keyedmutex,我们可以初始化D2D了,把它设置成D3D10.1的render target

首先我们创建D2D Factory, or ID2D1Factory object对象,通过D2D1CreateFactory().方法

The D2D Render Target Properties

初始化D2D,我们要做的就是设置它的render target和创建一个画刷。

我们要先填充D2D1_RENDER_TARGET_PROPERTIES结构,来创建它的render target,里面需要的设置的两个成员分别是type:D2D1_RENDER_TARGET_TYPE_HARDWARE(GPU可以处理)第二个是像素格式

我们先使用D2D1::PixelFormat函数来得到render target的像素格式,第一个参数是size和arrangement of color channels,我们设为DXGI_FORMAT_UNKNOWN

第二个参数是是alpha模式,(如果不管的话,覆盖在D3D场景上的贴图就不是透明的了。。。)我们这里设为t D2D1_ALPHA_MODE_PREMULTIPLIED。我们混合贴图的时候,贴图后面的背景是看不到的。D2D写到贴图上的东西就是不透明的,

Creating the D2D Render Target

现在我们就能创建D2D的render target了,这个会画到shared DXGI surface上,也就是D3D11 贴图指针

我们可以通过调用ID2D1Factory的CreateDxgiSurfaceRenderTarget()方法来创建render target。第一个参数是我们要绘制到的IDXGISurface对象,第二个参数是render targets properties

第三个就是返回值ID2D1RenderTarget

The D2D Brush

D2D使用画刷(ID2D1SolidColorBrush对象)功能来绘制屏幕

首先我们需要调用ID2D1RenderTarget接口的CreateSolidColorBrush来创建画刷。

两个参数:1.颜色(D2D color类型),2.创建的画刷(ID2D1SolidColorBrush 对象)

Initializing DirectWrite

为了在屏幕上渲染文字,我们需要使用DirectWrite API。这个API会告诉D2D怎么绘制

为了初始化DW,我们先通过函数DWriteCreateFactory创建DW Factory, IDWriteFactory对象。

DWriteCreateFactory函数

第一个参数是指定DW是否被分享,我们这里指定DWRITE_FACTORY_TYPE_SHARED

第二个参数是我们存入的接口ID IDWriteFactory

最后一个参数是:接口对象  IDWriteFactory对象

DirectWrite Text Format

调用IDWriteFactory接口的函数来创建文本格式

DirectWrite Text Alignment

我们可以指定DW文本位置   通过函数SetTextAlignment() and SetParagraphAlignment

Getting that Rendered Font in D3D 11

恭喜你,最无聊的部分已经结束拉。现在我们要做的就是让文本显示在我们的屏幕左上角

我们可以创建一个我们最开始创建好的D3D11 texture的 shader resource,,然后映射到D3D11的一个方形上。就像我们从一个图片文件里创建shader resource一样

我们可以用过D3D11device的CreateShaderResourceView方法来创建shader resource

第一个参数就是我们要拿数据的resource (the D3D shared texture)

第二个参数是resource view描述 我们设为NULL,表明提取所有数据

第三个参数是返回的shader resource view ,一个ID3D11ShaderResourceView对象

Rendering the Square in Screen Space

当渲染square的时候重新调整WVP(变换矩阵)

Swapping Between the D3D 11 and D3D 10.1 Devices

我们之前创建了两个keyed mutex,这个是为了保证每次只能有一个D3D device来使用texture

当设备请求获得贴图的时候,调用IDXGIKeyedMutex对象的AcquireSync方法。第一个参数是acquire key,第二个是等待时间(再次请求时间)(微秒为单位)这种情况可能在多线程的时候发生。

但是如果我们创建设备的时候,设置了D3D11_CREATE_DEVICE_SINGLETHREADED,(单线程),第二个参数就无所谓了

当我们用完贴图知乎我们就调用IDXGIKeyedMutex接口的ReleaseSync方法来释放。唯一的参数是release key

release key 和acquie key都是是整数,当我们有多个keyed mutex的时候,我们需要按照顺序调用,要不然的话就是谁先请求,谁先拿到texture

AcquireSync的acquire key应该和release key匹配

举个例子:D3D11 device调用AcquireSync,此时key是0 用完之后key 为1

然后D3D10.1请求,它的key如果是1,就可以成功请求。然后用完之后,key又变回0.

看到这里,说明你真的很有毅力了,我们终于把所有的概念和原理说完了,相信你现在还是有点似懂非懂对不对?

接下来我们用一个图把我们刚才所讲的东西简单的串起来,看看我们到底做了什么。

 

 

本节内容就到这里拉,关于字体部分的代码实现,我们在下一节再继续!

游戏开发路途遥远,但我相信只要坚持,总能到达彼岸!

如果我的文章对于你学习DirectX11有点帮助,欢迎评论给出建议,让我们一起学习进步!

                                                                                               ———————— 小明 2018.12.6 20.20

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值