CdrTomalak
CdrTomalak

Reputation: 479

Rendering text with DX11

I am trying to figure out how to draw text on screen in SlimDX.

Initial research is not encouraging. The only concrete example I found was this:

http://www.aaronblog.us/?p=36

I am trying to port this to my code, but it's proving extremely difficult, and I'm beginning to wonder after 4 hours if this is the right way to go.

Essentially it seems quite difficult to do something as simple as writing text to the screen. Aaron's method seems the only one out there which is practical at the moment. There are no other points of comparison.

Does anyone else have any advice they could offer?

P.S. I suspect I could have created individual images for letters by now, and coded a routine to convert a string into a series of sprites. It does seem slightly insane to do this though.

Upvotes: 4

Views: 3827

Answers (2)

mrvux
mrvux

Reputation: 8963

There's a nice DirectWrite wrapper called http://fw1.codeplex.com/

It's in c++ but it's very simple to make a mixed mode wrapper for it (which is what i did for my c# projects).

Here is simple example:

.h file

#pragma once
#include "Lib/FW1FontWrapper.h"
using namespace System::Runtime::InteropServices;

public ref class DX11FontWrapper
{
public:
    DX11FontWrapper(SlimDX::Direct3D11::Device^ device);
    void Draw(System::String^ str,float size,int x,int y,int color);
private:
    SlimDX::Direct3D11::Device^ device;
    IFW1FontWrapper* pFontWrapper;
};

.cpp file

#include "StdAfx.h"
#include "DX11FontWrapper.h"

DX11FontWrapper::DX11FontWrapper(SlimDX::Direct3D11::Device^ device)
{
    this->device = device;

    IFW1Factory *pFW1Factory;
    FW1CreateFactory(FW1_VERSION, &pFW1Factory);
    ID3D11Device* dev = (ID3D11Device*)device->ComPointer.ToPointer();

    IFW1FontWrapper* pw;

    pFW1Factory->CreateFontWrapper(dev, L"Arial", &pw); 
    pFW1Factory->Release();

    this->pFontWrapper = pw;
}

void DX11FontWrapper::Draw(System::String^ str,float size,int x,int y, int color)
{
    ID3D11DeviceContext* pImmediateContext = 
        (ID3D11DeviceContext*)this->device->ImmediateContext->ComPointer.ToPointer();

    void* txt = (void*)Marshal::StringToHGlobalUni(str);
    pFontWrapper->DrawString(pImmediateContext, (WCHAR*)txt, size, x, y, color, 0);
    Marshal::FreeHGlobal(System::IntPtr(txt));
}

Upvotes: 3

Nico Schertler
Nico Schertler

Reputation: 32597

Rendering text is a bit complex, indeed. The only way to render general text is to use Direct2D / DirectWrite. And this is only supported in DirectX10. So you have to create a DirectX 10 device, DirectWrite and Direct2D Factories. You then can create a shared texture that can be used by both DirectX 10 and 11 devices.

This texture will contain the text after rendering. Aaron uses this texture to blend it with the full screen. Therefore, you can use DirectWrite to draw complete strings. Essentially, this is just like drawing a textured quad.

Another way of doing this is, as you already mentioned, drawing a sprite sheet and splitting strings into several sprites. I assume, the latter way is a bit faster, but I haven't tested it yet. I used this method in my Sprite & Text engine. See methods AssertDevice and CreateCharTable

Upvotes: 4

Related Questions