您的位置:首页 > 其它

Directx9学习(七)初识texture(1)

2017-08-29 15:45 375 查看
2017.08.29

今天学习了texture的简单的使用,利用将texture画到sprite上来达到更高效的绘图,由于使用的sprite,那么在后面可以对sprite进行平移旋转缩放等操作,这些操作有的在表面上是做不到的。

表面surface的缺点:绘图较慢,不支持透明transparent

所以使用sprite还是比较好的选择

1.加载纹理texture:

声明纹理

LPDIRECT3DTEXTURE9 texture = NULL;
从位图文件读取分辨率数据:

D3DXIMAGE_INFO info;
HRESULT result = D3DXGetImageInfoFromFile(fileName.c_str(), &info);


从这里也可以得到图片的宽和高,可以存储在 D3DXVECTOR2类型的一个变量中

从位图文件中加载texture:使用D3DXCreateTextureFromFileEx直接将图片加载到纹理中

HRESULT WINAPI
D3DXCreateTextureFromFileExA(
LPDIRECT3DDEVICE9         pDevice,
LPCSTR                    pSrcFile,
UINT                      Width,
UINT                      Height,
UINT                      MipLevels,
DWORD                     Usage,
D3DFORMAT                 Format,
D3DPOOL                   Pool,
DWORD                     Filter,
DWORD                     MipFilter,
D3DCOLOR                  ColorKey,
D3DXIMAGE_INFO*           pSrcInfo,
PALETTEENTRY*             pPalette,
LPDIRECT3DTEXTURE9*       ppTexture);


2.对于透明的Sprite基本实用其alpha通道就可以

在有了纹理texture之后,需要从纹理绘制sprite道平哭上,因此需要sprite指针

LPD3DXSPRITE sprite = NULL;


然后再调用D3DXCreateSprite来初始化Sprite对象,将sprite处理器附着在D3D设备上,让他知道如何在后台缓冲区中绘制Sprite

HRESULT WINAPI
D3DXCreateSprite(
LPDIRECT3DDEVICE9   pDevice,
LPD3DXSPRITE*       ppSprite);


开始画吧!

首先需要锁住Sprite,使用Begin来开始绘画(其参数一般使用D3DXSPRITE_ALPHABLEND,支持透明),然后就可以从已有的texture中加载到Sprite上(Draw函数),最后调用End()来解锁

Draw函数:

HRESULT Draw(
LPDIRECT3DTEXTURE9 pTexture, 	//源图像纹理
CONST RECT *pSrcRect, 		//源图片的某一部分
CONST D3DXVECTOR3 *pCenter, 	//旋转发生的中心点
CONST D3DXVECTOR3 *pPosition, 	//sprite的绘制位置(在窗口的某个地方开始,图片的左上角为原点)
D3DCOLOR Color			//对色彩的变更,不影响透明度
)


顺序大致如下

if (d3ddev->BeginScene())
{
sprite->Begin(D3DXSPRITE_ALPHABLEND);  //锁住Sprite并开始绘制

sprite->Draw(texture, NULL, NULL, &vec3, D3DCOLOR_XRGB(255, 255, 255));

sprite->End();

d3ddev->EndScene();

d3ddev->Present(NULL, NULL, NULL, NULL); //交换后台到前台
}


基本的操作就是这么多,从texture绘制Sprite到窗口的基本操作就是这些。

注:

1.需要修改/添加d3dpp的一些设定,和之前写的几个程序不太一样

d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
d3dpp.EnableAutoDepthStencil = 1;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;


2.在没有缩放的情况下,原图多大,Sprite就画的多大,也就是说,

当我的图片是1680*1050,而我的窗口是1024*768的时候,我画出来的效果:



无论怎么去拉伸窗口(因为窗口已经定了就是那么大),图片都不会画成别的样子(全屏以后的图片,拉伸了但是没有画多)



如果把窗口的大小调成1680*1050,那么图片就能完整的画出来



如果图片比较小(我这里用了一张898*562的图片,窗口大小1024*768),他仍然不会拉伸



也就是说,在没有缩放的情况下,源图片有多大,则画到窗口上的就是多大,不会去像表面StretchRect一样适应屏幕

3.目前对于Draw中那个绘画position的理解:是图片左上角的位置而不是图片中心的位置

刚开始认为是图片中心的位置,于是就吧这个值写成了

D3DXVECTOR3 vec3(0.5*SCREENW,0.5*SCREENH,0);
sprite->Draw(texture, NULL, NULL, &vec3, D3DCOLOR_XRGB(255, 255, 255));


结果肯定是跑偏了



所以这个点(就目前所了解的知识来看)应该是图片的左上角(0,0)点的位置

把vector3改成0以后就正常了

D3DXVECTOR3 vec3(0,0,0);
sprite->Draw(texture, NULL, NULL, &vec3, D3DCOLOR_XRGB(255, 255, 255));



4.最后别忘了释放资源

sprite->Release();


最后是这次的主要代码:

//MyD3d.h
#pragma once
#include<iostream>
#include<windows.h>
#include<d3d9.h>
#include<d3dx9.h>

#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
using namespace std;

int SCREENW = 1024;
int SCREENH = 768;

LPDIRECT3D9 d3d;
LPDIRECT3DDEVICE9 d3ddev;
LPDIRECT3DSURFACE9 backbuffer = NULL;
LPDIRECT3DTEXTURE9 texture = NULL;
LPD3DXSPRITE sprite = NULL;
bool Direct3D_Init(HWND hwnd, int width, int height, bool fullscreen);
D3DXVECTOR2 GetImgSize(string fileName);
LPDIRECT3DTEXTURE9 LoadTexture(string fileName, D3DCOLOR transcolor);//加载位图到纹理
#include"MyD3d.h"
bool gameOver = false;
string imgPath = "D:\\Personal\\Documents\\My Pictures\\20151016033822677.jpg";
string imgAlphaPath = "E:\\Win32\\Win321\\MyFirstD3DGame\\Bucket.png";

LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lparam)
{
switch (msg)
{
case WM_DESTROY:
gameOver = true;
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, msg, wParam, lparam);

}

//Windows Entry point
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
//initialize window settings
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH
aef7
)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = "MainWindowClass";
wc.hIconSm = NULL;
RegisterClassEx(&wc);

//Create a new window
HWND window = CreateWindow(
"MainWindowClass",
"MainWindowClass",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
SCREENW, SCREENH,
NULL, NULL,
hInstance, NULL);
if (window == 0) //BUG??
return 0;
//display window
ShowWindow(window, nCmdShow);
UpdateWindow(window);

if (!Direct3D_Init(window, SCREENW, SCREENH, false))
return 0;

//main message loop
MSG message;
while (!gameOver)
{
if (PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
//process game loop

if (d3ddev->BeginScene())
{
sprite->Begin(D3DXSPRITE_ALPHABLEND); //锁住Sprite并开始绘制

//画 ,在没有缩放等变换之前 图片大小:如果是比窗口大的图片就只显示一部分(sprite大小和图片一样大),但如果是小图片的话就只会画出原始的,不会拉伸填充之类的
//总之,sprite多大,他就只会画多大的
D3DXVECTOR3 vec3(0,0,0); sprite->Draw(texture, NULL, NULL, &vec3, D3DCOLOR_XRGB(255, 255, 255));
//texture图源,图片单元(动画帧的矩形),旋转中心点,sprite位置(图片的左上角所在的位置而不是中心所在的位置),色彩变更(不影响透明度)

sprite->End();

d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL); //交换后台到前台
}

}

//shut down

sprite->Release();
d3ddev->Release();
d3d->Release();

return message.wParam;
}

bool Direct3D_Init(HWND hwnd, int width, int height, bool fullscreen)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (!d3d)
return false;

D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = (!fullscreen);
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight = height;
d3dpp.hDeviceWindow = hwnd;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; d3dpp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; d3dpp.EnableAutoDepthStencil = 1;

d3d->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev
);

if (!d3ddev)
return false;

d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);

texture = LoadTexture(imgPath, D3DCOLOR_XRGB(0,0,0));

//将sprite处理器附着在d3d设备上,以便他知道如何在后台缓冲区中绘制sprite
HRESULT result = D3DXCreateSprite(d3ddev, &sprite);

return true;
}

//得到图像大小(长宽)
D3DXVECTOR2 GetImgSize(string fileName)
{
D3DXIMAGE_INFO info; HRESULT result = D3DXGetImageInfoFromFile(fileName.c_str(), &info);
D3DXVECTOR2 size = D3DXVECTOR2((float)info.Width, (float)info.Height);
return size;
}

//加载贴图
LPDIRECT3DTEXTURE9 LoadTexture(string fileName, D3DCOLOR transcolor)
{
LPDIRECT3DTEXTURE9 tex = NULL;
D3DXIMAGE_INFO info; HRESULT result = D3DXGetImageInfoFromFile(fileName.c_str(), &info);
if (result != D3D_OK)
return NULL;
//create a new texture by loading a bitmap img file
result = D3DXCreateTextureFromFileEx(
d3ddev, //d3d device obj
fileName.c_str(), // bitmap filename
info.Width, //bitmap img width
info.Height, //bitmap img height
1, //mip-map levels(1 for no chain)
D3DPOOL_DEFAULT, //type of surface
D3DFMT_UNKNOWN, //surface format
D3DPOOL_DEFAULT, //memory class for the texture
D3DX_DEFAULT, //img filter
D3DX_DEFAULT, //mip filter
transcolor, //color key for transparency
&info, //bitmap file info
NULL, //color palette
&tex //destination tex
);

if (result != D3D_OK)
return NULL;

return tex;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  DirectX9