FreeType生成多个纹理 [英] FreeType generates multiple textures

查看:168
本文介绍了FreeType生成多个纹理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



然后我使用着色器绘制此着色器资源视图。问题在于该代码仅绘制文本的最后一个字母4次,而我却不明白为什么。



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



Graph.cpp

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

//问题
文字*文字= 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结果= SetShaderParameters(p_deviceContext,p_texView,p_matrix,p_camera._view,p_camera._projection);
如果(!result)
返回false;

RenderShader(p_deviceContext,p_indexCount);

返回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结果;
D3D11_MAPPED_SUBRESOURCE mappingResource;
unsigned int bufferNumber;
MatrixBufferType * dataMatrixPtr;

结果= p_deviceContext-> Map(_matrixBuffer,0,D3D11_MAP_WRITE_DISCARD,0,& mappedResource);
如果(失败(结果))
返回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);

返回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)
返回false;

if(!font-> LoadTTF(p_device,_library,p_fileName))
{
删除字体;
返回false;
}

//设置文本(tmp)
font-> RenderFont(p_device, ASDASD,Math :: Vec2(100,100));
_fonts.push_back(font);

返回true;
}

返回false;
}

对于 Font 类,我基于



这家伙(此处)遇到了相同的问题,但是该解决方案对我不起作用。有谁知道如何解决这个问题?我已经在这个问题上停留了一周了。

解决方案

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


I'm trying to use FreeType under DirectX 11, in order to draw some text on my screen. For the moment i'm able to convert a FT_Bitmap* to a ID3D11Texture2D*, then I create a ID3D11ShaderResourceView*.

I then use a shader to draw this shader resource view. The problem is that this code only draws the last letter of the text 4 times, and I don't really see why.

First, here is how I render a UI Element :

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);
}

Here is how I load a TTF font and convert it to a 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;
}

For the Font class, I based myself on this tutorial. CreateShaderResourceView() is 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;
}

And the shaders :

Sprite.ps (I use this shader to draw UI elements):

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;
}

Here is what I get :

This guy (here) had the same issue, but the solution doesn't work for me. Does anyone know how to solve this ? I've been stuck on this for a week now...

解决方案

It seems that inside of for (unsigned int i = 0; i < strlen(p_text); ++i) you try to render font letter-by-letter and recreate shader resource view on each iteration. So at the end you are left with shader resource view containing last letter texture view.

这篇关于FreeType生成多个纹理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆