ID3D10Font::DrawText

Started by
4 comments, last by BattleMetalChris 12 years, 3 months ago
I've been having a bit of trouble getting DrawText to work.

After my first try it immediately messed up all my other rendering. A few hours of swearing later, I eventually found out that it secretly turns off the depth test behind the scenes, and you have to save the depth stencil state before you call it, and reinstate it afterwards.

With that in place, the rest of my scene works ok again, but the text doesn't show up at all.

I create a ID3DX10Font and ID3DX10Sprite:


D3DX10_FONT_DESC fontDesc =
{
20, // height
0, // width
FW_NORMAL, // weight
1, // mip levels
false, // italic
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH | FF_DONTCARE,
"Arial"
};

HelperFunctions::checkError(D3DX10CreateFontIndirect(m_d3dDevice, &fontDesc, &m_font), "Directx Error", "Error creating ID3DX10Font");
HelperFunctions::checkError(D3DX10CreateSprite(m_d3dDevice, 256, &m_fontSprite), "Directx Error", "Error creating ID3DX10Sprite");


and then draw the text using


void DX10Renderer::drawText()
{
UINT stencilRef = 1;
ID3D10DepthStencilState* depthStencilState;
std::string textString("Some test Text");
D3DXCOLOR fontColor = D3DXCOLOR(255,0,0,255);

m_d3dDevice->OMGetDepthStencilState(&depthStencilState, &stencilRef);
m_fontSprite->Begin(D3DX10_SPRITE_SAVE_STATE);

RECT rect;
rect.top = 10;
rect.left = 10;
rect.bottom = 500;
rect.right = 500;
m_font->DrawText(m_fontSprite, textString.c_str(), textString.size(), &rect, NULL , fontColor);
m_fontSprite->End();

// don't forget to put the render target and depth stencil back when we've finished
m_d3dDevice->OMSetDepthStencilState(depthStencilState, stencilRef);

depthStencilState->Release(); // get adds a reference which we need to release

}


I render to a texture and then draw this to a fullscreen quad. My drawText() function above is called directly after the DrawIndexed statement which draws the final textured quad to the screen, so the correct render targets etc should already be set. The rest of my scene displays perfectly, it's just not writing the text at all.

I've run it through PIX and I get even wierder reults; Although the scene displays perfectly (again without the text though) while it runs and when I press F12 to take a snapshot, when I come to analyse the draw calls inside PIX, the recorded snapshot seems to be totally different - in there, a bunch of the lighting is wrong in the 'render' tab and the final render to the fullscreen quad is just black, but the text shows!.
Advertisement
No-one? :(

Could anyone offer any insight as to why PIX is showing me one thing while the experiment is running and capturing the frame, and a different thing when stepping through the captured frame?
Just looking at my code, try this

change

rect.bottom = 500;
rect.right = 500;


to

rect.bottom = 0;
rect.right = 0;


That probably won't do anything but its worth a try. anyway, I'm pretty sure drawtext changes pretty much all states, so i think you have to reset your depth/stencil state, blending state and primitive topology. also your code seems very complex for this. are you using only direct3d 10 in your app, or are you using direct3d 11 and only d3d 10 for the text?

try this, it might not work, but you can try:

void DX10Renderer::drawText()
{
std::string textString("Some test Text");
D3DXCOLOR fontColor = D3DXCOLOR(255,0,0,255);

RECT rect = {10, 10, 0, 0};
m_font->DrawText(0, textString.c_str(), textString.size(), &rect, NULL , fontColor);

// don't forget to put the render target and depth stencil back when we've finished
m_d3dDevice->OMSetDepthStencilState(depthStencilState, stencilRef);

// reset your blending state (if you have one) and your primitive topology
m_d3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
}
I call DrawText twice, with the DT_CALCRECT flag the first time, so the initial dimensions of my RECT don't really matter (as calling it with this flag doesn't darw anything, but sets the rect to fit the text). I've also stepped through my main code in debug and it is changing the Rect to a different (and sane) size, so there's 'something' there it seems to be trying to draw.

How do you mean by the code looks very complex? I use DX10 for all the drawing in the app.
sorry, when i said complex that was probably not the right word. It just seems to me that you are doing more than you need to to display some simple text. the sprite object only really needs to be used to optimize if your calling drawtext multiple times in a row from what i was reading. I never used the first parameter of drawtext so i'm not sure about that though. I just mentioned the rect thing because i remember having problems with it before, so i just put what i ended up using in my code.

oh yeah! i just remembered, like i said above, drawtext messes with all states, including in the shader. it does something with the geometry shader, so in your techniques in your shader, you have to reset the geometry shader if you don't use one, set it to null, something like this:
technique10 Tech
{
pass P0
{
SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0, PS() ) );
}
}
Ah right :)

I've already tried it with a NULL sprite and the same thing happens. I'll check my geometry shaders assignment in my .fx files when I get home, but I'm pretty sure I already set it to NULL in all my shaders. The normal drawing is unaffected anyway, so I don't think that's causing a problem.

I'm now working round the issue by writing a little application to make fontsheet textures for me, which also encodes the uvs of each character on the fontsheet into a separate 16x16 texture which I can then pass to my own text shader.

I'm still a little worried about the PIX weirdness though.

This topic is closed to new replies.

Advertisement