纹理缩放

时间:2014-01-24 02:47:34

标签: c++ scaling directx-9 texture2d

使用Direct-X9,如何将纹理缩放到文件中的确切大小?

我在MSPaint中查看我的纹理,它的大小是261 x 210。它在MSPaint中显示正常。 但是,当我绘制纹理时,它会比平常大得多。即使我将缩放设置为0f,它也会因某种原因而拉长。

我的代码如下:

#if defined(UNICODE) && !defined(_UNICODE)
#define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
#define UNICODE
#endif

#include <tchar.h>
#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <d3dx9tex.h>

IDirect3D9* d3d = nullptr;
IDirect3DDevice9* device = nullptr;
IDirect3DTexture9* Texture = nullptr;
ID3DXSprite* Sprite = nullptr;

const int Width = 800;
const int Height = 600;

void init(HWND hwnd, IDirect3D9* &d3d, IDirect3DDevice9* &device, int Width, int Height);
void render(IDirect3DDevice9* device);
void cleanup(IDirect3D9* &d3d, IDirect3DDevice9* &device);
void LoadTexture(const char* FilePath, IDirect3DTexture9* &Texture, ID3DXSprite* &Sprite);
void LoadTexture(unsigned char* buffer, int width, int height, IDirect3DTexture9* &Texture, ID3DXSprite* &Sprite);


LRESULT __stdcall WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            break;

        default:
            return DefWindowProc(hwnd, message, wParam, lParam);
    }

    return 0;
}

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    MSG msg = {0};

    WNDCLASSEX wc =
    {
        sizeof(WNDCLASSEX), CS_VREDRAW | CS_HREDRAW | CS_OWNDC,
        WindowProcedure, 0, 0, hInstance, nullptr, nullptr, (HBRUSH)(COLOR_WINDOW+1),
        nullptr, _T("DXClass"), nullptr
    };

    if(RegisterClassEx(&wc))
    {
        HWND hwnd = CreateWindow(_T("DXClass"), _T("DirectX Window"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, Width, Height, nullptr, nullptr, hInstance, nullptr);
        ShowWindow(hwnd, nCmdShow);
        UpdateWindow(hwnd);
        init(hwnd, d3d, device, Width, Height);
        LoadTexture("C:/Users/School/Desktop/Test.bmp", Texture, Sprite);

        while(true)
        {
            while(PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }

            if(msg.message == WM_QUIT)
                break;

            render(device);
        }

        cleanup(d3d, device);
        return msg.wParam;
    }
    return 0;
}


void init(HWND hwnd, IDirect3D9* &d3d, IDirect3DDevice9* &device, int Width, int Height)
{
    d3d = Direct3DCreate9(D3D_SDK_VERSION);
    D3DPRESENT_PARAMETERS parameters = {0};
    ZeroMemory(&parameters, sizeof(parameters));
    parameters.Windowed = true;
    parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
    parameters.hDeviceWindow = hwnd;
    parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
    parameters.BackBufferWidth = Width;
    parameters.BackBufferHeight = Height;
    d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &parameters, &device);
}

void render(IDirect3DDevice9* device)
{
    device->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0);
    device->BeginScene();

    if (Sprite && Texture)
    {
        D3DXMATRIX world = {0}, rotation = {0}, scale = {0}, translation = {0};
        D3DXMatrixIdentity(&world);

        D3DXMatrixScaling(&scale, 1.0f, 1.0f, 1.0f);
        D3DXMatrixRotationYawPitchRoll(&rotation, 0.0f, 0.0f, 0.0f);
        D3DXMatrixTranslation(&translation, 0.0f, 0.0f, 0.0f);
        world = rotation * scale * translation;

        Sprite->SetTransform(&world);
        D3DXVECTOR3 Position = D3DXVECTOR3(0, 0, 0);

        Sprite->Begin(D3DXSPRITE_ALPHABLEND);
        Sprite->Draw(Texture, nullptr, nullptr, &Position, 0xFFFFFFFF);
        Sprite->End();
    }

    device->EndScene();
    device->Present(nullptr, nullptr, nullptr, nullptr);
}

void cleanup(IDirect3D9* &d3d, IDirect3DDevice9* &device)
{
    if (Sprite) Sprite->Release();
    if (Texture) Texture->Release();
    if (device) device->Release();
    if (d3d) d3d->Release();
}

void LoadTexture(const char* FilePath, IDirect3DTexture9* &Texture, ID3DXSprite* &Sprite)
{
    D3DXCreateTextureFromFile(device, FilePath, &Texture);
    D3DXCreateSprite(device, &Sprite);
}

void LoadTexture(unsigned char* buffer, int width, int height, IDirect3DTexture9* &Texture, ID3DXSprite* &Sprite)
{
    device->CreateTexture(width, height, 1, 0, D3DFMT_X8B8G8R8, D3DPOOL_MANAGED, &Texture, 0);
    D3DXCreateSprite(device, &Sprite);

    D3DLOCKED_RECT rect;
    Texture->LockRect(0, &rect, nullptr, D3DLOCK_DISCARD);
    unsigned char* dest = static_cast<unsigned char*>(rect.pBits);
    memcpy(dest, buffer, width * height * 4);
    Texture->UnlockRect(0);
}

有什么想法吗?另外,有没有更好的方法来绘制我的纹理?例如,也许没有精灵?我是Direct-X的新手。

1 个答案:

答案 0 :(得分:0)

为了提高效率,纹理表面的尺寸通常要求为2:例如64,512等    尽管不同的硬件以不同方式实现光栅化,但是对纹理的各个像素进行寻​​址将需要大量的乘法。例如,要处理图像中的纹理元素,可以使用以下代码:

texel = PixelDataArray[y * texture_width + x];

然而,如果&#39; texture_width&#39;是256的幂,比如说256,然后会做同样的工作:

int texture_width_shift_by = 8;
texel = PixelDataArray[y << texture_width_shift_by + x];

优势在于实现硬件转换需要更少的硅,其运行速度比乘法运行快得多。当您使用并行硬件每帧进行数百万次此类操作时,增益可能会很大。

无论如何,结果是你必须用二维的力量保存那个图像然后,如果你想在那个表面内使用一个被剪裁的区域,使用UV坐标来做这个。