如何使用stb_truetype在DirectX9中渲染文本?

10
如何使用stb_truetype库在C/C++中使用D3D9渲染文本?我在各种论坛/网站和这个库的文档中寻找d3d9的示例,但没有找到任何示例。

2
所有形如“我该如何使用Direct3D 9来做X?”的问题的通用答案是:“不要使用Direct3D 9,而应该使用Direct3D 11。”它已经过时了,基本上没有理由再使用它。请参阅MSDN这篇博客文章 - Chuck Walbourn
1个回答

5

一个实现此目的的方法是创建一个D3D9纹理,然后将渲染的文本位图加载到其中。接着你可以像使用其他纹理一样使用生成的纹理。

#define STB_TRUETYPE_IMPLEMENTATION 
#include "stb_truetype.h"
IDirect3DTexture9 *LoadTextureFromText(const char *text)
{
    IDirect3DTexture9 *d3dTexture = 0;

    /* load font file */
    long size;
    unsigned char* fontBuffer;

    FILE* fontFile = fopen("C:\\path\\to\\font.ttf", "rb");
    fseek(fontFile, 0, SEEK_END);
    size = ftell(fontFile); /* how long is the file ? */
    fseek(fontFile, 0, SEEK_SET); /* reset */

    fontBuffer = (unsigned char*)malloc(size);

    fread(fontBuffer, size, 1, fontFile);
    fclose(fontFile);

    /* prepare font */
    stbtt_fontinfo info;
    if (!stbtt_InitFont(&info, fontBuffer, 0))
    {
        printf("failed\n");
    }

    int b_w = 512; /* bitmap width */
    int b_h = 128; /* bitmap height */
    int l_h = 64; /* line height */

    /* create a bitmap for the phrase */
    unsigned char* bitmap = (unsigned char*)calloc(b_w * b_h, sizeof(unsigned char));

    /* calculate font scaling */
    float scale = stbtt_ScaleForPixelHeight(&info, l_h);

    int x = 0;

    int ascent, descent, lineGap;
    stbtt_GetFontVMetrics(&info, &ascent, &descent, &lineGap);

    ascent *= scale;
    descent *= scale;

    int i;
    for (i = 0; i < strlen(text); ++i)
    {
        /* get bounding box for character (may be offset to account for chars that dip above or below the line */
        int c_x1, c_y1, c_x2, c_y2;
        stbtt_GetCodepointBitmapBox(&info, text[i], scale, scale, &c_x1, &c_y1, &c_x2, &c_y2);

        /* compute y (different characters have different heights */
        int y = ascent + c_y1;

        /* render character (stride and offset is important here) */
        int byteOffset = x + (y  * b_w);
        stbtt_MakeCodepointBitmap(&info, bitmap + byteOffset, c_x2 - c_x1, c_y2 - c_y1, b_w, scale, scale, text[i]);

        /* how wide is this character */
        int ax;
        stbtt_GetCodepointHMetrics(&info, text[i], &ax, 0);
        x += ax * scale;

        /* add kerning */
        int kern;
        kern = stbtt_GetCodepointKernAdvance(&info, text[i], text[i + 1]);
        x += kern * scale;
    }

    //Create a D3D9 texture and load the generated image. The text bitmap is 1 channel.
    D3DXCreateTexture(direct3DDevice, b_w, b_h, 1, D3DUSAGE_DYNAMIC, D3DFMT_L8, D3DPOOL_DEFAULT, (LPDIRECT3DTEXTURE9*)&d3dTexture);
    D3DLOCKED_RECT rect;
    d3dTexture->LockRect(0, &rect, NULL, 0);
    memcpy(rect.pBits, bitmap, b_w * b_h);
    d3dTexture->UnlockRect(0);

    free(fontBuffer);
    free(bitmap);

    return d3dTexture;
}

你的示例对我帮助很大,但是我遇到了一个问题,我正在使用ID3DXSprite来绘制纹理,文本被绘制出来了,但是有一个黑色的框,这是为什么?我做错了吗?代码(抱歉要发布链接,代码太长无法在评论中发布):paste.ofcode.org/bZ7dwEwqHGdj8KG2xLMSGK - cYeR
你没有提供完整的代码,我不知道是谁调用了print_text或者精灵是如何创建的。虽然我不是DirectX专家,但如果你提供所有的代码,我可以看一下。 - mnistic
D3DX9、D3DX10和D3DX11都已被弃用。您应该转而使用DirectX 11,这样您就可以在DirectX Tool Kit中使用“SpriteFont”类,该工具包是开源的。请参阅没有D3DX的生活。请注意,如果对您来说非常重要的是高质量和可扩展的文本,则应考虑使用带有DirectWrite的Direct3D 11。 - Chuck Walbourn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接