DirectX 11:文本输出,使用您自己的字体纹理

时间:2012-11-20 12:45:59

标签: text directx sprite textures directx-11

我正在学习DirectX,使用“Sherrod A.,Jones W. - Beginning DirectX 11 Game Programming - 2011”这本书。现在我正在探索关于绘图文本的第4章。

请帮助我们修复我的功能,我正在用它在屏幕上画一个字符串。我已经加载了字体纹理,在函数中我用字母创建了一些精灵,并为它们定义了纹理坐标。这个编译正确,但没有绘制任何东西。怎么了?

bool DirectXSpriteGame :: DrawString(char* StringToDraw, float StartX, float StartY)
{
//VAR
    HRESULT D3DResult;                                                                              //The result of D3D functions

    int i;                                                                                          //Counters
    const int IndexA = static_cast<char>('A');                                                      //ASCII index of letter A
    const int IndexZ = static_cast<char>('Z');                                                      //ASCII index of letter Z
    int StringLenth = strlen(StringToDraw);                                                         //Lenth of drawing string
    float ScreenCharWidth = static_cast<float>(LETTER_WIDTH) / static_cast<float>(SCREEN_WIDTH);    //Width of the single char on the screen(in %)
    float ScreenCharHeight = static_cast<float>(LETTER_HEIGHT) / static_cast<float>(SCREEN_HEIGHT); //Height of the single char on the screen(in %)
    float TexelCharWidth = 1.0f / static_cast<float>(LETTERS_NUM);                                  //Width of the char texel(in the texture %)
    float ThisStartX;                                                                               //The start x of the current letter, drawingh
    float ThisStartY;                                                                               //The start y of the current letter, drawingh
    float ThisEndX;                                                                                 //The end x of the current letter, drawing
    float ThisEndY;                                                                                 //The end y of the current letter, drawing
    int LetterNum;                                                                                  //Letter number in the loaded font
    int ThisLetter;                                                                                 //The current letter

    D3D11_MAPPED_SUBRESOURCE MapResource;                                                           //Map resource
    VertexPos* ThisSprite;                                                                          //Vertecies of the current sprite, drawing
//VAR

//Clamping string, if too long
if(StringLenth > LETTERS_NUM)
{
    StringLenth = LETTERS_NUM;
}

//Mapping resource
D3DResult = _DeviceContext -> Map(_vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MapResource);
if(FAILED(D3DResult))
{
    throw("Failed to map resource");
}
ThisSprite = (VertexPos*)MapResource.pData;

for(i = 0; i < StringLenth; i++)
{
    //Creating geometry for the letter sprite
    ThisStartX = StartX + ScreenCharWidth * static_cast<float>(i);
    ThisStartY = StartY;
    ThisEndX = ThisStartX + ScreenCharWidth;
    ThisEndY = StartY + ScreenCharHeight;

    ThisSprite[0].Position = XMFLOAT3(ThisEndX, ThisEndY, 1.0f);
    ThisSprite[1].Position = XMFLOAT3(ThisEndX, ThisStartY, 1.0f);
    ThisSprite[2].Position = XMFLOAT3(ThisStartX, ThisStartY, 1.0f);

    ThisSprite[3].Position = XMFLOAT3(ThisStartX, ThisStartY, 1.0f);
    ThisSprite[4].Position = XMFLOAT3(ThisStartX, ThisEndY, 1.0f);
    ThisSprite[5].Position = XMFLOAT3(ThisEndX, ThisEndY, 1.0f);

    ThisLetter = static_cast<char>(StringToDraw[i]);

    //Defining the letter place(number) in the font
    if(ThisLetter < IndexA || ThisLetter > IndexZ)
    {
        //Invalid character, the last character in the font, loaded
        LetterNum = IndexZ - IndexA + 1;
    }
    else
    {
        LetterNum = ThisLetter - IndexA;
    }

    //Unwraping texture on the geometry
    ThisStartX = TexelCharWidth * static_cast<float>(LetterNum);
    ThisStartY = 0.0f;
    ThisEndY = 1.0f;
    ThisEndX = ThisStartX + TexelCharWidth;

    ThisSprite[0].TextureCoords = XMFLOAT2(ThisEndX, ThisEndY);
    ThisSprite[1].TextureCoords = XMFLOAT2(ThisEndX, ThisStartY);
    ThisSprite[2].TextureCoords = XMFLOAT2(ThisStartX, ThisStartY);

    ThisSprite[3].TextureCoords = XMFLOAT2(ThisStartX, ThisStartY); 
    ThisSprite[4].TextureCoords = XMFLOAT2(ThisStartX, ThisEndY);   
    ThisSprite[5].TextureCoords = XMFLOAT2(ThisEndX, ThisEndY);

    ThisSprite += VERTEX_IN_RECT_NUM;
}

for(i = 0; i < StringLenth; i++, ThisSprite -= VERTEX_IN_RECT_NUM);

_DeviceContext -> Unmap(_vertexBuffer, 0);
_DeviceContext -> Draw(VERTEX_IN_RECT_NUM * StringLenth, 0);

return true;
}

1 个答案:

答案 0 :(得分:0)

虽然构建Vertex数组的代码乍一看对我来说似乎是正确的,但似乎你正在尝试使用尚未设置的Shader绘制顶点! 如果不查看整个代码就很难准确回答你,但我猜你需要做类似的事情:

1)通过首先从各自的缓冲区中编译它们来创建顶点和像素着色器

2)创建Input Layout描述,描述输入汇编程序阶段将读取的输入缓冲区。它必须与您的VertexPos结构和着色器结构匹配。

3)设置着色器参数。

4)只有现在你可以设置着色器渲染参数:设置InputLayout,以及用于渲染三角形的顶点和像素着色器:

_DeviceContext -> Unmap(_vertexBuffer, 0);

_DeviceContext->IASetInputLayout(myInputLayout);
_DeviceContext->VSSetShader(myVertexShader, NULL, 0); // Set Vertex shader
_DeviceContext->PSSetShader(myPixelShader, NULL, 0); // Set Pixel shader

_DeviceContext -> Draw(VERTEX_IN_RECT_NUM * StringLenth, 0);

此链接可帮助您实现目标:http://www.rastertek.com/dx11tut12.html

此外,我建议您设置一个IndexBuffer并使用方法DrawIndexed来渲染三角形,以提高性能:它允许图形适配器将顶点存储在顶点缓存中,最近允许 - 使用顶点从缓存中取出而不是从顶点缓冲区中读取它。 有关此问题的更多信息,请访问MSDN:http://msdn.microsoft.com/en-us/library/windows/desktop/bb147325(v=vs.85).aspx

希望这有帮助!

P.S:另外,请不要忘记在使用它们之后通过调用Release()来释放资源。