블로그 이미지
대갈장군

calendar

1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

Notice

2008. 2. 23. 02:28 프로그래밍/DirectX

이제 글자를 넣어보자.. 이거네

1. All About Fonts
font를 결정하는 세가지 요소가 있으니 바로 typeface, style 그리고 size다.

1-1. Typeface
타입페이스는 폰트의 모양, 길이 그리고 스트로크등을 결정하는 요소다. serif도 typeface를 결정하는 요소인데 이 serif라는 놈을 찾아보니 글자 모양 중에 끝부분에 각이진것을 serif라 하고 없는 것을 san serif라 한다. 다음 그림을 보면 그 예가 있는데

Image 1.1 - DirectGrid.png Displayed in DirectX

Image 4.1 - Sans Serif and Serif

Times New Roman의 글자 중 M자를 보면 아래쪽에 꺽이는 짧은 라인이 들어간다. 위에도 들어간다. 하지만 San serif에는 그런게 없다. 그것이 차이점이란다... 흠... 그랬군..

1-2. Style
Style은 사실 typeface의 변형이다. 이것은 글자의 무게나 기울기등을 담당한다. 무게라함은 사실 blod냐 아니냐를 말하고 기울기라 함은 italics냐 아니냐를 말한다.

Image 1.1 - DirectGrid.png Displayed in DirectX

Image 4.2 - Italic and Bold Styles

1-3. Size
이제는 크기다. 일반적으로 크기라 함은 글자의 제일 윗부분에서 제일 아랫부분의 크기인데 아래 그림에서 보다시피 의외로 낭비되는 공간이 있네.

Image 1.1 - DirectGrid.png Displayed in DirectX

Image 4.3 - Arial Font Size


이것들을 외우고 있을 필요는 없지만 나중에 사용할때는 반드시 이해하고 있는것이 좋다. 당삼하지요.

2. Creating Fonts and Displaying Text
글자를 그려내는것은 과정상으로 보면 되게 간단한데 다음과 같이 2단계만 거치면 된다.

1. Create the font
2. Draw the text using the created font

2-1. Create the font
폰트를 만들어내야 하는데 만들기 위해선 D3DXCreateFont() 함수를 호출해야 한다.

HRESULT D3DXCreateFont(LPDIRECT3DDEVICE9 pDevice,
                       INT Height,
                       UINT Width,
                       UINT Weight,
                       UINT MipLevels,
                       BOOL Italic,
                       DWORD CharSet,
                       DWORD OutputPrecision,
                       DWORD Quality,
                       DWORD PitchAndFamily,
                       LPCTSTR pFacename,
                       LPD3DXFONT* ppFont);

LPDIRECT3DDEVICE9 pDevice : 이건뭐 d3ddev다

INT Height : g의 아래쪽 부터 M의 위쪽까지의 크기다. 일반적인 사이즈는 12이다.

UINT Width : 폰트의 폭인데 이것은 각각의 글자마다 다르므로 딱히 하나로 지정할 수는 없고 0으로 설정하면 알아서 적당한 크기의 글자로 찍어낸다. 이 인자는 초기값을 주는 것으로써 아마도 크게 주면 크게 줄수록 글자들 자체가 옆으로 늘어날것으로 예상. (테스트 해보자)

UINT Weight : 글자의 두께. 0에서 1000까지 된다는 군. 0으로 놓으면 기본값으로 표현하기. 이 인자에 대해서는 특별히 두께 플래깅이 존재하는데 다음 테이블과 같다.

Flag Value
FW_DONTCARE 0
FW_THIN 100
FW_ULTRALIGHT 200
FW_LIGHT 300
FW_REGULAR 400
FW_MEDIUM 500
FW_DEMIBOLD 600
FW_BOLD 700
FW_ULTRABOLD 800
FW_BLACK 900
[Close Table]

UINT MipLevels : 밉맵 사용 레벨 설정인데 여기서는 1로 해놔도 됨

BOOL Italic : 이것은 이탤릭 체를 사용할 건가 말건가에 대한 설정. TRUE혹은 FALSE설정

DWORD CharSet : 이것은 어떤 글자셋을 사용할 건지 설정하는 건데 일반적으로는 English set으로 설정한다. 왜? 여기는 미국이니까... -_- 각각의 셋에 대해서 알고 싶다면 (한글, 중국어등) 문서를 찾아보면 된단다. 일단 영어를 기본으로 하니까 DEFAULT_CHARSET으로 쓰면 OK

DWORD OutputPrecision : 흠, 이것은 매치되는 글자체가 없는 경우 윈도우가 선택해야 할 글자체를 말하나 본데 일반적으로는 OUT_DEFAULT_PRECIS를 선택해서 사용한단다. 이 인자는 조금 이해가 안된다만 일단 넘어가자.

DWORD Quality : 폰트의 질을 말하는데 다음 테이블과 같은 값이 들어갈 수 있다.

Value Description
DEFAULT_QUALITY This indicates that the quality of the font does not matter.
NONANTIALIASED_QUALITY This indicates that the edges of the font will not be smooth.  It is faster and more efficient than quality types where smooth edges are used.
ANTIALIASED_QUALITY This indicates that the edges of the font are smooth.

Note that if you don't use either this flag or the prior one, DirectX will use antialiased fonts only if the user has selected "Smooth Screen Fonts" in the Control Panel.
PROOF_QUALITY This indicates that the quality of the font is very high, and exactly matches the font image.  However, because font images are not given in every size, this setting limits which sizes you can use, and using different fonts will cause DirectX to choose the closest font size supported.
DRAFT_QUALITY This indicates that the quality of the font is less important than in PROOF_QUALITY, but it allows you to select different sizes of fonts.  Be warned, however, using various styles, such as bold and italic, can slow this one down if you have a lot of fonts.
[Close Table]

DWORD PitchAndFamily : pitch와 font family는 폰트에 추가되는 새로운 2가지 속성이라는데 pitch는 1 인치에 들어가는 글자의 갯수를 말하고 Font Family는 비슷한 형태와 스타일을 가지는 그룹을 말한다.

일반적으로 내가 굉장히 폰트에 민감해 하지 않는다면 DEFAULT_PITCH || FF_DONTCARE로 놓으면 된다만 정말로 정확하게 하고 싶다면 문서를 뒤져봐라.

LPCTSTR pFacename : 폰트 이름을 지정하는 문자열에 대한 포인터. 일반적으로 Arial, Times New Roman 같은게 되겠죠.

LPD3DXFONT* ppFont : 폰트 오브젝트에 대한 포인터. 이 오브젝트가 폰트에 대한 모든 정보를 담게 된다.

LPD3DXFONT font_1;    // create a font object

D3DXCreateFont(d3ddev,    // the Direct3D Device
               20, 0,    // font size twenty with the default width
               FW_NORMAL,    // normal font weight
               1,    // no mipmap levels
               FALSE,    // not italic
               DEFAULT_CHARSET,    // default character set
               OUT_DEFAULT_PRECIS,    // default precision
               DEFAULT_QUALITY,    // default quality
               DEFAULT_PITCH || FF_DONTCARE,    // more defaults...
               L"Arial",    // typeface "Arial"
               &font_1);    // address of the font object created above

이제 다 만들었다.

2-2. Draw the text using the created font
이제 만들어진 폰트를 이용해서 그려보자. 음 DrawText라는 함수가 따로 존재하는구나...

INT DrawText(LPD3DXSPRITE pSprite,
             LPCTSTR pString,
             INT Count,
             LPRECT pRect,
             DWORD Format,
             D3DCOLOR Color);

LPD3DXSPRITE pSprite : 쪽화면 인자네... 이것을 사용하여 글자를 그려내는데 만약 안 만들었다면 NULL로 놓아도 무방하나 만약 빈번하게 재사용할 글자라면 만들어서 사용하는것이 효율적인 면에서 낫다.

LPCSTR pString : 디스플레이 하고 싶은 글자다.

INT Count : 디스플레이 할 글자수.

LPRECT pRect : 어디에 글자가 디스플레이 되어야 할지 설정해주는 사각형 좌표.

DWORD Format : 레이아웃을 결정하는 인자. 다음 테이블 참조.

[Table 4.3 - Font Format Flags]
Value Description
DT_SINGLELINE Displays the text on a single line, regardless of line breaks or carraige returns.
DT_CALCRECT Calculates the height and width of the rectangle for you, regardless of the values stored specified in the pRect parameter.
DT_CENTER Centers the text in the rectangle.
DT_LEFT Aligns the text to the left side of the rectangle.
DT_RIGHT Aligns the text to the right side of the rectangle.
DT_TOP Justifies the text to the top of the rectangle you select.
DT_BOTTOM Justifies the text to the bottom of the rectangle you select.  It only works when combined with DT_SINGLELINE
DT_VCENTER Justifies the text in the center of the rectangle.  It only works on single lines.
DT_WORDBREAK Lines are automatically broken between words when text reaches the end of a rectangle, thus adding an additional line.
[Close Table]

D3DCOLOR Color : 글자의 색상.

dxfont->DrawTextA(NULL,
                      "Hello World...FINALLY!",
                      22,
                      &textbox,
                      DT_CENTER | DT_VCENTER,
                      D3DCOLOR_ARGB(255, 255, 255, 255));

여기서 textbox는 전체 화면 사이즈 인듯.

3. The Finished Program

// include the basic windows header files and the Direct3D header file
#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>
#include <d3dx9.h>

// define the screen resolution and keyboard macros
#define SCREEN_WIDTH  640
#define SCREEN_HEIGHT 480
#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

// include the Direct3D Library file
#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")

// global declarations
LPDIRECT3D9 d3d;    // the pointer to our Direct3D interface
LPDIRECT3DDEVICE9 d3ddev;    // the pointer to the device class
LPD3DXFONT dxfont;    // the pointer to the font object

// function prototypes
void initD3D(HWND hWnd); // sets up and initializes Direct3D
void render_frame(void); // renders a single frame
void cleanD3D(void); // closes Direct3D and releases memory

// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);


// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{
    HWND hWnd;
    WNDCLASSEX wc;

    ZeroMemory(&wc, sizeof(WNDCLASSEX));

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = (WNDPROC)WindowProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.lpszClassName = L"WindowClass1";

    RegisterClassEx(&wc);

    hWnd = CreateWindowEx(NULL,
                          L"WindowClass1",
                          L"Our Direct3D Program",
                          WS_EX_TOPMOST | WS_POPUP,
                          0, 0,
                          SCREEN_WIDTH, SCREEN_HEIGHT,
                          NULL,
                          NULL,
                          hInstance,
                          NULL);

    ShowWindow(hWnd, nCmdShow);

    // set up and initialize Direct3D
    initD3D(hWnd);

    // enter the main loop:

    MSG msg;

    while(TRUE)
    {
        DWORD starting_point = GetTickCount();

        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT)
                break;

            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        render_frame();

        // check the 'escape' key
        if(KEY_DOWN(VK_ESCAPE))
            PostMessage(hWnd, WM_DESTROY, 0, 0);

        while ((GetTickCount() - starting_point) < 25);
    }

    // clean up DirectX and COM
    cleanD3D();

    return msg.wParam;
}


// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
        case WM_DESTROY:
            {
                PostQuitMessage(0);
                return 0;
            } break;
    }

    return DefWindowProc (hWnd, message, wParam, lParam);
}


// this function initializes and prepares Direct3D for use
void initD3D(HWND hWnd)
{
    d3d = Direct3DCreate9(D3D_SDK_VERSION);

    D3DPRESENT_PARAMETERS d3dpp;

    ZeroMemory(&d3dpp, sizeof(d3dpp));
    d3dpp.Windowed = FALSE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow = hWnd;
    d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
    d3dpp.BackBufferWidth = SCREEN_WIDTH;
    d3dpp.BackBufferHeight = SCREEN_HEIGHT;


    // create a device class using this information and the info from the d3dpp stuct
    d3d->CreateDevice(D3DADAPTER_DEFAULT,
                      D3DDEVTYPE_HAL,
                      hWnd,
                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                      &d3dpp,
                      &d3ddev);

    D3DXCreateFont(d3ddev,    // the D3D Device
                   30,    // font height of 30
                   0,    // default font width
                   FW_NORMAL,    // font weight
                   1,    // not using MipLevels
                   true,    // italic font
                   DEFAULT_CHARSET,    // default character set
                   OUT_DEFAULT_PRECIS,    // default OutputPrecision,
                   DEFAULT_QUALITY,    // default Quality
                   DEFAULT_PITCH | FF_DONTCARE,    // default pitch and family
                   L"Arial",    // use Facename Arial
                   &dxfont);    // the font object


    return;
}


// this is the function used to render a single frame
void render_frame(void)
{
    // clear the window to a deep blue
    d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);

    d3ddev->BeginScene();    // begins the 3D scene

    // create a RECT to contain the text
    static RECT textbox; SetRect(&textbox, 0, 0, 640, 480);

    // draw the Hello World text
    dxfont->DrawTextA(NULL,
                      "Hello World...FINALLY!",
                      22,
                      &textbox,
                      DT_CENTER | DT_VCENTER,
                      D3DCOLOR_ARGB(255, 255, 255, 255));

    d3ddev->EndScene();    // ends the 3D scene

    d3ddev->Present(NULL, NULL, NULL, NULL);

    return;
}


// this is the function that cleans up Direct3D and COM
void cleanD3D(void)
{
    d3ddev->Release();
    d3d->Release();

    return;
}



Image 1.1 - DirectGrid.png Displayed in DirectX

Image 2.5 - Hello World, DirectX Style
posted by 대갈장군