0

我正在学习 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;
}
4

1 回答 1

0

虽然构造顶点数组的那段代码乍一看似乎是正确的,但似乎您正在尝试使用尚未设置的着色器来绘制顶点!不看整个代码很难准确回答你,但我猜你需要做这样的事情:

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

希望这可以帮助!

PS:另外,不要忘记在使用资源后通过调用释放资源Release()

于 2012-11-23T23:05:59.937 回答