【问题标题】:Texture Scaling纹理缩放
【发布时间】:2014-01-24 02:47:33
【问题描述】:

使用 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 很陌生。

【问题讨论】:

    标签: c++ scaling directx-9 texture2d


    【解决方案1】:

    为了提高效率,通常要求纹理表面的维度是 2 的幂:例如64、512等 尽管不同的硬件以不同的方式实现光栅化,但处理纹理的单个像素将需要大量的乘法运算。例如,要处理图像中的纹素,您可以使用以下代码:

    texel = PixelDataArray[y * texture_width + x];
    

    但是,如果 'texture_width' 是 2 的幂,比如 256,那么会做同样的工作:

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

    实现硬件转换的优点是需要的硅更少,运行速度比乘法快得多。当您使用并行硬件每帧执行数百万次此类操作时,收益可能会非常显着。

    无论如何,结果是您必须保存具有二维幂的图像,然后,如果您想在该表面中使用剪切区域,请使用 UV 坐标执行此操作。

    【讨论】:

      猜你喜欢
      • 2012-01-28
      • 1970-01-01
      • 2018-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多