FreeType生成多个纹理

时间:2018-05-03 08:06:46

标签: c++ directx directx-11 freetype

我试图在DirectX 11下使用FreeType,以便在屏幕上绘制一些文字。目前,我可以将 FT_Bitmap * 转换为 ID3D11Texture2D * ,然后创建 ID3D11ShaderResourceView *

然后我使用着色器绘制此着色器资源视图。问题是这段代码只绘制了文本的最后一个字母,而且我不明白为什么。

首先,这是我渲染UI元素的方式:

Graph.cpp

void Graph::DrawSprite(Object* p_object)
{
/*...*/

    // Problem here
    Text* text = nullptr;
    text = p_object->GetComponent<Text>();
    if (text)
        _graphicAPI->Draw(text->GetBuffer());
/*...*/
}

GraphicAPI

void GraphicAPI::Draw(const TextBuffer& p_text)
{
    _shaders._orthoWindow->Render(_deviceContext);
    _shaders._sprite->Render(_deviceContext, _shaders._orthoWindow->GetIndexCount(), 
                             _managers._font->GetTextureView(p_text._font), p_text._matrix, _camera2D);
}

SpriteShader.cpp

bool SpriteShader::Render(ID3D11DeviceContext* p_deviceContext, unsigned int p_indexCount, ID3D11ShaderResourceView* p_texView, 
                          const Math::Mat4& p_matrix, const CameraBuffer& p_camera)
{
    bool result = SetShaderParameters(p_deviceContext, p_texView, p_matrix, p_camera._view, p_camera._projection);
    if (!result)
        return false;

    RenderShader(p_deviceContext, p_indexCount);

    return true;
}

bool SpriteShader::SetShaderParameters(ID3D11DeviceContext* p_deviceContext, ID3D11ShaderResourceView* p_texView,
    const Math::Mat4& p_worldMatrix, const Math::Mat4& p_viewMatrix, const Math::Mat4& p_projectionMatrix)
{
    HRESULT result;
    D3D11_MAPPED_SUBRESOURCE mappedResource;
    unsigned int bufferNumber;
    MatrixBufferType* dataMatrixPtr;

    result = p_deviceContext->Map(_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
    if (FAILED(result))
        return false;

    dataMatrixPtr = (MatrixBufferType*)mappedResource.pData;

    dataMatrixPtr->world = p_worldMatrix;
    dataMatrixPtr->view = p_viewMatrix;
    dataMatrixPtr->projection = p_projectionMatrix;

    p_deviceContext->Unmap(_matrixBuffer, 0);

    bufferNumber = 0;

    p_deviceContext->VSSetConstantBuffers(bufferNumber, 1, &_matrixBuffer);

    p_deviceContext->PSSetShaderResources(0, 1, &p_texView);

    return true;
}

void SpriteShader::RenderShader(ID3D11DeviceContext* p_deviceContext, unsigned int p_indexCount)
{
    p_deviceContext->IASetInputLayout(_layout);

    p_deviceContext->VSSetShader(_vertexShader, NULL, 0);
    p_deviceContext->PSSetShader(_pixelShader, NULL, 0);

    p_deviceContext->PSSetSamplers(0, 1, &_sampleState);

    p_deviceContext->DrawIndexed(p_indexCount, 0, 0);
}

以下是我如何加载TTF字体并将其转换为ID3D11ShaderResourceView *。

FontManager.cpp

bool FontManager::LoadFont(ID3D11Device* p_device, const std::string p_extension, const char* p_fileName)
{
    if (p_extension == ".ttf")
    {
        Font* font = new Font();
        if (!font)
            return false;

        if (!font->LoadTTF(p_device, _library, p_fileName))
        {
            delete font;
            return false;
        }

        // sets text (tmp)
        font->RenderFont(p_device, "ASDASD", Math::Vec2(100, 100));
        _fonts.push_back(font);

        return true;
    }

    return false;
}

对于 Font 类,我基于this教程。 CreateShaderResourceView() my_draw_bitmap()

Font.cpp

bool Font::LoadTTF(ID3D11Device* p_device, FT_Library p_library, const char* p_fileName)
{
    _fileName = p_fileName;

    if (FT_New_Face(p_library, p_fileName, 0, &_face))
        return false;

    if (FT_Set_Pixel_Sizes(_face, 0, DEFAULT_FONT_SIZE))
        return false;

    return true;
}

void Font::RenderFont(ID3D11Device* p_device, const char* p_text, Math::Vec2 p_position)
{
    FT_GlyphSlot slot = _face->glyph;

    FT_Vector pen;
    pen.x = p_position._x;
    pen.y = p_position._y;

    FT_Matrix matrix;
    float angle = (/*90*/0.0 / 360) * 3.14159 * 2;

    matrix.xx = (FT_Fixed)(cos(angle) * 0x10000L);
    matrix.xy = (FT_Fixed)(-sin(angle) * 0x10000L);
    matrix.yx = (FT_Fixed)(sin(angle) * 0x10000L);
    matrix.yy = (FT_Fixed)(cos(angle) * 0x10000L);

    for (unsigned int i = 0; i < strlen(p_text); ++i)
    {
        FT_Set_Transform(_face, &matrix, &pen);

        if (FT_Load_Char(_face, p_text[i], FT_LOAD_RENDER))
            continue;

        if (!CreateShaderResourceView(p_device, &slot->bitmap))
            return;

        // Increment pen position
        pen.x += slot->advance.x >> 6;
    }
}

bool Font::CreateShaderResourceView(ID3D11Device* p_device, FT_Bitmap* p_bitmap)
{
    D3D11_TEXTURE2D_DESC textureDesc;
    ZeroMemory(&textureDesc, sizeof(textureDesc));

    textureDesc.Width = p_bitmap->width;
    textureDesc.Height = p_bitmap->rows;
    textureDesc.MipLevels = 1;
    textureDesc.ArraySize = 1;
    textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    textureDesc.SampleDesc.Count = 1;
    textureDesc.SampleDesc.Quality = 0;
    textureDesc.Usage = D3D11_USAGE_DEFAULT;
    textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
    textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    textureDesc.MiscFlags = 0;

    ID3D11Texture2D* texture2D;
    ZeroMemory(&texture2D, sizeof(texture2D));

    D3D11_SUBRESOURCE_DATA resourceData;

    resourceData.pSysMem = p_bitmap->buffer;
    resourceData.SysMemPitch = p_bitmap->pitch;
    resourceData.SysMemSlicePitch = 0;

    HRESULT res = p_device->CreateTexture2D(&textureDesc, &resourceData, &texture2D);
    if (FAILED(res))
        return false;

    D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
    shaderResourceViewDesc.Format = textureDesc.Format;
    shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
    shaderResourceViewDesc.Texture2D.MipLevels = 1;

    HRESULT result = p_device->CreateShaderResourceView(texture2D, &shaderResourceViewDesc, &_shaderResourceView);
    if (FAILED(result))
        return false;

    return true;
}

着色器:

Sprite.ps 我使用此着色器绘制UI元素):

Texture2D spriteTexture;
SamplerState SampleType;

struct PixelInputType
{
    float4 position : SV_POSITION;
    float2 tex : TEXCOORD0;
};

float4 SpritePixelShader(PixelInputType input) : SV_TARGET
{
    float4 textureColor;

    textureColor = spriteTexture.Sample(SampleType, input.tex);

    return textureColor;
} 

Sprite.vs

cbuffer MatrixBuffer
{
    matrix worldMatrix;
    matrix viewMatrix;
    matrix projectionMatrix;
};

struct VertexInputType
{
    float4 position : POSITION;
    float2 tex : TEXCOORD0;
};

struct PixelInputType
{
    float4 position : SV_POSITION;
    float2 tex : TEXCOORD0;
};

PixelInputType SpriteVertexShader(VertexInputType input)
{
    PixelInputType output;

    input.position.w = 1.0f;

    output.position = mul(input.position, worldMatrix);
    output.position = mul(output.position, viewMatrix);
    output.position = mul(output.position, projectionMatrix);

    output.tex = input.tex;

    return output;
}

这是我得到的:

result

这个人(here)有同样的问题,但解决方案并不适合我。有谁知道如何解决这个问题?我已经坚持了一个星期了......

1 个答案:

答案 0 :(得分:0)

似乎在for (unsigned int i = 0; i < strlen(p_text); ++i)内部,您尝试逐字母呈现字体并在每次迭代时重新创建着色器资源视图。因此,最后您将看到包含最后一个字母纹理视图的着色器资源视图。