2014-02-19 90 views
0

我想紋理一個帶字符的字形,這是在字形紋理內(用D3DXFont :: GetGlyphData獲得)。繪製字體紋理(字符顛倒)

大部分字符繪製正確。

然而,諸如'F'和'A'這樣的字符正在被上下顛倒。

保存到文件中的字形似乎都沒有倒過來。

#include <Windows.h> 
#include <d3d9.h> 
#include <d3dx9.h> 

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

ID3DXSprite* pSprite; 
ID3DXFont* pFont; 

void drawCharacter(const char c, int screenX, int screenY, D3DCOLOR color) 
{ 
    struct CUSTOMVERTEX 
    { 
     float x, y, z, rhw, tu, tv; 
    }; 

    WORD glyphIndex; 
    IDirect3DTexture9* texture; 
    RECT rect; 
    POINT point; 
    D3DSURFACE_DESC desc; 

    if(GetGlyphIndices(pFont->GetDC(), &c, 1, &glyphIndex, GGI_MARK_NONEXISTING_GLYPHS) == GDI_ERROR) 
     return; 

    if(pFont->GetGlyphData(glyphIndex, &texture, &rect, &point) != S_OK) 
     return; 

    if(texture->GetLevelDesc(0, &desc) != D3D_OK) 
     return; 

    const float glyphWidth = static_cast<float>(desc.Width); 
    const float glyphHeight = static_cast<float>(desc.Height); 

    const float charWidth = static_cast<float>(rect.right - rect.left); 
    const float charHeight = static_cast<float>(rect.bottom - rect.top); 

    const float startX = static_cast<float>(screenY); 
    const float startY = static_cast<float>(screenY); 

    float u = (static_cast<float>(rect.left) + 0.5f)/glyphWidth; 
    float v = (static_cast<float>(rect.top) + 0.5f)/glyphHeight; 

    float u2 = u + (charWidth/glyphWidth); 
    float v2 = v + (charHeight/glyphHeight); 

const CUSTOMVERTEX char_quad[4] = 
{ 
    // Bottom left vertex 
    { 
     startX, startY, 0.0f, 1.0f, 
     u, v2 
    }, 

    // Bottom right vertex 
    { 
     startX + charWidth, startY, 0.0f, 1.0f, 
     u2, v2 
    }, 

    // Top right vertex 
    { 
     startX + charWidth, startY + charHeight, 0.0f, 1.0f, 
     u2, v 
    }, 

    // Top left vertex 
    { 
     startX, startY + charHeight, 0.0f, 1.0f, 
     u, v 
    } 
}; 

    // D3DXSaveTextureToFileA("glyph.dds", D3DXIFF_DDS, texture, 0); 

    d3ddev->SetTexture(0, texture); 
    d3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, char_quad, sizeof(CUSTOMVERTEX)); 
} 

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

    d3ddev->BeginScene(); 
    pSprite->Begin(D3DXSPRITE_ALPHABLEND); 

    // select which vertex format we are using 
    d3ddev->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); 

    drawCharacter('F', 100, 100, D3DCOLOR_XRGB(0, 255, 0)); 

    pSprite->End(); 
    d3ddev->EndScene(); 
    d3ddev->Present(NULL, NULL, NULL, NULL); 
} 

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

    wc.cbSize = sizeof(WNDCLASSEX); 
    wc.style = CS_HREDRAW | CS_VREDRAW; 
    wc.lpfnWndProc = DefWindowProc; 
    wc.hInstance = hInstance; 
    wc.hCursor = LoadCursor(NULL, IDC_ARROW); 
    wc.lpszClassName = "WindowClass"; 

    if(!RegisterClassEx(&wc)) 
    { 
     return 0; 
    } 

    hWnd = CreateWindowEx(NULL, 
     "WindowClass", 
     "Our Direct3D Program", 
     WS_OVERLAPPEDWINDOW, 
     0, 0, 
     800, 600, 
     NULL, 
     NULL, 
     hInstance, 
     NULL); 

    if(!hWnd) 
    { 
     UnregisterClass(wc.lpszClassName, hInstance); 
     return 0; 
    } 

    ShowWindow(hWnd, nCmdShow); 

    // set up and initialize Direct3D 
    d3d = Direct3DCreate9(D3D_SDK_VERSION); 

    if(!d3d) 
    { 
     UnregisterClass(wc.lpszClassName, hInstance); 
     return 0; 
    } 

    D3DPRESENT_PARAMETERS d3dpp = {}; 
    d3dpp.Windowed = TRUE; 
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; 
    d3dpp.hDeviceWindow = hWnd; 
    d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; 
    d3dpp.BackBufferWidth = 800; 
    d3dpp.BackBufferHeight = 600; 

    // create a device class using this information and the info from the d3dpp stuct 
    if(d3d->CreateDevice(D3DADAPTER_DEFAULT, 
     D3DDEVTYPE_HAL, 
     hWnd, 
     D3DCREATE_SOFTWARE_VERTEXPROCESSING, 
     &d3dpp, 
     &d3ddev) != D3D_OK) 
    { 
     d3d->Release(); 
     UnregisterClass(wc.lpszClassName, hInstance); 
     return 0; 
    } 

    if(D3DXCreateSprite(d3ddev, &pSprite) != D3D_OK) 
    { 
     d3d->Release(); 
     d3ddev->Release(); 
     UnregisterClass(wc.lpszClassName, hInstance); 
     return 0; 
    } 

    if(D3D_OK != D3DXCreateFont(d3ddev, 
      14, 
      0, 
      FW_BOLD, 
      1, 
      FALSE, 
      DEFAULT_CHARSET, 
      OUT_DEFAULT_PRECIS, 
      ANTIALIASED_QUALITY, 
      DEFAULT_PITCH | FF_DONTCARE, 
      "Georgia", 
      &pFont)) 
    { 
     d3d->Release(); 
     d3ddev->Release(); 
     pSprite->Release(); 
     UnregisterClass(wc.lpszClassName, hInstance); 
     return 0; 
    } 

    MSG msg; 
    while(TRUE) 
    { 
     while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
     { 
      TranslateMessage(&msg); 
      DispatchMessage(&msg); 
     } 

     if(msg.message == WM_QUIT) 
      break; 

     render_frame(); 
    } 

    d3d->Release(); 
    d3ddev->Release(); 
    pSprite->Release(); 
    pFont->Release(); 
    UnregisterClass(wc.lpszClassName, hInstance); 
    return msg.wParam; 
} 

編輯:更新,包括我的問題的一個完整的例子。

+0

只是看看你的代碼,不[FontGen(http://dhpoware.com/source/tools_fontgen.html)已經做到這一點? – Proxy

+0

看起來它不使用directX,而是使用TextOut。我想用我自己的繪圖功能。 – user1052842

回答

0

自從我做了任何DirextX的東西,這已經有一段時間了,但我認爲它可能與四紋理座標排序有關。我跑你的代碼,並試圖此:

const CUSTOMVERTEX char_quad[4] = 
{ 
    // Top left vertex 
    { 
     startX, startY + charHeight, 0.0f, 1.0f, 
     u, v2 
    }, 
    // Top right vertex 
    { 
     startX + charWidth, startY + charHeight, 0.0f, 1.0f, 
     u2, v2 
    }, 
    // Bottom right vertex 
    { 
     startX + charWidth, startY, 0.0f, 1.0f, 
     u2, v 
    }, 
    // Bottom left vertex 
    { 
     startX, startY, 0.0f, 1.0f, 
     u, v 
    } 
}; 

其輸出的字符ABCDEF一切ok。 我不能確切地記得如何指定自定義頂點,所以我想我可能是幸運的與上面的黑客:)

再看看這個,我認爲應該命令coords應呈現順時針方向的三角帆繞組順序(所以它沒有得到背面剔除)。重新排序COORDS更有意義,我認爲:

// TRIANGLEFAN coords: 
// v1-----v2 clockwise winding order 
// | /| 
// |/ | 
// v0-----v3 
// 
const CUSTOMVERTEX char_quad[4] = 
{ 
    // Bottom left vertex 
    { 
     startX, startY, 0.0f, 1.0f, 
     u, v 
    }, 
    // Top left vertex 
    { 
     startX, startY + charHeight, 0.0f, 1.0f, 
     u, v2 
    }, 
    // Top right vertex 
    { 
     startX + charWidth, startY + charHeight, 0.0f, 1.0f, 
     u2, v2 
    }, 
    // Bottom right vertex 
    { 
     startX + charWidth, startY, 0.0f, 1.0f, 
     u2, v 
    }, 
}; 
+0

只記得別的東西 - 三角帆應該有順時針卷繞順序,見上面的編輯 – TonyWilk