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

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)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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值