2017.08.24
装载位图,由于d3d本身不知道如何装载位图,所以我这次要用到d3dx9.h 和d3dx9.lib,但是查资料,VS2015本身的内置库的话是不包括d3dx9.h的,因为这个库属于工具库而非dx核心库,查找官方文档发现如果要用这个D3DX,就只能去下载d3d的sdk,官方的话是:
D3DX is not considered the canonical API for using Direct3D in Windows 8 and later and therefore isn't included with the corresponding Windows SDK.
于是就去下了DX的SDK,(安装的时候要退出vs),在项目的属性页->VC++目录->包含目录(Include)中添加上自己D3D安装的目录下的INCLUDE,在库目录下添加安装的DXSDK的LIB->X86,然后再在自己项目的头文件中添加
#include
#pragma comment(lib,"d3dx9.lib")
就能正确的使用这个库中提供的工具了。
今天先把环境配好,明天开始学习如何装载位图。
2017.08.25
今天学习如何装载位图
比较重要的函数是
HRESULT D3DXLoadSurfaceFromFile(
LPDIRECT3DSURFACE9 pDestSurface,
CONST PALETTEENTRY pDestPalette,
CONST RECT* pDestRect,
DWORD Filter,
D3DCOLOR ColorKey,
D3DXIMAGE_INFO* pSrcInfo
)
这个函数能够从指定文件中加载图像到指定表面(几乎所有静态图片格式)
还有就是利用
d3ddev->StretchRect(surface, NULL, backbuffer, NULL, D3DTEXF_NONE);
把图片拉伸成窗口大小,这样在改变窗口大小的同时图片大小也会改变,图片会一直填充窗口。
表面在创建的时候大小制定的稍微大一些,这样图片看起来就不会很模糊。
下面是代码:
#include
#include
#include
#include
using namespace std;
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
const string APPTITLE = "Direct3D_Windowed";
const int SCREEN_W = 1024;
const int SCREEN_H = 768;
const LPSTR FineNames[5] =
{
"D:\\Personal\\Documents\\My Pictures\\00eb096a08d184f145da2ca64b4b45e905d18c53.jpg",
"D:\\Personal\\Documents\\My Pictures\\i1XfcG5JX8KqO.jpg",
"D:\\Personal\\Documents\\My Pictures\\20151016033822677.jpg",
"D:\\Personal\\Documents\\My Pictures\\20150615122310_MYFPz.jpeg",
"D:\\Personal\\Documents\\My Pictures\\20130116175135_2C285 (1).jpeg"
};
int pictureIndex = 0;
//D3D设置
LPDIRECT3D9 d3d = NULL;
LPDIRECT3DDEVICE9 d3ddev = NULL;
LPDIRECT3DSURFACE9 backbuffer = NULL;
LPDIRECT3DSURFACE9 surface = NULL;
bool GameOver = false;
#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
//GameInit
bool Game_Init(HWND hwnd)
{
//初始化D3D
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (d3d == NULL)
{
MessageBox(hwnd, "Error Initialize D3D9", "ERROR", MB_OK);
return false;
}
//设置呈现参数
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferWidth = SCREEN_W;
d3dpp.BackBufferHeight = SCREEN_H;
d3dpp.hDeviceWindow = hwnd;
//创建D3D的设备
d3d->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev
);
if (d3ddev == NULL)
{
MessageBox(hwnd, "Error Create D3DDEV", "ERROR", MB_OK);
return false;
}
//清除缓冲区
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0F, 0);
//让backbuffer指向后台缓冲区
d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
//创建一个表面 surface指针指向这个表面
HRESULT hResult
= d3ddev->CreateOffscreenPlainSurface(
SCREEN_W, //表面的宽
SCREEN_H, //表面的高
D3DFMT_X8R8G8B8, //格式
D3DPOOL_DEFAULT, //所用的内存池
&surface, //表面的指针
NULL //预留
);
if (hResult != D3D_OK)
return false;
//加载图片
hResult = D3DXLoadSurfaceFromFile(
surface, //需要画图的表面
NULL, //调色板 ?
NULL, //矩形
FineNames[0],//源文件名字(路径)
NULL, //源矩形
D3DX_DEFAULT,//图片填充样式
0, //透明
NULL //图片信息(通常为NULL)
);
if (hResult != D3D_OK)
return false;
return true;
//初始化完成
return true;
}
void Game_Run(HWND hwnd)
{
if (KEY_DOWN(VK_ESCAPE))
{
PostMessage(hwnd, WM_DESTROY, 0, 0);
}
if (KEY_DOWN(VK_SPACE))
{
pictureIndex++;
if (pictureIndex >= 5)
pictureIndex = 0;
HRESULT hResult = D3DXLoadSurfaceFromFile(
surface,
NULL,
NULL,
FineNames[pictureIndex],
NULL,
D3DX_DEFAULT,
0,
NULL
);
}
if (!d3ddev)
return;
//开始渲染
if (d3ddev->BeginScene())
{
//在后台缓冲中画图并拉伸至屏幕
d3ddev->StretchRect(surface, NULL, backbuffer, NULL, D3DTEXF_NONE);
//停止渲染
d3ddev->EndScene();
//copy back buffer to the frame buffer
d3ddev->Present(NULL, NULL, NULL, NULL);
}
}
void Game_End(HWND hwnd)
{
if (d3ddev)
{
d3ddev->Release();
d3ddev = NULL;
}
if (d3d)
{
d3d->Release();
d3d = NULL;
}
}
//Win消息处理
LRESULT CALLBACK WinProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
//HWND:窗口句柄,使用窗口句柄创建一个新的设备环境句柄HDC,只要引用一个窗口或空间就必须得用到窗口句柄
switch (message)
{
case WM_DESTROY:
GameOver = true;
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevinstance, LPSTR lpCmdLine, int nCmdShow)
{
//set the new window properties
WNDCLASSEX wc;
MSG msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW; //在移动或尺寸更新完|高度调整后重新绘制
wc.lpfnWndProc = (WNDPROC)WinProc; //返回一个指向回调函数的指针,如果不设定这个值,消息就无法传递给HWND
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = "MainWindowClass";
wc.hIconSm = NULL;
if (!RegisterClassEx(&wc))
return FALSE;
//Create a Window
HWND hwnd = CreateWindow("MainWindowClass",
APPTITLE.c_str(),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
SCREEN_W, SCREEN_H,
(HWND)NULL,
(HMENU)NULL,
hInstance,
(LPVOID)NULL
);
if (hwnd == 0) //创建失败
return 0;
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
//初始化
if (!Game_Init(hwnd))
return 0;
while (!GameOver)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Game_Run(hwnd);
}
Game_End(hwnd);
return msg.wParam;
}
d3ddev->StretchRect(surface, NULL, backbuffer, NULL, D3DTEXF_NONE);
这句代码是将表面绘制到屏幕,而且是整个表面图片填充到窗口中。
如果添加
RECT rect;
rect.bottom = 510;
rect.top = 50;
rect.left = 50;
rect.right = 510;
d3ddev->StretchRect(surface, NULL, backbuffer, &rect, D3DTEXF_NONE);
则是将整个图片画在了这个矩形的区域内
而如果把代码改成
d3ddev->StretchRect(surface, &rect, backbuffer,NULL, D3DTEXF_NONE);
那么这句代码就只画了图片中矩形的一部分
如果想将表面创建的和图像一样大的话,则需要添加下面代码:
D3DXIMAGE_INFO imageInfo;
hResult = D3DXGetImageInfoFromFile(filename, &imageInfo);
HRESULT hResult
= d3ddev->CreateOffscreenPlainSurface(
imageInfo.Width, //表面的宽
imageInfo.Height, //表面的高
D3DFMT_X8R8G8B8, //格式D3DPOOL_DEFAULT, //所用的内存池&surface, //表面的指针NULL //预留);