2014-01-24 116 views
0

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

回答

0

對於效率,紋理表面通常要求是2的冪次方:例如, 64,512等 雖然不同的硬件實現不同的光柵化,但尋址紋理的各個像素將需要大量的乘法。例如,爲了解決圖像中的紋理元素,你可以使用此代碼:

texel = PixelDataArray[y * texture_width + x]; 

但是,如果「texture_width」是二的冪,說256,然後再會做同樣的工作:

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

的優點在於,實現在硬件移位花費少了很多的硅可以操作比乘法快得多。當你使用並行硬件每幀執行數百萬次這樣的操作時,獲得的收益可能很大。

無論如何,結果是,你必須保存圖像與二維的電源,然後,如果你想那面中使用截取區域,做到這一點使用UV座標。