• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Tim Lawton

DX11
Creating a Font Engine in DirectX11

15 posts in this topic

Hey there,

I've been trying to create a font engine using Rastertek's guide over at http://rastertek.com/dx11tut12.html

I've come across a problem I can't seem to fix, I've created a struct which holds some data which is used to find the location and size of the font I am using from a image file (a .dds file). It initializes fine, but when it comes to rendering the struct's values are all 0. I'm going to show my font class and say whats going on, you can reference it all back from the tutorial linked above.

If anyone who is experienced in DirectX11 could see a solution to this problem I'd be grateful Also the 'fontdata.txt" and "font.dds" are available on that link also

Font.h
[CODE]
//--------------------------------------------------\\
// Font.h under Text class \\
// handles texture for the font \\
//--------------------------------------------------\\
#ifndef _FONT_H
#define _FONT_H
//includes
#include <D3D11.h>
#include <D3DX10math.h>
#include <fstream>
using namespace std;
#include "Texture.h"
//class
class Font
{
private:
struct FontType
{
float left, right;
int size;
};
struct VertexType
{
D3DXVECTOR3 position;
D3DXVECTOR2 texture;
};
public:
Font();
Font(const Font&amp;);
~Font();
bool Init(ID3D11Device*, char*, CHAR*);
void Shutdown();
ID3D11ShaderResourceView* GetTexture();
void BuildVertexArray(void*, char*, float, float);
private:
bool LoadFontData(char*);
void ReleaseFontData();
bool LoadTexture(ID3D11Device*, CHAR*);
void ReleaseTexture();
private:
FontType* fonttype;
Texture* texture;
};
#endif
[/CODE]


Font.cpp
[CODE]
//--------------------------------------------------\\
// Font.cpp under Text class \\
// handles texture for the font \\
//--------------------------------------------------\\
#include "Font.h"
Font::Font()
{
fonttype = 0;
texture = 0;
}
Font::Font(const Font&amp; other){}
Font::~Font(){}
bool Font::Init(ID3D11Device* device, char* fontFilename, CHAR* textureFilename)
{
bool result;

//Load in the text file containing the font data.
result = LoadFontData(fontFilename);
if(!result)
{
return false;
}
// Load the texture that has the font characters on it.
result = LoadTexture(device, textureFilename);
if(!result)
{
return false;
}
return true;
}
void Font::Shutdown()
{
//Release the font texture.
ReleaseTexture();
//Release the font data.
ReleaseFontData();
return;
}
bool Font::LoadFontData(char* filename)
{
ifstream fin;
int i;
char temp;
//Create the font spacing buffer
fonttype = new FontType[95];
if(!fonttype)
{
return false;
}
//Read in the font size and spacing between chars
fin.open(filename);
if(fin.fail())
{
return false;
}
//Read in the 95 used ascii characters for text.
for(i=0; i<95; i++)
{
fin.get(temp);
while(temp != ' ')
{
fin.get(temp);
}
fin.get(temp);
while(temp != ' ')
{
fin.get(temp);
}
fin >> fonttype[i].left;
fin >> fonttype[i].right;
fin >> fonttype[i].size;
}
// Close the file.
fin.close();
return true;
}
void Font::ReleaseFontData()
{
// Release the font data array.
if(fonttype)
{
delete [] fonttype;
fonttype = 0;
}
return;
}
bool Font::LoadTexture(ID3D11Device* device, CHAR* filename)
{
bool result;
//Create the texture object.
texture = new Texture;
if(!texture)
{
return false;
}
//Initialize the texture object.
result = texture->Init(device, filename);
if(!result)
{
return false;
}
return true;
}
void Font::ReleaseTexture()
{
//Release the texture object.
if(texture)
{
texture->Shutdown();
delete texture;
texture = 0;
}
return;
}
ID3D11ShaderResourceView* Font::GetTexture()
{
return texture->GetTexture();
}
void Font::BuildVertexArray(void* vertices, char* sentence, float drawX, float drawY)
{
VertexType* vertexPtr;
int numLetters, index, i, letter;

// Coerce the input vertices into a VertexType structure.
vertexPtr = (VertexType*)vertices;
// Get the number of letters in the sentence.
numLetters = (int)strlen(sentence);
// Initialize the index to the vertex array.
index = 0;
// Draw each letter onto a quad.
for(i=0; i<numLetters; i++)
{
letter = ((int)sentence[i]) - 32;
// If the letter is a space then just move over three pixels.
if(letter == 0)
{
drawX = drawX + 3.0f;
}
else
{
// First triangle in quad.
vertexPtr[index].position = D3DXVECTOR3(drawX, drawY, 0.0f); // Top left.
vertexPtr[index].texture = D3DXVECTOR2(fonttype[letter].left, 0.0f);
index++;
vertexPtr[index].position = D3DXVECTOR3((drawX + fonttype[letter].size), (drawY - 16), 0.0f); // Bottom right.
vertexPtr[index].texture = D3DXVECTOR2(fonttype[letter].right, 1.0f);
index++;
vertexPtr[index].position = D3DXVECTOR3(drawX, (drawY - 16), 0.0f); // Bottom left.
vertexPtr[index].texture = D3DXVECTOR2(fonttype[letter].left, 1.0f);
index++;
// Second triangle in quad.
vertexPtr[index].position = D3DXVECTOR3(drawX, drawY, 0.0f); // Top left.
vertexPtr[index].texture = D3DXVECTOR2(fonttype[letter].left, 0.0f);
index++;
vertexPtr[index].position = D3DXVECTOR3(drawX + fonttype[letter].size, drawY, 0.0f); // Top right.
vertexPtr[index].texture = D3DXVECTOR2(fonttype[letter].right, 0.0f);
index++;
vertexPtr[index].position = D3DXVECTOR3((drawX + fonttype[letter].size), (drawY - 16), 0.0f); // Bottom right.
vertexPtr[index].texture = D3DXVECTOR2(fonttype[letter].right, 1.0f);
index++;
// Update the x location for drawing by the size of the letter and one pixel.
drawX = drawX + fonttype[letter].size + 1.0f;
}
}
return;
}
[/CODE]

During the while loop that fills up the array, it starts to store the data. But when it gets to 'drawX = drawX + fonttype[letter].size + 1.0f;' the fonttype array is empty, and stores all 0s for left, right and size.

Any ideas?

EDIT:

to get a better understanding of what I mean, you can see here the fonttype is holding values:
http://img651.imageshack.us/img651/9278/fonttypefilled.png

But at the end of the method it is empty:
http://img715.imageshack.us/img715/3660/fonttypeempty.png

I'm stumped Edited by Xuchilbara
0

Share this post


Link to post
Share on other sites
I'm sorry I can't help you with your exact problem, here are my two cents on fonts and DirectX

1. Drawing 2-D fonts is the responsibility of the OS and you can leverage all that goodness using GDI with offscreen DC or using D2D. No need to wrap or create anything in DX11. We are spoiled because DX9 fonts could also do 2-d fonts but ....
2. The main reason of a DX font is to be a 3-d font which can be rotated and lit with pixel shaders. This is what DX9 font was originally intended for in my opinion, and I've seen people use it for that purpose to good effect.

Going forwards ...

If you need to create 3-d meshes to represent letters of an alphabet, you can either do it offline mathematically with the old DX9 font routines and save the mesh to a file format and read it in DX11 and use it .... or you can have your art team generate these meshes and bring them into the game through normal content pipeline.

All 2-d fonts should be done with D2D or GDI. If you need to get them into 3-d space, you can either use project/unproject to convert a 3-d world position into a 2-d (x,y) point or place a billboard in 3-d space and then write the font using 2-d APIs onto a texture and map it to the billboard. Edited by Steve_Segreto
1

Share this post


Link to post
Share on other sites
Yeah, I know that way of doing it, you mean by making an adapter and linking it with the swap chain, allowing to use DirectX9 or 10. Then using their functions to create font. Although I am not trying to create 3D font, or anything fancy. I am trying to create 2D font which can hold values, such as FPS or mouse position. I can't figure out why the values of my struct almost disappear for no reason, really bumming me out
0

Share this post


Link to post
Share on other sites
I don't think the values disappear, I rather suspect they were not there in the first place.

The code looks semantically the same like rasterteks, so the problems lies probably elsewhere. The debug values -842150451 and -4.3160208E+08 are 0xCDCDCDCD in hex, which is a well known [url="http://en.wikipedia.org/wiki/Magic_number_(programming)"]magic [strike]word[/strike]number[/url] from the visual studio C++ debug runtime, marking uninitialized heap memory.

I guess your not really loading that glyph description file (wrong path ?) in LoadFontData. Either that or you corrupt your heap elsewhere.

[b]Edit[/b]: Hmmm, scratch that, I wasn't looking closely enough. Looks like the >> parsing fails for some reason. Check the state of the of the stream after parsing each value. Edited by unbird
0

Share this post


Link to post
Share on other sites
You mean during this for loop?

[CODE]
//Read in the 95 used ascii characters for text.
for(i=0; i<95; i++)
{
fin.get(temp);
while(temp != ' ')
{
fin.get(temp);
}
fin.get(temp);
while(temp != ' ')
{
fin.get(temp);
}
fin >> fonttype[i].left;
fin >> fonttype[i].right;
fin >> fonttype[i].size;
}
[/CODE]

Everythings to be going fine within it
0

Share this post


Link to post
Share on other sites
Really confusing. If the values get parsed just fine, I don't see a reason why they should change afterwards. Nothing else writes to it. At least not in the code you have provided so far (it looks like the original code after all). We need to see more code then.

If you got a professional version of Visual Studio, I think there's a debugger option to break on (specific) memory write or something. Alternatively, grab the raw pointer value after init, add it as a watch (dereferenced), step through your whole frame code and find out [i]when[/i] it changes. Or do a comment/uncomment "binary search".

... wait: Is really the whole array filled with zeroes or just the first entry ? Edited by unbird
0

Share this post


Link to post
Share on other sites
Ok, I was wrong about it reading it in correctly.

As you can see here by this screenshot: http://img29.imageshack.us/img29/4099/41977412.jpg

i = 5, thus being 6th in the series. the 6th line in fontdata.txt reads: "37 % 0.0205078 0.0302734 10"
so left should be: 0.0205078
right: 0.0302734
size: 10

Although you can see it is all 0.

Sorry I dont know why I said it was working correctly during the for loop, it must of came up with some magic numbers again at some point and I wasn't paying attention. But yeah I can confirm it is constantly 0, not just the first entry.

Somebody suggested that left and right are floats, and shouldn't be able to take in numbers this long, could that be the case?

Edit: I just tried a breakpoint inside my Init function and something strange came up
http://img41.imageshack.us/img41/553/errorlja.jpg Edited by Xuchilbara
0

Share this post


Link to post
Share on other sites
[url="http://fw1.codeplex.com/"]http://fw1.codeplex.com/[/url] have you tried FW1FontWrapper? May save a bit of your work.

Cheers!
2

Share this post


Link to post
Share on other sites
[quote name='kauna' timestamp='1354059082' post='5004736']
[url="http://fw1.codeplex.com/"]http://fw1.codeplex.com/[/url] have you tried FW1FontWrapper? May save a bit of your work.

Cheers!
[/quote]

This seems pretty cool, how do I use it?
2

Share this post


Link to post
Share on other sites
It's pretty easy, Link the library to your project, Call following functions:

IFW1Factory *pFW1Factory;
HRESULT hResult = FW1CreateFactory(FW1_VERSION, &pFW1Factory);
if(FAILED(hResult)) {
return;
}

hResult = pFW1Factory->CreateFontWrapper(pDevice, _T("ARIAL"), &pFontWrapper);
if(FAILED(hResult)) {
return;
}

....
and to draw some text:

pFontWrapper->DrawString(pDeviceContext,_T("HELLO"),FontSize,PositionX,PositionY,Color,FW1_LEFT | FW1_TOP);


Just don't call the creation functions every time you draw text.

Best regards!
2

Share this post


Link to post
Share on other sites
Also lets say I want to replace my own text with some other value, such as FPS? I could just replace the _T("HELLO") with fps->getfps() for example?
0

Share this post


Link to post
Share on other sites
Well, the second parameter is just a pointer to a TCHAR string in this case so you may use the required string construction functions to manipulate a TCHAR array to contain the desired text. [url="http://msdn.microsoft.com/en-us/library/ybk95axf.aspx"]http://msdn.microsoft.com/en-us/library/ybk95axf.aspx[/url] contains some string manipulation functions.

Cheers!
0

Share this post


Link to post
Share on other sites
This is horrible, I have no idea how to link this up or anything, including its folders though the Linker didnt do anything
0

Share this post


Link to post
Share on other sites
[url="http://fw1.codeplex.com/releases/view/75558"]http://fw1.codeplex.com/releases/view/75558[/url] <- from this page download FW1FontWrapper 1.1, Header, Lib & DLL x86/x64, you don't need the source code.

Include the lib in your project and put the DLL in your program directory. Include the .h file to your text rendering code and then the code should work.

Cheers!
2

Share this post


Link to post
Share on other sites
Thanks alot for your help kauna, but I have finally fixed my own broken version! turns out the Font.vs HLSL had this line:

float4 position : POSITION;

when it should of been

float4 position : SV_POSITION;
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0

  • Similar Content

    • By YixunLiu
      Hi,
      I have a surface mesh and I want to use a cone to cut a hole on the surface mesh.
      Anybody know a fast method to calculate the intersected boundary of these two geometries?
       
      Thanks.
       
      YL
       
    • By hiya83
      Hi, I tried searching for this but either I failed or couldn't find anything. I know there's D11/D12 interop and there are extensions for GL/D11 (though not very efficient). I was wondering if there's any Vulkan/D11 or Vulkan/D12 interop?
      Thanks!
    • By lonewolff
      Hi Guys,
      I am just wondering if it is possible to acquire the address of the backbuffer if an API (based on DX11) only exposes the 'device' and 'context' pointers?
      Any advice would be greatly appreciated
    • By MarcusAseth
      bool InitDirect3D::Init() { if (!D3DApp::Init()) { return false; } //Additional Initialization //Disable Alt+Enter Fullscreen Toggle shortkey IDXGIFactory* factory; CreateDXGIFactory(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&factory)); factory->MakeWindowAssociation(mhWindow, DXGI_MWA_NO_WINDOW_CHANGES); factory->Release(); return true; }  
      As stated on the title and displayed on the code above, regardless of it Alt+Enter still takes effect...
      I recall something from the book during the swapChain creation, where in order to create it one has to use the same factory used to create the ID3D11Device, therefore I tested and indeed using that same factory indeed it work.
      How is that one particular factory related to my window and how come the MakeWindowAssociation won't take effect with a newly created factory?
      Also what's even the point of being able to create this Factories if they won't work,?(except from that one associated with the ID3D11Device) 
    • By ProfL
      Can anyone recommend a wrapper for Direct3D 11 that is similarly simple to use as SFML? I don't need all the image formats etc. BUT I want a simple way to open a window, allocate a texture, buffer, shader.
  • Popular Now