C++ FreeType生成多个纹理

C++ FreeType生成多个纹理,c++,directx,directx-11,freetype,C++,Directx,Directx 11,Freetype,我试图在DirectX 11下使用FreeType,以便在屏幕上绘制一些文本。目前,我能够将FT\u位图*转换为ID3D11Texture2D*,然后创建一个ID3D11ShaderResourceView* 然后,我使用着色器绘制此着色器资源视图。问题是这段代码只画了文本的最后一个字母4次,我真的不明白为什么 首先,以下是如何呈现UI元素: 图表.cpp: void Graph::DrawSprite(Object* p_object) { /*...*/ // Problem he

我试图在DirectX 11下使用FreeType,以便在屏幕上绘制一些文本。目前,我能够将FT\u位图*转换为ID3D11Texture2D*,然后创建一个ID3D11ShaderResourceView*

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

首先,以下是如何呈现UI元素:

图表.cpp

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

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

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

    // Problem here
    Text* text = nullptr;
    text = p_object->GetComponent<Text>();
    if (text)
        _graphicAPI->Draw(text->GetBuffer());
/*...*/
}
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;
}
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;
}
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;
}
对于字体类,我基于教程。CreateShaderResourceView()是我的绘图位图()

Font.cpp

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

    // Problem here
    Text* text = nullptr;
    text = p_object->GetComponent<Text>();
    if (text)
        _graphicAPI->Draw(text->GetBuffer());
/*...*/
}
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;
}
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;
}
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;
}
精灵vs

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

    // Problem here
    Text* text = nullptr;
    text = p_object->GetComponent<Text>();
    if (text)
        _graphicAPI->Draw(text->GetBuffer());
/*...*/
}
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;
}
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;
}
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;
}
以下是我得到的:


这家伙()也有同样的问题,但解决方案对我不起作用。有人知道如何解决这个问题吗?我已经在这上面呆了一个星期了…

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

谢谢^^^,我还必须通过此
textureDesc.Width=p_bitmap->Width更改textureDesc.Width值