Sign in to follow this  
garusher

TTF implementation.

Recommended Posts

garusher    164

Hi All,

 

I'm trying to draw to the screen using Directx11. did some reading and found TTF. but i cannot seem to get it working and would like some help. currently just trying to display the letter "H". my application is displaying 3d object at 0,0 and i have a orbiting camera.

 

I figured i could massage the tex, co-efficient and position data into my existing PositionTextured structure and dump it to FontShader. 

 

I seem to be constructing the PositionTextured struct okay, but what should be an "H" is displayed as a white square very far in positive z. my objects are displayed in negative z.

 

here is some relavant code.

TTF::Font *m_font;
std::vector<PositionTextured> params;
ID3D11Buffer *m_pFontBuffer;
struct PositionTextured
{
    PositionTextured(){}
    PositionTextured(float x, float y, float z, float u, float v) : pos(x, y, z), tex(u, v){}
    PositionTextured(D3DXVECTOR3 position, D3DXVECTOR2 texture) : pos(position), tex(texture){}
    D3DXVECTOR3 pos;
    D3DXVECTOR2 tex;
};

void DOIT::BuildDisplay()
{
params.clear();
std::string msg = "H";
TTFCore::Triangulator2D<TTFCore::vec2t, TTF::TriSmall> triangulator2DI;
for (auto &m : msg)
{
    TTFCore::CodePoint cp(m);
    m_font->TriangulateGlyph(cp, triangulator2DI);
    TTFCore::Mesh mesh;
    for (auto i : triangulator2DI)
    {
        PositionTextured pt0;
	pt0.pos.x = triangulator2DI[i.i0].x;
	pt0.pos.y = triangulator2DI[i.i0].y;
	pt0.pos.z = 0.0f;

	PositionTextured pt1;
	pt1.pos.x = triangulator2DI[i.i1].x;
	pt1.pos.y = triangulator2DI[i.i1].y;
	pt1.pos.z = 0.0f;

        PositionTextured pt2;
	pt2.pos.x = triangulator2DI[i.i2].x;
	pt2.pos.y = triangulator2DI[i.i2].y;
	pt2.pos.z = 0.0f;

	if (i.coef != 0)
	{
	    pt0.tex.x = 0;
	    pt1.tex.x = 1;
	    pt2.tex.x = 2;
	}
	else
	{
	    pt0.tex.x = 0;
	    pt1.tex.x = 0;
	    pt2.tex.x = 0;
	}

	pt0.tex.y = i.coef;
	pt1.tex.y = i.coef;
	pt2.tex.y = i.coef;
		
	params.push_back(pt0);
	params.push_back(pt1);
	params.push_back(pt2);
    }
}

HRESULT result;
D3D11_SUBRESOURCE_DATA vertexData;
D3D11_BUFFER_DESC vertexBufferDesc;

//prepare a description of the vertex buffer
ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc));
vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
vertexBufferDesc.ByteWidth = sizeof(PositionTextured) * params.size();
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = 0;

//set subresource data to point to  our objects vertexdata
vertexData.pSysMem = &(params[0]);

//create buffers in our object
result = m_pd3dDevice->CreateBuffer(&vertexBufferDesc, &vertexData, &m_pFontBuffer);
if (FAILED(result))
    return;
}

void DOIT::Render()
{
if (params.size())
    {
        m_pImmediateContext->PSSetShader(m_pFontShader, NULL, 0);
	m_pImmediateContext->IASetVertexBuffers(0, 1, &m_pFontBuffer, &stride, &offset);
	m_pImmediateContext->Draw(params.size(), 0);
    }
}

and my shader code.

Texture2D txDiffuse : register( t0 );
SamplerState samLinear : register(s0);

cbuffer ConstantBuffer : register(b0)
{
matrix World;
matrix View;
matrix Projection;
};

cbuffer TransparentBuffer
{
float blendAmount;
};

struct VS_INPUT
{
float4 Pos : POSITION;
float2 Tex : TEXCOORD0;
};

struct PS_INPUT
{
float4 Pos : SV_POSITION;
float2 Tex : TEXCOORD0;
};

PS_INPUT VS(VS_INPUT input)
{
PS_INPUT output = (PS_INPUT)0;
output.Pos.w = 1.0f;
output.Pos = mul(input.Pos, World);
output.Pos = mul(output.Pos, View);
output.Pos = mul(output.Pos, Projection);
output.Tex = input.Tex;
return output;
}

float4 PS(PS_INPUT input) : SV_Target
{
float4 color = txDiffuse.Sample(samLinear, input.Tex);
color.a = blendAmount;
return color;
}

float4 PSGray(PS_INPUT input) : SV_Target
{
float4 color = txDiffuse.Sample(samLinear, input.Tex);
float fLuminance = 0.299f * color.r + 0.587f * color.g + 0.114f * color.b;
return float4(fLuminance, fLuminance, fLuminance, blendAmount);
}

float round(float val)
{
return sign(val) * floor(abs(val) + 0.5f);
}

float4 PSFont(PS_INPUT input) : SV_Target
{
float3 tpos = float3(input.Tex.x * 0.5f, max(input.Tex.x - 1.0f, 0.0f), input.Tex.y);
float alpha = round((tpos.x * tpos.x - tpos.y) * tpos.z + 0.5f);
return (float4(1.0f, 1.0f, 1.0f, 1.0f) * alpha);
}

Thanks

Gary

Edited by garusher

Share this post


Link to post
Share on other sites
Ryan_001    3476

The vertices are in 'font units'.  This is the internal data type used in all .ttf files.  This web page; https://www.microsoft.com/typography/otspec/TTCH01.htm will explain all the terminology, what an 'em square' is, converting font units to pixels, what 'points' are, etc...

 

For example, to convert 'font units' to pixels you can do something like:

TTF::FontMetrics font_metrics = font->GetFontMetrics();
float units_per_em = static_cast<float>(font->UnitsPerEM());
float scale = (pt_size * screen_dpi) / (72 * units_per_em); // convert pt_size and screen_dpi into pixels

scale then is a scaling factor you can use to create a transformation matrix for the vertex shader, or pre-scale all vertices by that value.  Also depending on your coordinate system/transformations you may need to invert the y axis.

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