龙书笔记(4)

1.顶点缓存与索引缓存: 包含顶点数据的连续内存空间,包含索引数据的连续存储空间。
不用数组的原因:顶点缓存和索引缓存存放在位置是 显存, 而数组是放在 内存中,在绘制速度方面是 显存的速度更快
创建顶点缓存 和 索引缓存:
		HRESULT IDirect3DDevice9::CreateVertexBuffer(
			UINT Length,								//为缓存分配的字节数,比如sizeof(Vertex)
			DOWRD Usage,								//0(无附加属性) D3DUSAGE_DYNAMIC(设为动态缓存) D3DUSAGE_WRITEONLY(只写,在这里读的话会报错)
			DWORD FVF,									//指定灵活顶点的格式
			D3DPOOL Pool,								//容纳缓存的内存池
			IDirect3DVertexBuffer9 **ppVertexBuffer,	//接受创建顶点缓存的指针
			HANDLE *pSharedHandle						
		);
		HRESULT IDirect3DDevice9::CreateIndexBuffer(
			UINT Length,								//同上
			DWORD Usage,								//同上
			D3DFORMAT Format,							//D3DFMT_INDEX16表示16位索引,D3DFMT_INDEX32表示32位索引
			D3DPOOL Pool,								//同上
			IDirect3DIndexBuffer9 **ppIndexBuffer,		//接受创建索引缓存的指针
			HANDLE *pSharedHandle					
		);


注意:若不指定D3DUSAGE_DYNAMIC,则创建的就是静态缓存,他通常用来存储的是不需要经常修改或访问的数据
 而若指定D3DUSAGE_DYNAMIC,则适合用于频繁更新缓存数据类型


2.访问缓存内容 (操作的是IDirect3DVertexBuffer9对象和IDirect3DIndexbuffer9对象)
通过lock方法,但要注意使用完毕后Unlock方法释放。
lock的最后一个参数可以设置的值为0, D3DLOCK_DISCARD, D3DLOCK_NOOVERWRITE, D3DLOCK_READONLY
注意一下,后面的vb都是假设已经通过CreateVertexBuffer()创建好的顶点指针
			Vertex * vertices;
			vb->Lock(0, 0, (void**)&vertices, 0);			//前面的两个参数指定为0则是表示 锁定整个缓存,这里假定vb是以创建好的 静态顶点缓存
			vertices[0] = Vertex(-1.0f, 0.0f, 2.0f);
			vertices[1] = Vertex(0.0f, 1.0f, 2.0f);
			vertices[2] = Vertex(1.0f, 0.0f, 2.0f);
			vb->Unlock();
			//也可以这样:
			Vertex Data[] = 
			{
				{ -1.0f, 0.0f, 2.0f },
				{ 0.0f, 1.0f, 2.0f },
				{ 1.0f, 0.0f, 2.0f }
			};
			void* v;
			vb->Lock(0, 0, (void**)&v, 0);
			memcpy( v, Data, sizeof( Data ) );				//内存复制
			vb->Unlock();



3.获取顶点缓存和索引缓存的信息
顶点的信息包含了顶点的format,type,usage,pool,fvf,size等信息。
索引信息只少一个fvf而已。
			D3DVERTEXBUFFER_DESC vbDesc;
			vb->GetDesc( &vbDesc );
			
			D3DINDEXBUFFER_DESC ibDesc;
			ib->GetDesc( &ibDesc );	


4.绘制状态, IDirect3DDevice9::SetRenderState
这个方法会经常用到,他有很多参数,比如alpha,stencil,light,着色情况,还有很多
			//使用线框模式来绘制物体
			device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);


5.绘制的准备工作
(1)指定数据流输入源。将顶点缓存和数据流进行链接。(实质就是向数据流中给出几何体的信息):
			IDirect3DDevice9::SetStreamSource(
				UINT StreamNumber,					//标识与顶点缓存建立链接的数据流
				IDirect3DVertexBuffer9 * pSD,		//指定希望与给定数据流建立链接的顶点缓存指针
				UINT OffsetInBytes,					//从数据流起始点算起的一个偏移量,单位是字节
				UINT Stride							//顶点缓存中每个元素的大小,单位是字节
			)
			//eg:
			device->SetStreamSoure(0, vb, 0, sizeof(Vertex));


(2)设置顶点格式,在这里指定后续绘制调用的顶点格式
			device->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);


(3)设置索引,这是可选的,如果使用了索引缓存就必须调用这个方法
			device->SetIndices(ib);				//假定ib已创建好的索引缓存


注意:任意时刻只能使用一个 索引缓存,所以如果使用不同的索引缓存绘制物体,必须切换

注意2:这三步是用在 绘制由顶点缓存或者索引缓存构建的 模型中的,茶壶什么的不需要这几步,茶壶的绘制是直接teapot->DrawSubset(0);


6.使用顶点缓存和索引缓存进行绘制

数据流输入源,灵活顶点,(可选)索引缓存指定好之后,接下来就是绘制了,主要有2种绘制方式:

(1)  IDirect3DDevice::DrawPrimitive,用在只有顶点的时候。
原型如下:
			HRESULT IDirect3DDevice9::DrawPrimitive(
				D3DPRIMITIVETYPE PrimitiveType,				//所要绘制的图元类型(比如三角形 ,点, 线)
				UINT StartVertex,							//顶点数据读取起点的元素的索引
				UINT PrimitiveCount							//图元的数量
			);
			//eg:			
				device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 4);


   (2)IDirect3DDevice::DrawIndexedPrimitive,用在既有顶点又有索引的时候。
原型如下:
			HRESULT IDirect3DDevice9::DrawIndexedPrimitive(
				D3DPRIMITIVETYPE Type,						//同上
				INT BaseVertexIndex,						//为索引添加一个基数
				UINT MinIndex,								//允许使用的最小索引值
				UINT NumVertices,							//本次调用中使用的顶点总数
				UINT StartIndex,							//标识索引的读取起始点的元素的索引
				UINT PrimitiveCount							//同上
			);
			//eg:
				device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);


  Begin/End Scene: 最后,所有的绘制方法都必须放在IDirect3DDevice9::BeginScene 和 IDirect3DDevice9::EndScene之间
			//eg:		
				device->BeginScene();
					device->DrawPrimitive(...);
				device->EndScene();


7.D3DX几何体
D3DX库提供了一些用于生成3D几何体的网格数据的办法,这些都是拿给新手玩的~
D3DXCreateBox
D3DXCreateSphere
D3DXCreateCylinder
D3DXCreateTeapot
D3DXCreatePolygon

D3DXCreateTorus

注意:这些函数 生成的网格只有一个属性子集,这就是为什么DrawSubset参数填0的原因,关于属性子集的概念会在网格的时候谈到...

		//eg:
			ID3DXMesh * mesh = 0;				//创建网格
			D3DXCreateTeapot(device, &mesh, 0);
			
			device->BeginScene();
				mesh->DrawSubset(0);			//用DrawSubset(0)对网格数据进行绘制,其中参数0表示的是 接受一个代表网格数据的子集的参数。
			device->EndScene();
			
			mesh->Release();					//使用网格完毕后必须释放
			mesh = 0;



对 4个例程 的讨论:

1.Triangle: 结果是一个三角形的图形。(这个例子仅仅用了顶点缓存)

essential 1: 创建Vertex对象(更准确的说是结构),这里面的静态参数FVF指明了灵活顶点的格式

	struct Vertex
	{
		Vertex(){}
		Vertex(float x, float y, float z)
		{
			_x = x;	 _y = y;  _z = z;
		}
		float _x, _y, _z;
		static const DWORD FVF;
	};
	const DWORD Vertex::FVF = D3DFVF_XYZ;


essential 2: 注意Setup里面的内容包含这几个部分:
1.创建顶点缓存
2.用Vertex填充这个缓存,注意释放的问题
3.设置投影矩阵并在device中使用他
4.设置绘制状态
Device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); //线框模式,不指定的话,绘制出来的是全部黑色的三角形


essential 3: Display函数
1.数据流输入源
2.灵活顶点的设置
3.在BeginScene和EndScene中添加绘制的代码,这里用的是DrawPrimitive 


2.Cube: 结果是一个旋转的立方体,背面消隐的。(这个例子用到了 顶点缓存 和 索引缓存)


essential 1: 创建了Vertex结构,同上。


essential 2: Setup函数,主要包括:
1.创建顶点缓存和索引缓存,  CreateVertexBuffer CreateIndexBuffer
2.填充缓存的内容,注意Lock和Unlcok,用来填充的类型分别是Vertex和WORD
3.设置观察矩阵并使用 D3DXMatrixLookAtLH SetTransform
4.设置投影矩阵并使用 D3DXMatrixPerspectiveFovLH SetTransform

5.设置绘制状态


essential 3: Display函数,主要包括:
1.先创建x和y方向旋转矩阵,设置沿x轴和y轴旋转的角度, 由于要使立方体旋转起来,所以每帧的y都应该有所变化,
最后在y方向旋转一周完毕后将y设为0,回到初始的状态,这样就可以一直循环下去。
2.以上过程是通过世界变换完成的。
3.数据流输入源,顶点缓存, 注意,和上面不一样的是还需要指定 索引缓存
4.用DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,8,0,12)来绘制,但必须放在BeginScene和EndScene中

essential 4: 体验顶点创建的顺序和空间结构...然后改变摄像机的位置,超有趣!


3.teapot: 结果是一个旋转的茶壶。(这个例子用的是系统的 D3DXCreateTeapot,并且使用的绘制方法是 DrawSubset)


essential 1: 由于创建的对象类型是ID3DXMesh(系统定义好的),所以不用自己定义结构。
essential 2: Setup函数:观察矩阵和投影矩阵的建立并使用,设置绘制状态

essential 3: Display函数:通过设置y方向的旋转角度来控制每帧旋转的角度,在在BeginScene和EndScene之间添加DrawSubset(0)


4.D3DCreateXXX: 结果是5个物体,视角在旋转。

这个例子中,动的不是物体,是摄像机,而且摄像机一边旋转,一边上下移动。下面是旋转的逻辑部分:(这是Display中的内容)

	static float angle = (3.0f * D3DX_PI) / 2.0f;				//设为静态,所以在每次时间变化时,都会从上一次的位置开始
	static float cameraHeight = 0.0f;							//摄像机的真实坐标
	static float cameraHeightDirection = 5.0f;					//摄像机每次变化的高度,当为负是说明摄像机下降
				
	D3DXVECTOR3 position( cosf(angle) * 10.0f, cameraHeight, sinf(angle) * 10.0f );		//摄像机的位置


	D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);					//摄像机的观察点,这里为原点


	D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);													


	D3DXMATRIX V;
	D3DXMatrixLookAtLH(&V, &position, &target, &up);
	Device->SetTransform(D3DTS_VIEW, &V);


	angle += timeDelta;							//摄像机旋转角度的变化情况
	if( angle >= 6.28f )
		angle = 0.0f;


	cameraHeight += cameraHeightDirection * timeDelta;			//摄像机高度的变化情况
	if( cameraHeight >= 10.0f )
		cameraHeightDirection = -5.0f;


	if( cameraHeight <= -10.0f )
		cameraHeightDirection = 5.0f;




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值