2014-01-24 184 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坐标。