Рисование текстуры шрифта (персонаж вверх ногами)

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 уже делает это?
  • 0
    Похоже, он не использует DirectX, а вместо этого использует TextOut. Я хочу использовать свою собственную функцию рисования.
Теги:
fonts
directx
directx-9

1 ответ

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 все ОК. Я не могу точно запомнить, как указать пользовательскую вершину, поэтому, наверное, мне повезло с вышеупомянутым взломом :)

Если бы еще один взгляд на это, и я думаю, что коорды должны быть заказаны, чтобы сделать TRIANGLEFAN в порядке по часовой стрелке (так что он не получает обратную поверхность). Переупорядочение коордов имеет смысл, я думаю:

// 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
    Просто вспомнил кое-что еще - у TRIANGLEFAN должен быть Порядок намотки по часовой стрелке, см. Выше

Ещё вопросы

Сообщество Overcoder
Наверх
Меню