direct3D学习笔记【转】.doc_第1页
direct3D学习笔记【转】.doc_第2页
direct3D学习笔记【转】.doc_第3页
direct3D学习笔记【转】.doc_第4页
direct3D学习笔记【转】.doc_第5页
已阅读5页,还剩30页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

DirectX SDK 2006学习笔记1框架2008-01-31 13:20友情提醒:所谓的框架是指SDK目录下SamplesC+Common路径下的DXUT系列函数包装。学习框架的前提是必须有足够的 Windows API,GUI编程经验,必须熟悉Windows的消息机制,回调机制,最好有万行左右的C/C+编程经验。MFC在这里没有任何用处。另外我觉得最好 在看程序之前对于D3D的所有概念有点了解,什么是vertex,texture,matrix,lighting,mesh等等,以及相关的数学概念。 这些都可以在网上找到中文翻译,帮助你快速入门。 DXSDK2006和2003版的比起来更新了不少东西,比如DirectX10,还有ManagedDirectX等等。不过我关心的还是D3D9。除了个别接口的更改之外,DXSDK2006还提供了一套图形控件的类库,它的界面还是很漂亮的:)如图: 学习一个框架还是从它的入口学习比较方便,否则容易迷失在无穷无尽的API和层层包装之中。DXSDK2006的框架和2003版的DX9.0c框架有 很大的不同。首先是2003版的框架中提供了一个CD3DApplication类,这个类对于初始化,清除,以及游戏窗口的创建,游戏主循环进行了包 装。这是一个不错的类,不知道为什么在2006版中去掉了。不过不要紧,2006版的框架中提供的一些C包装函数已经足够了。在看这些函数之前,我们还是 先来看看SDK目录下SamplesC+ Direct3DTutorials中有些什么吧。Tut01_CreateDevice是创建框架,这个程序不用框架,研究一下有助于了解D3D的 大致工作流程。下面是winmain函数中的一部分。 / Initialize Direct3D if( SUCCEEDED( InitD3D( hWnd ) ) ) / Show the window ShowWindow( hWnd, SW_SHOWDEFAULT ); UpdateWindow( hWnd ); / Enter the message loop MSGmsg; while( GetMessage( &msg, NULL, 0, 0 ) ) TranslateMessage( &msg ); DispatchMessage( &msg ); 在消息循环之前有个初始化设备的函数InitD3D( hWnd ),其代码如下:HRESULTInitD3D( HWNDhWnd ) if( NULL = ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) returnE_FAIL; D3DPRESENT_PARAMETERSd3dpp; ZeroMemory( &d3dpp, sizeof(d3dpp) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;if( FAILED( g_pD3D-CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ) ) ) returnE_FAIL; returnS_OK;主要是调用Direct3DCreate9和g_pD3D-CreateDevice这两个函数。查看DXSDK文档中关于D3DPRESENT_PARAMETERS的定义,大致了解一下。接下来要关心的就是消息循环了,在回调函数MsgProc中处理了两个消息,一个是WM_DESTROY,里面调用了Cleanup函数,另一个是WM_PAINT函数,里面调用了Render函数。Cleanup函数很简单,就是调用D3D对象及其设备对象的Release函数释放资源,而Render函数就是D3D中最重要的函数了。VOIDRender() if( NULL=g_pd3dDevice) return; / Clear the backbuffer to a blue color g_pd3dDevice-Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 ); / Begin the scene if( SUCCEEDED( g_pd3dDevice-BeginScene() ) ) / Rendering of scene objects can happen here / End the scene g_pd3dDevice-EndScene(); / Present the backbuffer contents to the display g_pd3dDevice-Present( NULL, NULL, NULL, NULL);主要调用的函数有BeginScene, EndScene和Present函数。 对D3D应用程序有了大概了解之后就可以看空框架程序了。这个程序可以在SamplesC+Direct3DEmptyProject中找到。 从WinMain中的调用可以看到,框架首先设定一堆回调函数,很多事情的是在用户自己写的回调函数中实现。从DXUTInit开始,程序开始调用框架 内的API来完成初始化创建窗口创建设备主消息循环退出等一系列操作。调查Common目录下DXUT.cpp文件就可以发现 DXUTInit函数干了以下几件事情 设定开始调用这个函数的标志符 InitCommonControls 保存当前的sticky/toggle/filter键 通过事先导入winmm.dll的方法timeBeginPeriod来确保调用Sleep的准确性 设定一些标志附,读取命令行参数 检查版本 获 得D3D对象指针。值得一提的是框架中大部分全局变量是通过类DXUTState的静态变量state的get/set方法得到的。这些get/set方 法是用宏定义的,里面调用了加锁和解锁,因此保证了全局变量设定的线程安全。这些全局性的变量包括D3D对象指针,D3D设备对象指针, BackBufferSurfaceDesc,DeviceCaps,窗口HINSTANCE,窗口句柄HWND,焦点句柄HWNDFocus,全屏设备 句柄,窗口设备句柄,窗口客户端矩形,模式切换时窗口客户端矩形,模式切换时全屏客户端矩形,Time,ElapsedTime,FPS数,窗口标题,设 备数据DeviceStats,以及是否暂停渲染,时间是否暂停,窗口是否激活等标志,一些窗口事件等等。这些都可以通过 DXUTGETXXX/DXUTSETXXX/DXUTISXXX系列包装函数获得。 通过DXUT_Dynamic_Direct3DCreate9创建D3D对象。很多D3D底层API都是通过动态的方式加载的,这样有利于效率的提高。 重设全局时钟 设 定DXUTInited为true。很多DXUT系列的函数都喜欢在入口设定一个开始调这个函数的标志,在出口设定一个这个函数已经被调过的标志,这样可 以在以后再次调用这个函数的时候了解当前什么工作已经做了,什么工作没做需要补做。我想这个主要是用来防止函数重入问题的吧。其他函数中的这一对函数就不 再提了呼第一个函数大致看完了,接下来是DXUTCreateWindow函数。什么?要问DXUTSetCursorSettings为什么被无视?因为这个函数不重要。DXUTCreateWindow的工作大致是这样的 判断关于设备的CallBack有没有设定好 判断DXUTInit()有没有被调用成功(注意不是有没有调用)。 获得焦点句柄,因为窗口还没有创建,所以这个句柄应该是NULL 设定HInstance 设定窗口类 注册窗口类 设定窗口位置和大小。好长一段代码,汗 创建窗口。终于。 设定窗口焦点句柄,全屏设备句柄,窗口设备句柄接下来的函数是DXUTCreateDevice。这个函数就是用来选择最优设备并创建的。 设定参数中的回调函数和上下文,以备后用 检查窗口是否被成功创建,否则再调用一次DXUTCreateWindow 枚举所有可能的显示模式。枚举过程非常复杂,用到了CD3DEnumeration中的一些包装函数,这些设备信息包括分辨率,颜色位深等等。这里会用到DXUTCreateDevice传进来的参数IsDeviceAcceptable 如果命令行设定过显示模式,那么将刚才得到的信息覆盖。 采用某种权重的算法找出最优显示模式(DXUTFindValidDeviceSettings) 切 换设备。这里用到了DXUTCreateDevice传进来的参数ModifyDeviceSettings。切换设备时要考虑很多问题:比如需要暂时忽 略WM_SIZE消息;只有在第一次创建设备的时候才用命令行参数;按照需要调用DXUTCreate3DEnvironment和 DXUTReset3DEnvironment;分全屏和窗口设备重设;重设完了根据需要处理WM_SIZE消息;显示窗口,允许WM_SIZE消息等等最后是DXUTMainLoop。 检查是否有重入问题 设定进入主循环标志 检查设备是否已经被成功创建,没创建的话用默认参数创建一次 检查前面三个函数是否成功调用。汗,又是检查 处理窗口消息,注意只有在没有消息处理的时候才调用DXUTRender3DEnvironment() 在消息循环退出之后清除加速表。应该是类似SHIFT+X这种键盘加速表的清除吧 更改主循环标志还是有必要看一下主消息循环中的DXUTRender3DEnvironment 检查设备是否丢失 在窗口模式下检查桌面分辨率位深设定,以便重设设备 尝试重设设备DXUTReset3DEnvironment 判断上次渲染到现在时间(elapsed time)决定是否要进行渲染 调用用户的FrameMove函数 调用用户的FrameRender函数 调用Present函数 更新当前Frame 根据命令行检查是否需要关闭应用程序主函数看完之后,剩下的就是一些回调函数了。要正确使用这些回调函数,除了知道它们的作用之外,还需要知道这些函数是何时被调用的。下面是调用顺序 程序启动:InitApp MsgProc IsDeviceAcceptable ModifyDeviceSettings OnCreateDevice OnResetDevice 渲染主循环 渲染主循环:OnFrameMove OnFrameRender 改变设备:ModifyDeviceSettings OnLostDevice 根据需要调用OnDestroyDevice OnResetDevice 渲染主循环 程序退出:OnLostDevice OnDestroyDevice 下面是各函数的作用:InitApp初始化一些图形控件和GUI的消息处理函数OnCreateDevice创建设备时的回调函数,用于创建D3DPOOL_MANAGED资源OnResetDevice重设设备时的回调函数,用于创建D3DPOOL_DEFAULT资源OnFrameMove动画实现处,常用于矩阵转换等操作OnFrameRender渲染实现处,常用于渲染场景OnLostDevice设备丢失时的回调函数,释放由OnResetDevice创建的资源OnDestroyDevice设备析构时的回调函数,释放由OnCreateDevice创建的资源IsDeviceAcceptable创建设备时用来对所有可用设备进行过滤的函数ModifyDeviceSettings更改设备时的回调函数,用于实现更改设备时所需做的其他操作MsgProc安排各空件处理消息的顺序OnGUIEvent程序控件绑定的消息处理回调函数以上函数均可以更换名字,这里只是用框架默认的函数名字。DirectX SDK 2006学习笔记2顶点缓冲2008-01-31 13:22D3D9以一种比较易于理解的方式让程序员来组织游戏画面,这种方式就是顶点缓冲。程序员可以自己定义一组记录多 边形定点颜色,纹理位置等的数组,让D3D9去自动生成多边形内部每个像素的信息。为了和以后的vertex shader相区别,我们现在谈论的都是固定功能的顶点处理( Fixed-Function )。 上面一段话似乎有点晦涩,让我们首先来看看这些术语的定义吧: 顶点缓冲Vertex Buffer:由用户定义的,包含顶点信息的数组。首先我们来学习一下Vertex Buffer的技术。我喜欢先看代码再讲理论,否则看了理论也找不到北。下面就是一个自定义的顶点缓冲的结构struct CUSTOMVERTEX FLOATx, y, z, rhw; / The transformed position for the vertex DWORDcolor; / The vertex color;其中,x, y, z是顶点在3维空间的最终位置,rhw是3维矩阵的倒数(不明白的话找本图形学的书研究一下),color自然就是顶点的颜色了。由于这个结构是自定义的,所以我们需要告诉D3D应该如何识别这个结构,这就需要我们定义一个常量了:/ Our custom FVF, which describes our custom vertex structure#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE) 这个D3DFVF_CUSTOMVERTEX就是用来告诉D3D上面那个CUSTOMVERTEX结构是如何组织的:首先是 D3DFVF_XYZRHW,即顶点在3维坐标系的最终位置,D3DFVF_DIFFUSE是色彩模式,告诉D3D紧接着D3DFVF_XYZRHW信息 的是顶点的色彩信息,并且这种色彩信息是漫反射模式的。类似的标志可以学习DirectX SDK文档(搜索D3DFVF),这里就不再赘述。上面所提到的顶点缓冲定义方式就是为大家熟知Flexible Vertex Format,简称FVF,是不是有点眼熟呢。下面是Direct3D游戏编程入门一书中对复杂的FVF举的一个例子,供参考typedef struct SObjVertex FLOATx, y, z;/ position FLOATnx, ny, nz; / normal DWORDdiffuse; / diffuse color DWORDspecular;/ specular color FLOATtu, tv; / first pair of texture coordinates FLOATtu2, tv2, tw2; / second pair of texture coordinates FLOATtu3, tv3; / third pair of texture coordinates FLOATtu4, tv4; / fourth pair of texture coordinates SObjVertex;const DWORD gSObjVertexFVF = (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR |D3DFVF_NORMAL | D3DFVF_TEX4 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEXCOORDSIZE2(3) );看完了FVF顶点格式的定义,就可以看它是如何使用的。使用方法非常简单,在OnCreateDevice中添加创建和初始化代码,在OnFrameRender中添加渲染代码就可以了,具体如下:LPDIRECT3DVERTEXBUFFER9g_pVB = NULL; / Buffer to hold verticesHRESULTCALLBACKOnCreateDevice( IDirect3DDevice9* pd3dDevice, constD3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ) / Initialize three vertices for rendering a triangle CUSTOMVERTEX vertices = / x, y, z, rhw, color 150.0f, 50.0f, 0.5f, 1.0f, 0xffff0000, , 250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, , 50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, , ; if( FAILED( pd3dDevice-CreateVertexBuffer( 3*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_MANAGED, &g_pVB, NULL ) ) ) return E_FAIL; / Now we fill the vertex buffer. To do this, we need to Lock() / the VB togain access to the vertices. This mechanism is / required becuase vertexbuffers may be in device memory. VOID* pVertices; if( FAILED( g_pVB-Lock( 0, sizeof(vertices), (void*)&pVertices, 0 ) ) ) returnE_FAIL; memcpy( pVertices, vertices, sizeof(vertices) ); g_pVB-Unlock(); 为了统一和强调精度,D3D采用了float作为其主要的数值类型。上面的程序调用了CreateVertexBuffer和 LPDIRECT3DVERTEXBUFFER9- Lock和Unlock函数。另外需要在OnFrameRender中的BeginScene和EndScene中调用如下代码pd3dDevice-SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX) );pd3dDevice-SetFVF( D3DFVF_CUSTOMVERTEX );pd3dDevice-DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );其中SetStreamSource函数第一个参数StreamNumber用来设定使用哪条数据流,这个数据流的最大值根据显卡硬件的不同而不同,现在好的显卡可以支持8条或者16条数据流。SetFVF函数用来把我们自定义的顶点缓冲布局常量传递给D3D。DrawPrimitive函数用来告诉D3D以那种图元绘制这个图形。其中图元这个概念很重要,它是D3D世界中最基本的单位,分为点列表,线列表,线带,三角形列表,三角形带,三角扇形六中,在D3D中的具体定义如下: typedef enum _D3DPRIMITIVETYPE D3DPT_POINTLIST = 1, D3DPT_LINELIST = 2, D3DPT_LINESTRIP = 3, D3DPT_TRIANGLELIST = 4, D3DPT_TRIANGLESTRIP = 5, D3DPT_TRIANGLEFAN = 6, D3DPT_FORCE_DWORD = 0x7fffffff, D3DPRIMITIVETYPE; 其中点列表,线列表,三角形列表很好理解,它们就是独立的点线三角形的集合,每个顶点缓冲中的点分别表示一个点独立线条中的一个端点独立三角形 中的一个顶点。而线带,三角形带每个顶点缓冲中的点表示连续的线条的端点连续三角形中的顶点。三角扇形顶点缓冲中的点表示三角扇形中的每个顶点,如图: 三角形列表 三角形带 三角扇形 线列表 点列表 线带在特殊情况下三角形带和三角扇形都可以组成四边形。只要将DrawPrimitive中的参数变换一下,适当改变顶点缓冲就可以得到D3D中以不同图元画出的图形。下图是三角形列表形式画出的一个三角形。不要忘了更改CreateVertexBuffer中的第一个表示顶点缓冲大小的参数,否则添加的顶点会被忽略的。最后在OnDestroyDevice中调用SAFE_RELEASE( g_pVB )来释放资源。DirectX SDK 2006学习笔记3索引缓冲2008-01-31 13:24索引缓冲索引缓冲Index Buffer是由用户定义的,用来告诉D3D渲染顶点顺序的WORD或者DWORD数组。索引缓冲离不开顶点缓冲,但是顶点缓冲却不一定需要索引缓冲。创建索引缓冲的过程和创建顶点缓冲类似,首先是声明,然后在OnCreateDevice中初始化和创建,在OnFrameRender中渲染,在OnDestroyDevice中销毁。相关代码如下:声明:LPDIRECT3DINDEXBUFFER9 g_pIB = NULL; / Buffer to hold indecesOnCreateDevice:HRESULT hr;V_RETURN( g_DialogResourceManager.OnCreateDevice( pd3dDevice ) );V_RETURN( g_SettingsDlg.OnCreateDevice( pd3dDevice ) );/ Initialize the fontV_RETURN( D3DXCreateFont( pd3dDevice, 15, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, LArial, &g_pFont ) );/ Initialize vertices for rendering a triangleCUSTOMVERTEX vertices = 0.0f, 0.0f, 0.5f, 1.0f, 0xffff0000, , / x, y, z, rhw, color (float)pBackBufferSurfaceDesc-Width, 0.0f, 0.5f, 1.0f, 0xff00ff00, , (float)pBackBufferSurfaceDesc-Width, (float)pBackBufferSurfaceDesc-Height, 0.5f, 1.0f, 0xffff00ff, , 0.0f, (float)pBackBufferSurfaceDesc-Height, 0.5f, 1.0f, 0xff0000ff, ,;/ Create the vertex bufferV_RETURN( pd3dDevice-CreateVertexBuffer( sizeof(vertices), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_MANAGED, &g_pVB, NULL ) );VOID* pVertices;V_RETURN( g_pVB-Lock( 0, sizeof(vertices), (void*)&pVertices, 0 ) );memcpy( pVertices, vertices, sizeof(vertices) );g_pVB-Unlock();/ Initialize index buffer for renderingWORDwIndeces = 0,1,2,0,2,3;/ Create the index bufferV_RETURN( pd3dDevice-CreateIndexBuffer( sizeof(wIndeces), 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &g_pIB, NULL) );VOID* pIndeces; V_RETURN( g_pIB-Lock( 0, sizeof(wIndeces), &pIndeces, 0) );memcpy( pIndeces, wIndeces, sizeof(wIndeces) );g_pIB-Unlock();returnS_OK;OnRender中BeginScene和EndScene之间pd3dDevice-SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX) );pd3dDevice-SetFVF( D3DFVF_CUSTOMVERTEX );pd3dDevice-SetIndices( g_pIB );/pd3dDevice-DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );pd3dDevice-DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, 4, 0, 2 );OnDestroyDeviceSAFE_RELEASE( g_pVB );SAFE_RELEASE( g_pIB );下面是这段代码的效果图:挺PP的吧?这段代码和顶点缓冲最重要的不同在于DrawIndexedPrimitive函数。这个函数的使用方法请看下面的例子(整理自SDK文档Rendering from Vertex and Index Buffers):Scenario 1:画两个没有索引缓冲的三角形(为了方便现在仅列出三维坐标的x,y值,下同)左图上的正方形由两个三角形组成,从右图可以看出顶点缓冲程序采用了TRIANGLELIST的图元方式分别画出了两个三角形,代码如下:DrawPrimitive( D3DPT_TRIANGLELIST, / PrimitiveType 0, / StartVertex 2 ); / PrimitiveCountScenario 2:用索引缓冲画两个三角形右边图的是顶点缓冲,和场景1相比少了两个重复定义的顶点,左边的数组就是索引缓冲,方框中的数字就是右边顶点缓冲的编号,其中顶点0, 1, 2构成一个独立的三角形,顶点3, 0, 2独立构成另一个独立的三角形,代码如下:DrawIndexPrimitive( D3DPT_TRIANGLELIST, / PrimitiveType 0, / BaseVertexIndex 0, / MinIndex 4, / NumVertices 0, / StartIndex 2 ); / PrimitiveCount函数由DrawPrimitive换成了DrawIndexPrimitive,图元类型仍然为TRIANGLELIST。图元数仍然为2。Scenario 3:使用索引渲染一个三角形这次需求变更,但是仍然想用上面的索引缓冲和顶点缓冲怎么办呢?具体来说,我们只想要画由顶点0, 2, 3构成的三角形。研究DrawIndexPrimitive之后发现只要这样调用就可以了:DrawIndexPrimitive( D3DPT_TRIANGLELIST, / PrimitiveType 0, / BaseVertexIndex 0, / MinIndex 4, / NumVertices 3, / StartIndex 1 ); / PrimitiveCountStartIndex为3,就是说从第三个元素开始使用索引缓冲,上图中第三个元素对应的正好是顶点3。图元数为1,因为我们只需要画一个三角形。顶点个数仍然为4。Scenario 4:使用索引缓冲的Offset渲染一个三角形 假如一个顶点缓冲特别大,顶点的标号已经达到50, 51, 52, 53这样的数字,我们可以通过填写Offset的方法来调用DrawIndexPrimitive。上图的情况只要将Offset这个参数设为50,就可 以达到不变更上几例中的索引缓冲内容的目的。这种情况下,中间一幅图描述的索引信息就等同于左边的索引信息,而下面函数渲染出的图形就是由顶点53, 50, 52构成的三角形。DrawIndexPrimitive( D3DPT_TRIANGLELIST, / PrimitiveType 50, / BaseVertexIndex 0, / MinIndex 4, / NumVertices 3, / StartIndex 1 ); / PrimitiveCountDirectX SDK 2006学习笔记4纹理2008-01-31 13:25纹理在D3D中是一个非常重要的概念,它的出现改变了以前3D物体表面不真实的状况,为程序员提供了将2维图像应用到3维物体上去的功能。请做 好心理准备,因为新的概念将像暴风骤雨般的袭来,而在没有弄懂基本概念之前是不可能进行下一步的学习的。下面是一些术语的大致概念: 纹理( Textrue ):将要应用到3维(或者2维)模型中的图片,可以有dds, hdr, bmp, tga, jpg, png等多种格式,各种格式可以有8位,16位,32位,64位以及128位的色彩位深 纹理坐标( Textrue Coordinates ):x,y轴分别以0,1为区间的2维坐标。将纹理的长和宽分别认作单位1,用u和v来表示纹理上的每一个色彩的坐标。 图素( Texel ):纹理上每一个色彩点称为图素。每个图素都有自己的纹理坐标。 纹理寻址模式( Textrue Addressing Modes ):系统映射0, 1 区间以外的图素坐标的模式。纹理寻址模式共有五种,它们分别是包装纹理寻址模式、镜像纹理寻址模式、夹持纹理寻址模式,边框纹理寻址模式和一次镜像纹理寻址模式。 包装纹理寻址模式:D3D默认寻址模式。效果如下: 镜像纹理寻址模式:每两个相邻的单位纹理都是镜像效果的。如下: 夹持纹理寻址模式:只映射在区间0, 1中的纹理,然后在其他空间中涂上和纹理边界相反的颜色,如图: 边框颜色纹理寻址模式:在区间0, 1之外涂上指定颜色,例如: 一次镜像纹理寻址模式:纹理在-1.0, 1.0范围内作镜像,在该范围外作夹持。 纹理包装:决定如何在纹理坐标之间做插值计算。 纹 理过滤:通过给定的uv坐标从纹理贴图中获得图素的一种方法。为了抗锯齿,D3D中采用了3中技术来实现纹理过滤,它们分别是最近点采样,线性纹理过滤, 各向异性(anisotropic)纹理过滤。而现在游戏中看到的图像高级选项中,一般都有点采样、双线过滤(即D3D的线性纹理过滤),三线过滤(即 D3D中的线性过滤加上mipmap),以及各向异性过滤。 mipmap:由一系列纹理组成,其中每张纹理的高宽都是前一级高宽的一半。D3D在渲染时会自动挑选出一个图素与像素的比值最接近于1的mip层级。 最近点采样:将纹理坐标对齐到最接近的整数,再将那个位于整数坐标上的纹理像素作为最终的颜色。缺点:容易在图像边界上造成错误,优点:快。 线性纹理过滤:(即双线纹理过滤),计算相对于采样点最近的4各图素(上下左右4个点)的平均值。缺点:有各项异性失真可能。 三线过滤:对于每个像素,三线过滤会先选择两张最接近的mipmap,将它们双线过滤为两张理想大小的mipmap,然后根据理想的mip级组合这两张过滤后的mipmap中的对应像素。缺点:有各项异性失真可能。 各项异性过滤:根据屏幕像素的伸张度来测量各项异性,再将屏幕像素反向映射到纹理空间中。效果:在非水平的渲染时要比三线过滤更加锐化。 抗锯齿:有全屏多采样和可屏蔽多采样之分。全屏多采样对每个像素进行多次采样,这些不同的样本被混合后输出到屏幕。可屏蔽多采样仅影响三角形和三角形组,不影响直线。 Alpha混合:可将图元颜色和先前的帧缓冲器像素的颜色组合起来,用于实现透明效果。有个很著名的alpha混合计算公式: FinalColor = SourceColor * SourceBlendFactor + DestColor * DestBlendFactor如果使SourceBlendFactor + DestBlendFactor = 1,那么就可以实现透明效果。Example 1 Simple Texture & Wrap Texture Address Mode 一个简单的贴图是很容易实现的,因为它可以简单的建立FVF基础之上,整个过程是这样的:在顶点缓冲之中添加纹理坐标信息,然后在 OnCreateDevice中添加纹理创建代码,在OnFrameRender中添加纹理的设置,最后在OnDestoryDevice中添加纹理资源 释放代码。定义:在顶点缓冲定义中添加纹理坐标信息LPDIRECT3DTEXTURE9 g_pTexture = NULL; / TexturestructCUSTOMVERTEX FLOATx, y, z, rhw; / The transformed position for the vertex /DWORD color; / The vertex color, no use here FLOATtu, tv; / The texture coordinates;#defineD3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_TEX1)OnCreateDevice:添加纹理创建代码,在顶点缓冲中添加纹理坐标信息,横向复制两遍纹理V_RETURN( D3DXCreateTextureFromFile(pd3dDevice, LDaNing_Hudie.jpg, &g_pTexture) );CUSTOMVERTEXvertices = 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, / x, y, z, rhw, color (float)pBackBufferSurfaceDesc-Width, 0.0f, 0.5f, 1.0f, 2.0f, 0.0f, (float)pBackBufferSurfaceDesc-Width, (float)pBackBufferSurfaceDesc-Height, 0.5f, 1.0f, 2.0f, 1.0f, 0.0f, (float)pBackBufferSurfaceDesc-Height, 0.5f, 1.0f, 0.0f, 1.0f, ,;OnFrameRender:在BeginScene和EndScene中间添加如下代码。因为D3D默认使用包装纹理寻址模式,所以不必调用SetSampleState来设置纹理模式。pd3dDevice-SetTexture( 0, g_pTexture );OnDestroyDevice:添加释放代码SAFE_RELEASE( g_pTexture);Example 2Texture Address Mode 包装寻址模式见Example 1。接下来是镜像寻址模式。顶点缓冲的初始化:横向复制四遍,纵向复制两遍,一共是八个纹理单元CUSTOMVERTEXvertices = 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, / x, y, z, rhw, color (float)pBackBufferSurfaceDesc-Width, 0.0f, 0.5f, 1.0f, 4.0f, 0.0f, (float)pBackBufferSurfaceDesc-Width, (float)pBackBufferSurfaceDesc-Height, 0.5f, 1.0f, 4.0f, 2.0f, 0.0f, (float)p

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论