Используя 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(¶meters, 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, ¶meters, &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.
Для эффективности текстурные поверхности обычно должны иметь степень 2 по размерам: например, 64, 512 и т. Д.
Хотя различные аппаратные средства по-разному реализуют растеризацию, адресация отдельных пикселей текстуры потребует значительного умножения. Например, для адресации texel на изображении, вы можете использовать этот код:
texel = PixelDataArray[y * texture_width + x];
однако, если ‘texture_width’ является степенью двойки, скажем, 256, то тогда будет делать ту же работу:
int texture_width_shift_by = 8;
texel = PixelDataArray[y << texture_width_shift_by + x];
Преимущество заключается в том, что для внедрения аппаратного сдвига требуется гораздо меньше кремния, он может работать намного быстрее, чем умножение. Когда вы выполняете миллионы таких операций в каждом кадре с использованием параллельного оборудования, выигрыш может быть значительным.
В любом случае, в результате вы должны сохранить это изображение с силой двух измерений, а затем, если вы хотите использовать обрезанную область на этой поверхности, сделать это с помощью UV-координат.
Других решений пока нет …