• Directx11教程(66) D3D11屏幕文本输出(1)


         在D3D10中,通过ID3DX10Font接口对象,我们可以方便的在屏幕上输出文字信息,一个DrawText函数就能解决所有问题,但在D3D11中个,这个变得超级麻烦,因为微软移除了Font接口,要在屏幕上输出文本,用户需要做很多事情。

    通常我们可以用以下的方法来输出文本信息:

    (1)用纹理贴图的方法,把所有的字体存储在一张纹理上,再做一个字体查询表,对应纹理的相应位置,可以用2D渲染的方式,把文本染出来,但这种方法不是很灵活,英文还好说,字母字符就那么多,但对于汉字就麻烦了,另外字体大小不能任意缩放。

    (2)通过和GDI/GDI+进行交互,得到字体,把它们存储在纹理中,然后再用2D渲染的方式渲染出来,这种方法可以得到任意大小的文字,而且对英文、中文都适用。

    (3)用direct write,但据说效率不高,http://www.braynzarsoft.net/index.php?p=D3D11FONT 这篇教程中有详细的介绍。

    (4)使用一些文本输出控件,比如CEGUI。

    (5)用FreeType2动态生成字体纹理,然后用2D渲染的方式显示。

    在本篇教程中,我们先看看第一种方法的具体实现,程序的代码是在myTutorialD3D11_61的基础上修改的。

    1、准备一副图片,该图片中包含所有的英文字母、标点以及特殊字符(ascii码32-126之间的所有字符),该图片将被当作纹理。

        该图片背景是纯黑色,RGB为(0,0,0),用该图片产生font.dds纹理资源文件。

    image

    2、建立一个文本索引文件fontdata.txt,该文件索引ascii码32-126之间的所有字符,该文件的格式为:

    [Ascii value of character] [The character] [Left Texture U coordinate] [Right Texture U Coordinate] [Pixel Width of Character]

         第一列为字符的ascii码,第二列为字符,第三列为字符左边的纹理坐标,第四列为字符右边的纹理坐标,第五列为像素宽度。

    32   0.0        0.0         0
    33 ! 0.0        0.000976563 1
    34 " 0.00195313 0.00488281  3
    35 # 0.00585938 0.0136719   8

    125 } 0.573242  0.576172    3
    126 ~ 0.577148  0.583984    7

          通过这几列值,我们就可以把一个字符和纹理中的相应位置对应起来,比如一个字符串"hello”,我们可以动态创建5个四边形,每个四边形有2个三角形组成,三角形的顶点位置为该字符在屏幕上的显示位置,顶点属性中包括纹理坐标,该四边形将通过纹理的方式显示该字符。

    下边大致介绍下增加的代码:

    我们的2D 文本渲染在TextClass中,可以把该类看作一个sprites class, 主要的功能就是渲染文本。

    首先该类用了2个结构来描述文本,第一个是文本句子的结构类型,因为文本都是显示在四边形中,所以该类中包含了顶点缓冲、索引缓冲、顶点数量、顶点颜色等信息。

    struct SentenceType
    {
        ID3D11Buffer *vertexBuffer, *indexBuffer;
        int vertexCount, indexCount, maxLength;
        float red, green, blue;
    };

    struct VertexType
    {
        D3DXVECTOR3 position;
        D3DXVECTOR2 texture;
    };

         通过函数InitializeSentence、UpdateSentence我们生成文本句子数据,RenderSentence函数渲染执行最终的渲染,其中的texture就是包含字体的纹理,该函数调用FontShader类实现最终的渲染。

    bool TextClass::RenderSentence(ID3D11DeviceContext* deviceContext, SentenceType* sentence, D3DXMATRIX worldMatrix,
                                   D3DXMATRIX orthoMatrix,  ID3D11ShaderResourceView* texture)

        类FontClass建立文本句子顶点、索引数据,FontShaderClass类用执行渲染。

        另外,还有2个shader文件:font.vs和font.ps, ps文件中会根据纹理的颜色来设置alpha的值,这样既可以很好的把字体纹理和背景混合起来。

    // 根据选取字符.
    color = shaderTexture.Sample(SampleType, input.tex);

    //如果纹理为黑色,设置透明,这样可以镂空不需要的背景,只显示字体
    if(color.r == 0.0f)
    {
        color.a = 0.0f;
    }
    else
    {
        color.rgb = pixelColor.rgb;
        color.a = 1.0f;
    }

        最终的渲染代码在GraphicsClass类中,主要在开始文本渲染时,要禁用zbuffer,并开启alpha blend功能,渲染完成后,进行相反的操作。

    // 关掉z buffer,以便2d渲染
    m_D3D->TurnZBufferOff();

    // 打开alpha blending
    m_D3D->TurnOnAlphaBlending();

    //得到正交投影矩阵
    m_D3D->GetOrthoMatrix(orthoMatrix);
    // 渲染文本
    result = m_Text->Render(m_D3D->GetDeviceContext(), worldMatrix, orthoMatrix,m_TexManager->createTex(m_D3D->GetDevice(),string("font.dds")));
    if(!result)
        {
        return false;
        }

    // 关闭alpha blending
    m_D3D->TurnOffAlphaBlending();

    // 打开z buffer
    m_D3D->TurnZBufferOn();


    程序执行后的界面如下,我们用白色和黄色显示了几个字tessellation demo by mikewolf

    image

    完整的代码请参考:

    工程文件myTutorialD3D11_63

    代码下载:

    稍后提供

     

  • 相关阅读:
    (转) CS0234: 命名空间“System.Web.Mvc”中不存在类型或命名空间名称“Ajax”(是否缺少程序集引用?)
    服务器修改密码后,发布的网站报“500内部服务器错误”
    关于“/”应用程序中的服务器错误 之解决方案
    (转)根据IP返回对应的位置信息
    (转)C# DateTime格式化大全
    线包字效果
    (转)VS2012网站发布详细步骤
    HTML5 为什么这么火?
    百度地图下拉框搜索建议,并自动添加标注点
    js中检查时间段列表是否有交叉
  • 原文地址:https://www.cnblogs.com/mikewolf2002/p/2830133.html
Copyright © 2020-2023  润新知