DirectX11 绘制字体

1. DirectX中如何实现绘制字体?

由于Direct3D11中微软移除了ID3DXFont这个在Direct3D 9中非常好用的字体接口,这样导致了目前的Direct3D11中竟然没有一个官方的字体解决方案。所以如果要绘制字体,必须要采取手动绘制文本的方式。
我们这里介绍一种图形贴图的方式来绘制字体,即将游戏中要绘制的字体做成一副图片(见下图),然后在游戏里面切开一个个字符图片,按字符串所需字符来绘制。

2. 如何将一幅字体纹理切开每一个字符图片?

其实我们并没有真正的切开一幅字体纹理,而是通过修改UV来选中不同的字符。实际上,我们只需要增加一些代码来将之前 Demo 中的顶点缓存修改为动态缓存,和增加一个函数来将我们的贴图精灵填充到缓存中即可。 动态缓存对于我们需要修改一块缓存中的内容的这种情况来说是很合适的。 不推荐多次创建和销毁静态缓存块,特别是逐帧这样做,你应该使用动态缓存来做这样的任务(上一节已经介绍过如何创建动态缓存)。
也就是说我们就修改动态顶点缓存中的顶点位置(字符的位置)和UV(字符的纹理)就可以了。

3. 如何修改动态顶点缓存的数据?

想修改动态缓存,首先要调用D3D设备的Map函数,来获得子资源的指针(ID3D11Buffer继承自 ID3D11Resource,所以缓存也是一种资源)。
Map函数的原型如下:

HRESULT Map([in]            ID3D11Resource           *pResource,[in]            UINT                     Subresource,[in]            D3D11_MAP                MapType,[in]            UINT                     MapFlags,[out, optional] D3D11_MAPPED_SUBRESOURCE *pMappedResource
);

第一个参数pResource,是映射的源头。
第二个参数Subresource,是子资源的索引(设置为 0,因为我们没有多个子资源)。
第三个参数D3D11_MAP,在本 Demo 中映射类型是 D3D11_MAP_WRITE_DISCARD,它指示 Direct3D 将缓存中的之前的值作为未定义考虑。
第四个参数MapFlags,映射标识。对于其它的映射类型,映射标识可以是 D3D11_MAP_FLAG_DO_NOT_WAIT。但是当使用映射类型D3D11_MAP_WIRTE_DISCARD,则映射标识必须是 0,因为D3D11_MAP_FLAG_DO_NOT_WAIT标识不能用于此种映射类型。
第五个参数pMappedResource,用一个D3D11_MAPPED_SUBRESOURCE结构体类型的指针来保存该映射子资源。(我们通过它来修改动态缓存。为了更新缓存,我们只需要简单的拷贝任何数据给 D3D11_MAPPED_SUBRESOURCE 结构的 pData 成员。 )

4. 绘制字体示例代码

(完整代码太多就不贴了,请自行查看该书附带源码)

bool D3DTextDemo::DrawString( char* message, float startX, float startY )
{// Size in bytes for a single sprite.const int sizeOfSprite = sizeof( VertexPos ) * 6;// Demo's dynamic buffer setup for max of 24 letters.const int maxLetters = 24;int length = strlen( message );// Clamp for strings too long.if( length > maxLetters )length = maxLetters;// Char's width on screen.float charWidth = 32.0f / 800.0f;// Char's height on screen.float charHeight = 32.0f / 640.0f;// Char's texel width.float texelWidth = 32.0f / 864.0f;// verts per-triangle (3) * total triangles (2) = 6.const int verticesPerLetter = 6;D3D11_MAPPED_SUBRESOURCE mapResource;HRESULT d3dResult = d3dContext_->Map( vertexBuffer_, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapResource );if( FAILED( d3dResult ) ){DXTRACE_MSG( "Failed to map resource!" );return false;}// Point to our vertex buffer's internal data.VertexPos *spritePtr = ( VertexPos* )mapResource.pData;const int indexA = static_cast<char>( 'A' );const int indexZ = static_cast<char>( 'Z' );for( int i = 0; i < length; ++i ){float thisStartX = startX + ( charWidth * static_cast<float>( i ) );float thisEndX = thisStartX + charWidth;float thisEndY = startY + charHeight;spritePtr[0].pos = XMFLOAT3( thisEndX,   thisEndY, 1.0f );spritePtr[1].pos = XMFLOAT3( thisEndX,   startY,   1.0f );spritePtr[2].pos = XMFLOAT3( thisStartX, startY,   1.0f );spritePtr[3].pos = XMFLOAT3( thisStartX, startY,   1.0f );spritePtr[4].pos = XMFLOAT3( thisStartX, thisEndY, 1.0f );spritePtr[5].pos = XMFLOAT3( thisEndX,   thisEndY, 1.0f );int texLookup = 0;int letter = static_cast<char>( message[i] );if( letter < indexA || letter > indexZ ){// Grab one index past Z, which is a blank space in the texture.texLookup = ( indexZ - indexA ) + 1;}else{// A = 0, B = 1, Z = 25, etc.texLookup = ( letter - indexA );}float tuStart = 0.0f + ( texelWidth * static_cast<float>( texLookup ) );float tuEnd = tuStart + texelWidth;spritePtr[0].tex0 = XMFLOAT2( tuEnd, 0.0f );spritePtr[1].tex0 = XMFLOAT2( tuEnd, 1.0f );spritePtr[2].tex0 = XMFLOAT2( tuStart, 1.0f );spritePtr[3].tex0 = XMFLOAT2( tuStart, 1.0f );spritePtr[4].tex0 = XMFLOAT2( tuStart, 0.0f );spritePtr[5].tex0 = XMFLOAT2( tuEnd, 0.0f );spritePtr += 6;}d3dContext_->Unmap( vertexBuffer_, 0 );d3dContext_->Draw( 6 * length, 0 );return true;
}

DirectX11 绘制字体相关推荐

  1. C++ Opengl 绘制字体源码

    C++ Opengl 绘制字体源码 项目开发环境 项目功能 项目演示 项目源码传送门 项目开发环境 开发语言:C++和IDE:VS2017,操作系统Windows版本windows SDK8.1,三方 ...

  2. canvas绘制字体时遇到Bookshelf Symbol 7字体bug

    JS使用canvas绘制字体时,如果像以下代码设置字体为Bookshelf Symbol 7时会出现bug,不显示实际字体效果 let font_txt = document.getElementBy ...

  3. GDI+ 使用笔刷绘制字体

    以下将采用十字架来绘制字体.如图: 1.思路,先创建图案笔刷,然后再绘制图形. 代码如下: View Code  1    private void Form1_Paint(object sender ...

  4. 14 Three.js绘制字体模型

    案例查看地址:http://www.wjceo.com/blog/threejs/2018-02-12/16.html 使用three.js绘制字体模型,没有想象当中那么难. 首先你需要实例化 THR ...

  5. 使用FreeType绘制字体

    不带缓存的FreeType使用 1. 初始化库 FT_Init_FreeType( FT_Library  *alibrary ); 2. 通过创建一个新的 face 对象来打开一个字体文件 FT_N ...

  6. android字体图形绘制,android paint api drawText 绘制字体字形

    android paint 的里面有很多属性设置的方法,我们来了解一下: Paint paint = new Paint(); // 设置字体颜色 paint.setColor(Color.RED); ...

  7. Canvas 绘制字体图标库

    1.首先,你要引入一个字体图标库 – iconfont 阿里的字体图标库 将链接复制到浏览器,将获取到的css 代码复制到自己的项目 代码中 其他的不一一赘述,没有用过 iconfont 的 可以看 ...

  8. C/C++ 实现屏幕绘制字体

    新建一个空项目,根据自己的D3D库路径导入D3D 新建一个预编译.h头文件: #pragma once#include <d3d9.h> #include <d3dx9.h> ...

  9. canvas绘制字体

    效果图 html结构 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> &l ...

最新文章

  1. 解决Office互操作错误检索COML类工厂中 CLSID为 {xxx}的组件时失败,原因是出现以下错误: 80070005...
  2. 专访施巍松:边缘计算早期提出者之一
  3. cron表达式详解 Elastic-Job名次解释
  4. linux aspnet服务器,在Linux中安装ASPNET.Core3.0运行时的示例代码
  5. JS(JavaScript) 使用捕获性分组处理文本模板,最终生成完整字符串
  6. 如何让程序员变得没朋友
  7. 收藏:PCWorld:火狐浏览器已宣告死亡
  8. 构造函数必须是public吗_谈谈 constructor 的private和public
  9. linux系统 安装mysql,在linux系统中安装MySQL
  10. Oracle 去掉重复字符串
  11. 问题十七:怎么用ray tracing画多个球?
  12. Spring Boot 注解描述
  13. 宿命java_昆仑奇侠传外传之宿命篇
  14. Word OpenXML常用标签openxml标签
  15. 苹果也被撕下遮羞布,iPhone14后继乏力,靠十三香维持销量
  16. 看得见的数据结构Android版之开篇前言
  17. 推荐一些 iOSer 创办的硬核公众号
  18. NFT引发的“十大行业变局”
  19. 移动硬盘显示请将磁盘插入驱动器的解决方法
  20. 长江大学图书馆校外登陆使用学术资源

热门文章

  1. Android 相册图库功能,按时间排序
  2. 加薪其实也不难:加薪五步曲
  3. 万网绑定二级域名_万网阿里云用.htaccess二级域名绑定子目录
  4. QT视频客户端全屏后视频卡住解决办法
  5. 在nano上进行catkin_make编译时卡住
  6. 大数据开发面试题必备20题
  7. 解锁WiFi密码,我只用了60行代码
  8. [启动“powershell.exe”时出现错误 0x80070002]
  9. 利用VBA编程制作互动效果的PPT
  10. 奥的斯全球总裁朱蒂访华,与中国区总裁罗小莉共同走访嘉兴、杭州、天津、北京等地...