Direct3D学习手记五:纹理映射

本文介绍纹理映射:将2D图像映射到3D物体上

纹理坐标:

使用纹理映射将图片贴到3D物体表面必须物体的顶点指定纹理坐标,最多指定8级纹理坐标,本次我们只使用一级

可以像以下方式定义定点格式:

//自定义顶点格式
typedef struct VERTEX
{
	FLOAT	_x,_y,_z;//三维坐标
	FLOAT	_u,_v;//纹理坐标,一级纹理
	VERTEX(FLOAT x,FLOAT y,FLOAT z,FLOAT u,FLOAT v)
		:_x(x),_y(y),_z(z),_u(u),_v(v){}
	const static DWORD FVF;//格式
}VERTEX;
const DWORD VERTEX::FVF=D3DFVF_XYZ|D3DFVF_TEX1;

纹理坐标中u表示横向,v表示纵向,u,v >=0(可以理解为横向和纵向的重复次数):

如下图所示,四个顶点的纹理坐标分别为(0,0)、(2,0)、(2,2)、(0,2),就会在一个表面横向重复两次,纵向重复两次


另外,在创建顶点时,由于一个点在不同的面的纹理坐标可能不同,所以在创建顶点缓存时,所创建的顶点数=一个面的顶点数 x 面数

例如要创建立方体,则需创建 6面 x 4个/面 = 24个顶点,而不再是8个顶点,如下所示:

//创建与初始化顶点缓存,这里我们绘制一个立方体
	hr=g_pd3dDevice->CreateVertexBuffer(24*sizeof(VERTEX),//缓存大小,字节数
														0,
														VERTEX::FVF,//顶点格式
														D3DPOOL_DEFAULT,//内存池,让系统设置
														&g_pVertexBuffer,//缓存指针
														NULL);
	if(FAILED(hr))
		return FALSE;
	//向顶点缓存中写入顶点数据
	VERTEX	* pVertices=NULL;
	g_pVertexBuffer->Lock(0,0,(void **)&pVertices,0);//对缓存加锁,数据同步

	pVertices[0]=VERTEX(-1.0F,1.0F,1.0F,0.0F,0.0F);//上面
	pVertices[1]=VERTEX(1.0F,1.0F,1.0F,2.0F,0.0F);
	pVertices[2]=VERTEX(1.0F,1.0F,-1.0F,2.0F,2.0F);
	pVertices[3]=VERTEX(-1.0F,1.0F,-1.0F,0.0F,2.0F);

	pVertices[4]=VERTEX(-1.0F,-1.0F,1.0F,0.0F,0.0F);//下面
	pVertices[5]=VERTEX(1.0F,-1.0F,1.0F,2.0F,0.0F);
	pVertices[6]=VERTEX(1.0F,-1.0F,-1.0F,2.0F,1.0F);
	pVertices[7]=VERTEX(-1.0F,-1.0F,-1.0F,0.0F,1.0F);

	pVertices[8]=VERTEX(-1.0F,1.0F,1.0F,0.0F,0.0F);//左面
	pVertices[9]=VERTEX(-1.0F,1.0F,-1.0F,3.0F,0.0F);
	pVertices[10]=VERTEX(-1.0F,-1.0F,-1.0F,3.0F,3.0F);
	pVertices[11]=VERTEX(-1.0F,-1.0F,1.0F,0.0F,3.0F);

	pVertices[12]=VERTEX(1.0F,1.0F,-1.0F,0.0F,0.0F);//右面
	pVertices[13]=VERTEX(1.0F,1.0F,1.0F,3.0F,0.0F);
	pVertices[14]=VERTEX(1.0F,-1.0F,1.0F,3.0F,2.0F);
	pVertices[15]=VERTEX(1.0F,-1.0F,-1.0F,0.0F,2.0F);

	pVertices[16]=VERTEX(-1.0F,1.0F,-1.0F,0.0F,0.0F);//前面
	pVertices[17]=VERTEX(1.0F,1.0F,-1.0F,1.0F,0.0F);
	pVertices[18]=VERTEX(1.0F,-1.0F,-1.0F,1.0F,1.0F);
	pVertices[19]=VERTEX(-1.0F,-1.0F,-1.0F,0.0F,1.0F);

	pVertices[20]=VERTEX(-1.0F,1.0F,1.0F,0.0F,0.0F);//后面
	pVertices[21]=VERTEX(1.0F,1.0F,1.0F,2.0F,0.0F);
	pVertices[22]=VERTEX(1.0F,-1.0F,1.0F,2.0F,3.0F);
	pVertices[23]=VERTEX(-1.0F,-1.0F,1.0F,0.0F,3.0F);

	g_pVertexBuffer->Unlock();//解锁

在设置索引缓存数据时,可以使用的索引为0到23:

//向索引缓存中写入顶点的索引
	WORD * dwIndex=NULL;
	g_pIndexBuffer->Lock(0,0,(void **)&dwIndex,0);//加锁
	//能看见的面要用顺时针,不能看见的面用逆时针
	
	dwIndex[0]=0,dwIndex[1]=1,dwIndex[2]=2;
	dwIndex[3]=0,dwIndex[4]=2,dwIndex[5]=3;//上面,顺

	dwIndex[6]=4,dwIndex[7]=7,dwIndex[8]=6;
	dwIndex[9]=4,dwIndex[10]=6,dwIndex[11]=5;//下面,逆

	dwIndex[12]=8,dwIndex[13]=9,dwIndex[14]=10;
	dwIndex[15]=8,dwIndex[16]=10,dwIndex[17]=11;//左侧面,逆

	dwIndex[18]=12,dwIndex[19]=13,dwIndex[20]=14;
	dwIndex[21]=12,dwIndex[22]=14,dwIndex[23]=15;//右侧面,顺

	dwIndex[24]=16,dwIndex[25]=17,dwIndex[26]=18;
	dwIndex[27]=16,dwIndex[28]=18,dwIndex[29]=19;//前面,顺

	dwIndex[30]=20,dwIndex[31]=23,dwIndex[32]=22;
	dwIndex[33]=20,dwIndex[34]=22,dwIndex[35]=21;//后面,逆

	g_pIndexBuffer->Unlock();//解锁


纹理寻址模式:

如果u和v在[0,1]的范围内则不需要考虑纹理寻址模式,即一张图片足够贴完物体的一个表面

但是当u或v大于1时,就不足以覆盖一个表面,就需要设置纹理寻址模式,不同的模式对应不同的贴图方式

使用函数SetSamplerState设置(要使用两次分别对u和v方向分别设置):

SetSamplerState(0,D3DSAMP_ADDRESSU,modeu)

SetSamplerState(0,D3DSAMP_ADDRESSV,modev)


1.重复寻址模式D3DTADDRESS_WRAP

SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_WRAP)

SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_WRAP)



2.镜像寻址模式D3DTADDRESS_MIRROR

SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_MIRROR)

SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_MIRROR)



3.夹取寻址模式D3DTADDRESS_CLAMP

首先对[0,1]的范围内应用一次纹理,对于其余的部分,则使用纹理的边缘像素填充

SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_CLAMP)

SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_CLAMP)



4.边框寻址模式D3DTADDRESS_BORDER

首先对[0,1]的范围内应用一次纹理,对于其余的部分,则使用纹理的边框颜色填充

SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_BORDER)

SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_BORDER)




创建纹理:

纹理的创建有两种方式,一是直接创建用D3DXCreateTexture函数,二是从一个图片文件中创建纹理用D3DXCreateTextureFromFile,其中方式二最常用

HRESULT D3DXCreateTextureFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, LPDIRECT3DTEXTURE9 * ppTexture);

pDevice为设备指针,pSrcFile为图片文件,ppTexture为存储纹理的IDirect3DTexture9接口对象指针

//加载贴图图片
	D3DXCreateTextureFromFile(g_pd3dDevice,TEXT("Demo_05_Media\\texture1.jpg"),&g_pTexture1);
	D3DXCreateTextureFromFile(g_pd3dDevice,TEXT("Demo_05_Media\\texture2.jpg"),&g_pTexture2);
	D3DXCreateTextureFromFile(g_pd3dDevice,TEXT("Demo_05_Media\\texture3.jpg"),&g_pTexture3);
	D3DXCreateTextureFromFile(g_pd3dDevice,TEXT("Demo_05_Media\\texture4.jpg"),&g_pTexture4);


使用纹理:

HRESULT SetTexture( DWORD Stage, IDirect3DBaseTexture9 * pTexture);

Stage指定使用的纹理的层数(最多为8层,Stage为0到7)

pTexture即为将要启用的IDirect3DTexture9接口对象

设置完纹理即可进行绘制。

g_pd3dDevice->SetTexture(0,g_pTexture1);
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,24,0,12);//8个顶点,12个三角形


纹理过滤

Direct3D将图元绘制到二维屏幕上时,如果图元有对应的纹理,则必须计算其纹理像素,这个过程就叫纹理过滤。

贴图时可能因为图片过大或过小而产生放大缩小现象,会造成图像的失真,解决该问题的方式有四种,

最常用的也是性价比最高的方式是:线性纹理过滤

使用如下方式设置:

g_pd3dDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
	g_pd3dDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);

同时可以采用多级渐进纹理过滤:

g_pd3dDevice->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR);//多级渐进过滤
	g_pd3dDevice->SetSamplerState(0,D3DSAMP_MAXMIPLEVEL,2);//最大映射级别,设为2,默认为0,最大为16

程序源代码:

(函数的声明单独放在了Common.h文件中,这里只贴出函数的实现)

/***************************************************************
*	Demo_04	:	纹理贴图
***************************************************************
*	FileName	:	main.cpp
*	Author		:	Anonymous
*	Time			:	2013/12/24
***************************************************************/
#include "Common.h"
#include "resource.h"

//释放COM接口对象的宏
#define		SAFE_RELEASE(p)	\
do												\
{													\
	if(p)											\
	{												\
		(p)->Release();						\
		(p)=NULL;							\
	}												\
}while(0);

//全局变量
HWND									g_hWnd=NULL;//窗口句柄
LPTSTR									g_pszClassName=TEXT("Demo_04");//类名
LPTSTR									g_pszWindowName=TEXT("Demo_04	:	纹理贴图");//窗口标题
const int									g_nWidth=1000;//窗口宽度
const int									g_nHeight=700;//窗口高度

LPDIRECT3DDEVICE9			g_pd3dDevice=NULL;//IDirect3DDevice9接口对象,用它绘制场景及其他操作
LPDIRECT3DTEXTURE9		g_pTexture1=NULL;//IDirect3DTexture9接口对象,用它保存纹理贴图
LPDIRECT3DTEXTURE9		g_pTexture2=NULL;
LPDIRECT3DTEXTURE9		g_pTexture3=NULL;
LPDIRECT3DTEXTURE9		g_pTexture4=NULL;

//自定义顶点格式
typedef struct VERTEX
{
	FLOAT	_x,_y,_z;//三维坐标
	FLOAT	_u,_v;//纹理坐标,一级纹理
	VERTEX(FLOAT x,FLOAT y,FLOAT z,FLOAT u,FLOAT v)
		:_x(x),_y(y),_z(z),_u(u),_v(v){}
	const static DWORD FVF;//格式
}VERTEX;
const DWORD VERTEX::FVF=D3DFVF_XYZ|D3DFVF_TEX1;

//全局资源
LPDIRECT3DVERTEXBUFFER9		g_pVertexBuffer=NULL;//顶点缓存
LPDIRECT3DINDEXBUFFER9			g_pIndexBuffer=NULL;//索引缓存

//窗口过程
LRESULT	CALLBACK	WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
	switch(msg)
	{
	case WM_PAINT:
		Render();
		ValidateRect(hWnd,NULL);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	case WM_KEYDOWN:
		if(VK_ESCAPE==wParam)
			DestroyWindow(hWnd);
		break;
	}
	return DefWindowProc(hWnd,msg,wParam,lParam);
}
//程序主函数,入口点
int WINAPI	WinMain(HINSTANCE hInstance,HINSTANCE hPreInstance,LPSTR pszCmdLine,int nCmdShow)
{
	//Step 1	:	注册窗口类,创建窗口,创建设备
	if(!InitDirect3D(hInstance,g_nWidth,g_nHeight,TRUE))
		return 0;

	//Step 2	:	创建与初始化资源、缓存、变换等
	if(!Setup(g_hWnd))
	{
		SAFE_RELEASE(g_pd3dDevice);
		return 0;
	}

	//Step 3	:	游戏循环
	GameLoop();

	//Step 4	:	游戏退出,清理
	Cleanup();
	UnregisterClass(g_pszClassName,hInstance);
	return 0;
}

/****************************************************************
*函数名	:	InitDirect3D
*功能		:	注册窗口类,创建程序窗口,创建IDirect3DDevice9接口对象
*输入		:	hInstance:程序实例句柄,
*					nWidth:窗口宽度,nHeight:窗口高度,
*					bWindowed:窗口模式还是全屏模式
*输出		:	无
*返回值	:	成功:TRUE		失败:FALSE
****************************************************************/
BOOL			InitDirect3D(HINSTANCE hInstance,int nWidth,int nHeight,BOOL bWindowed)
{
	HINSTANCE hInst=hInstance;
	if(NULL==hInst)
		hInst=GetModuleHandle(NULL);//如果hInstance为NULL,则得到当前程序的实例句柄

	/********** 	Step 1	:	注册窗口类	**************/
	WNDCLASS	wndcls;//窗口类
	wndcls.cbClsExtra=0;
	wndcls.cbWndExtra=0;
	wndcls.hbrBackground=(HBRUSH)GetStockObject(GRAY_BRUSH);//使用系统自带的灰色画刷
	wndcls.hCursor=LoadCursor(hInst,MAKEINTRESOURCE(IDC_MAIN_CURSOR));//设置光标
	wndcls.hIcon=LoadIcon(hInst,MAKEINTRESOURCE(IDI_MAIN_ICON));//设置图标
	wndcls.hInstance=hInst;
	wndcls.lpfnWndProc=WndProc;//设置窗口过程,用于处理各种消息
	wndcls.lpszClassName=g_pszClassName;//窗口类名
	wndcls.lpszMenuName=NULL;
	wndcls.style=CS_VREDRAW|CS_HREDRAW;

	//注册窗口类,失败返回FALSE
	if(!RegisterClass(&wndcls))
		return FALSE;

	/********** 	Step 2	:	创建窗口	**************/
	g_hWnd=CreateWindow(g_pszClassName,//类名
													g_pszWindowName,//窗口标题
													WS_OVERLAPPEDWINDOW,//风格
													200,//左上角点的横坐标
													10,//左上角点的纵坐标
													nWidth,//窗口宽度
													nHeight,//窗口高度
													NULL,//父窗口实例句柄
													NULL,//菜单句柄
													hInst,//实例句柄
													NULL);
	//判断窗口是否创建成功
	if(NULL==g_hWnd)
	{
		UnregisterClass(g_pszClassName,hInst);
		return FALSE;
	}

	/********** 	Step 3	:	创建IDirect3DDevice9接口对象		**************/
	//Step 3.1 : 创建IDirect3D9 接口对象
	LPDIRECT3D9	pD3D=NULL;
	pD3D=Direct3DCreate9(D3D_SDK_VERSION);
	if(NULL==pD3D)//创建失败
	{
		UnregisterClass(g_pszClassName,hInst);
		return FALSE;
	}

	//Step 3.2 : 获取设备性能信息,设置顶点处理方式:软件or硬件
	D3DCAPS9 caps;
	int vp=0;//顶点处理方式
	if(FAILED(pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,&caps)))
	{
		SAFE_RELEASE(pD3D);
		return FALSE;
	}
	if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)//判断设备是否支持硬件顶点处理(转换和光照)
		vp=D3DCREATE_HARDWARE_VERTEXPROCESSING;//硬件处理
	else
		vp=D3DCREATE_SOFTWARE_VERTEXPROCESSING;//软件处理

	//Step 3.3 : 初始化创建设备的参数
	D3DPRESENT_PARAMETERS d3dpp;
	d3dpp.AutoDepthStencilFormat=D3DFMT_D24S8;//24位深度缓存,8位模板缓存
	d3dpp.BackBufferCount=1;//后台缓存数
	d3dpp.BackBufferFormat=D3DFMT_A8R8G8B8;//后台缓存像素点格式
	d3dpp.BackBufferHeight=nHeight;//后台缓存高度(像素)
	d3dpp.BackBufferWidth=nWidth;//宽度
	d3dpp.EnableAutoDepthStencil=true;//自动管理深度缓存和模板缓存
	d3dpp.Flags=0;//其他标识
	d3dpp.FullScreen_RefreshRateInHz=D3DPRESENT_RATE_DEFAULT;//刷新频率
	d3dpp.hDeviceWindow=g_hWnd;//要绘制的窗口句柄
	d3dpp.MultiSampleQuality=0;//多重采样质量
	d3dpp.MultiSampleType=D3DMULTISAMPLE_NONE;//多重采样设为无
	d3dpp.PresentationInterval=D3DPRESENT_INTERVAL_IMMEDIATE;//立即提交/交换
	d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;//交换时销毁缓存
	d3dpp.Windowed=bWindowed;//窗口模式还是全屏模式

	//Step 3.4 : 创建设备
	if(FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,g_hWnd,vp,&d3dpp,&g_pd3dDevice)))
	{
		SAFE_RELEASE(pD3D);
		return FALSE;
	}

	SAFE_RELEASE(pD3D);
	return TRUE;
}

/****************************************************************
*函数名	:	Setup
*功能		:	创建与初始化资源、缓存、变换等
*输入		:	hWnd:窗口句柄
*输出		:	无
*返回值	:	成功:TRUE		失败:FALSE
****************************************************************/
BOOL			Setup(HWND hWnd)
{
	if(NULL==hWnd)
		return FALSE;
	HRESULT hr=E_FAIL;
	//创建与初始化顶点缓存,这里我们绘制一个立方体
	hr=g_pd3dDevice->CreateVertexBuffer(24*sizeof(VERTEX),//缓存大小,字节数
														0,
														VERTEX::FVF,//顶点格式
														D3DPOOL_DEFAULT,//内存池,让系统设置
														&g_pVertexBuffer,//缓存指针
														NULL);
	if(FAILED(hr))
		return FALSE;
	//向顶点缓存中写入顶点数据
	VERTEX	* pVertices=NULL;
	g_pVertexBuffer->Lock(0,0,(void **)&pVertices,0);//对缓存加锁,数据同步

	pVertices[0]=VERTEX(-1.0F,1.0F,1.0F,0.0F,0.0F);//上面
	pVertices[1]=VERTEX(1.0F,1.0F,1.0F,2.0F,0.0F);
	pVertices[2]=VERTEX(1.0F,1.0F,-1.0F,2.0F,2.0F);
	pVertices[3]=VERTEX(-1.0F,1.0F,-1.0F,0.0F,2.0F);

	pVertices[4]=VERTEX(-1.0F,-1.0F,1.0F,0.0F,0.0F);//下面
	pVertices[5]=VERTEX(1.0F,-1.0F,1.0F,2.0F,0.0F);
	pVertices[6]=VERTEX(1.0F,-1.0F,-1.0F,2.0F,1.0F);
	pVertices[7]=VERTEX(-1.0F,-1.0F,-1.0F,0.0F,1.0F);

	pVertices[8]=VERTEX(-1.0F,1.0F,1.0F,0.0F,0.0F);//左面
	pVertices[9]=VERTEX(-1.0F,1.0F,-1.0F,3.0F,0.0F);
	pVertices[10]=VERTEX(-1.0F,-1.0F,-1.0F,3.0F,3.0F);
	pVertices[11]=VERTEX(-1.0F,-1.0F,1.0F,0.0F,3.0F);

	pVertices[12]=VERTEX(1.0F,1.0F,-1.0F,0.0F,0.0F);//右面
	pVertices[13]=VERTEX(1.0F,1.0F,1.0F,3.0F,0.0F);
	pVertices[14]=VERTEX(1.0F,-1.0F,1.0F,3.0F,2.0F);
	pVertices[15]=VERTEX(1.0F,-1.0F,-1.0F,0.0F,2.0F);

	pVertices[16]=VERTEX(-1.0F,1.0F,-1.0F,0.0F,0.0F);//前面
	pVertices[17]=VERTEX(1.0F,1.0F,-1.0F,1.0F,0.0F);
	pVertices[18]=VERTEX(1.0F,-1.0F,-1.0F,1.0F,1.0F);
	pVertices[19]=VERTEX(-1.0F,-1.0F,-1.0F,0.0F,1.0F);

	pVertices[20]=VERTEX(-1.0F,1.0F,1.0F,0.0F,0.0F);//后面
	pVertices[21]=VERTEX(1.0F,1.0F,1.0F,2.0F,0.0F);
	pVertices[22]=VERTEX(1.0F,-1.0F,1.0F,2.0F,3.0F);
	pVertices[23]=VERTEX(-1.0F,-1.0F,1.0F,0.0F,3.0F);

	g_pVertexBuffer->Unlock();//解锁

	//创建与初始化索引缓存,立方体,6个面,要绘制12个三角形,需要12x3=36个索引
	hr=g_pd3dDevice->CreateIndexBuffer(36*sizeof(WORD),//缓存大小,字节为单位,一个索引占用2个字节(WORD)
																0,
																D3DFMT_INDEX16,//索引类型,使用16位的WORD格式
																D3DPOOL_DEFAULT,//内存池
																&g_pIndexBuffer,//索引缓存地址
																NULL);
	if(FAILED(hr))
	{
		SAFE_RELEASE(g_pVertexBuffer);
		return FALSE;
	}
	//向索引缓存中写入顶点的索引
	WORD * dwIndex=NULL;
	g_pIndexBuffer->Lock(0,0,(void **)&dwIndex,0);//加锁
	//能看见的面要用顺时针,不能看见的面用逆时针
	
	dwIndex[0]=0,dwIndex[1]=1,dwIndex[2]=2;
	dwIndex[3]=0,dwIndex[4]=2,dwIndex[5]=3;//上面,顺

	dwIndex[6]=4,dwIndex[7]=7,dwIndex[8]=6;
	dwIndex[9]=4,dwIndex[10]=6,dwIndex[11]=5;//下面,逆

	dwIndex[12]=8,dwIndex[13]=9,dwIndex[14]=10;
	dwIndex[15]=8,dwIndex[16]=10,dwIndex[17]=11;//左侧面,逆

	dwIndex[18]=12,dwIndex[19]=13,dwIndex[20]=14;
	dwIndex[21]=12,dwIndex[22]=14,dwIndex[23]=15;//右侧面,顺

	dwIndex[24]=16,dwIndex[25]=17,dwIndex[26]=18;
	dwIndex[27]=16,dwIndex[28]=18,dwIndex[29]=19;//前面,顺

	dwIndex[30]=20,dwIndex[31]=23,dwIndex[32]=22;
	dwIndex[33]=20,dwIndex[34]=22,dwIndex[35]=21;//后面,逆

	g_pIndexBuffer->Unlock();//解锁

	//加载贴图图片
	D3DXCreateTextureFromFile(g_pd3dDevice,TEXT("Demo_05_Media\\texture1.jpg"),&g_pTexture1);
	D3DXCreateTextureFromFile(g_pd3dDevice,TEXT("Demo_05_Media\\texture2.jpg"),&g_pTexture2);
	D3DXCreateTextureFromFile(g_pd3dDevice,TEXT("Demo_05_Media\\texture3.jpg"),&g_pTexture3);
	D3DXCreateTextureFromFile(g_pd3dDevice,TEXT("Demo_05_Media\\texture4.jpg"),&g_pTexture4);

	//设置取景变换矩阵
	D3DXMATRIX matView;
	D3DXVECTOR3 vEye(0.0f,0.0f,-10.0f);//摄像机位置
	D3DXVECTOR3 vAt(0.0f,0.0f,0.0f);//观察点位置
	D3DXVECTOR3 vUp(0.0f,1.0f,0.0f);//摄像机向上分量
	D3DXMatrixLookAtLH(&matView,&vEye,&vAt,&vUp);
	g_pd3dDevice->SetTransform(D3DTS_VIEW,&matView);//设置取景变换矩阵

	//设置投影变换矩阵
	D3DXMATRIX matProjection;
	D3DXMatrixPerspectiveFovLH(&matProjection,D3DX_PI/4.0f,(FLOAT)g_nWidth/(FLOAT)g_nHeight,1.0f,1000.0f);
	g_pd3dDevice->SetTransform(D3DTS_PROJECTION,&matProjection);//设置投影变换矩阵

	//关闭光照
	g_pd3dDevice->SetRenderState(D3DRS_LIGHTING,false);

	//设置纹理过滤方式,线性过滤,多级渐进过滤
	g_pd3dDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
	g_pd3dDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
	g_pd3dDevice->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR);//多级渐进过滤
	g_pd3dDevice->SetSamplerState(0,D3DSAMP_MAXMIPLEVEL,2);//最大映射级别,设为2,默认为0,最大为16
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	return TRUE;
}

/****************************************************************
*函数名	:	GameLoop
*功能		:	游戏循环(消息循环)
*输入		:	无
*输出		:	无
*返回值	:	无
****************************************************************/
void			GameLoop()
{
	MSG	msg;
	ZeroMemory(&msg,sizeof(MSG));

	//消息循环,收到WM_QUIT时退出程序
	while(WM_QUIT != msg.message)
	{
		if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{
			//有消息产生,转发消息
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			//没有消息,利用空余时间绘制场景
			Render();
		}
	}
}

/****************************************************************
*函数名	:	Render
*功能		:	场景绘制
*输入		:	无
*输出		:	无
*返回值	:	无
****************************************************************/
void			Render()
{
	//清屏,颜色设为灰色,深度缓存置为1.0,模板缓存置为0
	g_pd3dDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(150,150,150),1.0F,0);

	if(SUCCEEDED(g_pd3dDevice->BeginScene()))//开始绘制
	{
		/*在此绘制其他*/
		
		//设置世界变换矩阵
		D3DXMATRIX matWorld,Rx,Ry,Rz;
		D3DXMatrixRotationX(&Rx,D3DX_PI/4.0F);
		D3DXMatrixRotationY(&Ry,timeGetTime()/2000.0f);
		D3DXMatrixRotationZ(&Rz,0.0F);		

		g_pd3dDevice->SetStreamSource(0,g_pVertexBuffer,0,sizeof(VERTEX));//设置顶点数据源
		g_pd3dDevice->SetFVF(VERTEX::FVF);//设置顶点格式
		g_pd3dDevice->SetIndices(g_pIndexBuffer);//设置索引缓存

		//第一个重复寻址
		g_pd3dDevice->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_WRAP);
		g_pd3dDevice->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_WRAP);
		D3DXMatrixTranslation(&matWorld,-2.0F,2.0F,0.0F);
		matWorld=matWorld*Rx*Ry*Rz;
		g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld);//设置世界变换矩阵
		g_pd3dDevice->SetTexture(0,g_pTexture1);
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,24,0,12);//8个顶点,12个三角形

		//第二个镜像寻址
		g_pd3dDevice->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_MIRROR);
		g_pd3dDevice->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_MIRROR);
		D3DXMatrixTranslation(&matWorld,2.0F,2.0F,0.0F);
		matWorld=matWorld*Rx*Ry*Rz;
		g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld);//设置世界变换矩阵
		g_pd3dDevice->SetTexture(0,g_pTexture2);
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,24,0,12);//8个顶点,12个三角形

		//第三个夹取寻址
		g_pd3dDevice->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_CLAMP);
		g_pd3dDevice->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_CLAMP);
		D3DXMatrixTranslation(&matWorld,-2.0F,-2.0F,0.0F);
		matWorld=matWorld*Rx*Ry*Rz;
		g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld);//设置世界变换矩阵
		g_pd3dDevice->SetTexture(0,g_pTexture3);
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,24,0,12);//8个顶点,12个三角形

		//第四个边框颜色寻址
		g_pd3dDevice->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_BORDER);
		g_pd3dDevice->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_BORDER);
		D3DXMatrixTranslation(&matWorld,2.0F,-2.0F,0.0F);
		matWorld=matWorld*Rx*Ry*Rz;
		g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld);//设置世界变换矩阵
		g_pd3dDevice->SetTexture(0,g_pTexture4);
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,24,0,12);//8个顶点,12个三角形
		g_pd3dDevice->EndScene();//结束绘制
	}
	g_pd3dDevice->Present(NULL,NULL,NULL,NULL);//翻转,显示
}

/****************************************************************
*函数名	:	Cleanup
*功能		:	程序退出时释放申请的资源
*输入		:	无
*输出		:	无
*返回值	:	无
****************************************************************/
void			Cleanup()
{
	SAFE_RELEASE(g_pVertexBuffer);//释放顶点缓存
	SAFE_RELEASE(g_pIndexBuffer);//释放索引缓存
	SAFE_RELEASE(g_pTexture1);//释放纹理
	SAFE_RELEASE(g_pTexture2);//释放纹理
	SAFE_RELEASE(g_pTexture3);//释放纹理
	SAFE_RELEASE(g_pTexture4);//释放纹理
	SAFE_RELEASE(g_pd3dDevice);//释放设备
}

程序运行结果:



源代码及工程文件下载地址:

百度网盘

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值