




免费预览已结束,剩余62页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
通过ID3DXSprite来实现DirectX 9.0C绘制2D动画最近我一直在不停地问有关2D游戏制做的技术。继上一篇DirectX9中的二维图片的加载以后,我再发一篇关于通过ID3DXSprite来实现DirectX 9.0C绘制2D动画的帖子,希望对大家有所帮助。 DirectX9中的二维图片的加载/forum/dispbbs.asp?boardID=46&ID=5578通过ID3DXSprite来实现DirectX 9.0C绘制2D动画/forum/dispbbs.asp?boardid=46&id=5581在DirectX 8以前,2D都是DirectDraw来完成的,是Direct中非常重要的一个部分,但是到了DirectX 8以后,DirectDraw被合并到DirectX Graphics 当中了,所以在那以后就很少有人谈到如何用DirectX Graphics 实现2D效果。大多数需要2D的人都不辞辛苦用DirectDraw来实现了,毕竟用Direct 7的东西,后面的都是支持的。但是正如一个老外说的,喜欢用DirectDraw的人用用也无所谓,从Direct 8 以后学习的人再去学DirectDraw就不合适了,那么怎么实现自己需要的2D效果呢?我接触到了3种方法DirectX9中的二维图片的加载就是其中之一,这里我们要讲的是第二种通过ID3DXSprite来实现DirectX 9.0C绘制2D动画感谢Fenger提供的ID3DXSprite用法指导!非常全面非常好!以下是引用Fenger的原话:建立D3D和其他相关的设备应该没有问题吧.然后再定义一个ID3DXSprite*变量:ID3DXSprite* pSprite = NULL; 然后在创建D3D设备(假如是pd3dDevice)之后, 用D3DXCreateSprite创建Sprite:D3DXCreateSprite( pd3dDevice, &pSprite );记得在设备丢失/释放时使用: SAFE_RELEASE( pSprite );在渲染场景的时候, 使用: pSprite-Begin(x);. / 具体绘制代码pSprite-End();其中的x可以是下面各值的组合, 如 D3DXSPRITE_ALPHABLEND | D3DXSPRITE_OBJECTSPACED3DXSPRITE_DONOTSAVESTATE调用Begin()或End()不保存/恢复设备状态. (如pd3dDevice-SetRenderState中设置的部分状态)D3DXSPRITE_DONOTMODIFY_RENDERSTATE不是很清楚, 呵呵, 表面上看好像是不改变渲染状态.D3DXSPRITE_OBJECTSPACE不改变世界矩阵(WORLD)/投影矩阵(TRANSFORM)以及视点矩阵(VIEW), 使用设置在D3DDevice上的矩阵, 如果不指定这个标志, 3个矩阵自动改变为屏幕空间座标D3DXSPRITE_BILLBOARDBillBoard, 很清楚吧, 所有的Sprite都全部自动旋转来对着观看着D3DXSPRITE_ALPHABLEND让Sprite支持AlphaBlend, 很重要, 几乎每次调用Begin都要指定此标志, 另外, D3DRS_ALPHATESTENABLE 状态必须设置为 TRUE, D3DBLEND_SRCALPHA / D3DBLEND_INVSRCALPHA 分别为源混和状态和目标很合状态D3DXSPRITE_SORT_TEXTURESprite会按照渲染先后排序, 当渲染在同一个深度的Sprite推荐使用.D3DXSPRITE_SORT_DEPTH_FRONTTOBACK按照从前到后的渲染顺序对Sprite排序, 当在不同深度渲染有透明信息的Sprite时推荐使用.D3DXSPRITE_SORT_DEPTH_BACKTOFRONT按照从后到前的渲染顺序对Sprite排序, 当在不同深度渲染透明Sprite时推荐使用一般就是D3DXSPRITE_ALPHABLEND, 或者根据需要再加上D3DXSPRITE_OBJECTSPACE, 其他来源:GameR的我都不怎么用.中间的绘制代码使用 pSprite-Draw, 函数原型为:HRESULT Draw(LPDIRECT3DTEXTURE9 pTexture,CONST RECT *pSrcRect,CONST D3DXVECTOR3 *pCenter,CONST D3DXVECTOR3 *pPosition,D3DCOLOR Color );pTexture 是需要绘制的贴图pSrcRect 是需要绘制的贴图上的一个矩形区域, 绘制整过贴图可以指定为NULL.pCenter 是绘制的中心座标(旋转时会以此点为中心), 指定NULL表示中心座标为(0,0,0)pPosition 是绘制的位置座标, 也可以指定NULL表示(0,0,0)Color 是绘制的颜色, 一般情况下指定为 0xffffffff. 最高位到底位的各8字节为Alpha, 红, 绿, 蓝, 如果指定0x80ffffff就是半透明贴图. 如果0xffff0000就只保留贴图里的红色分量, 具体功能自己体会. 当然贴图本身可以包含Alpha信息.需要旋转等功能可以使用 pSprite-SetTransform(), 函数原型为:HRESULT SetTransform( CONST D3DXMATRIX *pTransform );相信这个不用解释都很清楚了吧.最后再提醒一点: pSprite-Begin和pSprite-End 必须成对的出现在 IDirect3DDevice9:BeginScene 和 IDirect3DDevice9:EndScene 之间.还有问题加QQ: 103226172. 指明原因(验证消息).窗体顶端注册: 2004-10 状态: Offline1 Top窗体底端鼯鼠Exp:504下士发表于:2005-8-11 2:19:00 档案 | 短信 | 树状 | 收藏 | 编辑 | 删除 | 引用Re:通过ID3DXSprite来实现DirectX 9.0C绘制2D动画前一种方法我们说过了,是单纯的图片加入,对于游戏而言没有太大的用处,游戏里面毕竟动态的东西比较多,怎么让他动起来呢?我们先看一下源代码。 (本帖子不分析代码,主要留作讨论。代码分析在超级马里奥.net游戏代码完全分析中,欢迎下载)/forum/dispbbs.asp?boardID=47&ID=5582&page=1以下代码在 Microsoft DirectX 9.0 SDK Update (August 2005)环境运行通过,如果遇到编译不通过在下面留言。把SDK中底个例子(纹理)中的banana.bmp(或者自己找一个不要太小的bmp文件)考到你的程序目录下。/-程序2-/学自网络 回馈网络/-/-#include /-LPDIRECT3D9 g_pD3D = NULL; LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;LPDIRECT3DVERTEXBUFFER9 g_pVB= NULL; LPDIRECT3DTEXTURE9g_pTexture= NULL;LPD3DXSPRITE g_pSprite= NULL;struct CUSTOMVERTEXFLOAT x, y, z, rhw; DWORD color; ;#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)RECT rct;/-HRESULT InitD3D( HWND hWnd )SetRect( &rct, 0,200, 100, 250 );if( NULL = ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )return E_FAIL;D3DPRESENT_PARAMETERS d3dpp;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 ) ) )return E_FAIL;g_pd3dDevice-SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );g_pd3dDevice-SetRenderState( D3DRS_LIGHTING, FALSE );D3DXCreateSprite( g_pd3dDevice, &g_pSprite ); if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, banana.bmp, &g_pTexture ) ) )if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, .banana.bmp, &g_pTexture ) ) )MessageBox(NULL, Could not find banana.bmp, Textures.exe, MB_OK);return E_FAIL;g_pd3dDevice-SetRenderState( D3DRS_ZENABLE, TRUE );g_pd3dDevice-SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);g_pd3dDevice-SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);g_pd3dDevice-SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);g_pd3dDevice-SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);return S_OK;/-HRESULT InitVB()CUSTOMVERTEX vertices = 50.0f,50.0f, 0.5f, 1.0f, 0xffff0000, , / x, y, z, rhw, color 250.0f, 50.0f, 0.5f, 1.0f, 0xff00ff00, , 50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, , 250.0f, 250.0f, 0.5f,1.0f, 0xff00ffff, ,;if( FAILED( g_pd3dDevice-CreateVertexBuffer( 4*sizeof(CUSTOMVERTEX),0, D3DFVF_CUSTOMVERTEX,D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )return E_FAIL; VOID* pVertices;if( FAILED( g_pVB-Lock( 0, sizeof(vertices), (void*)&pVertices, 0 ) ) )return E_FAIL;memcpy( pVertices, vertices, sizeof(vertices) );g_pVB-Unlock();return S_OK;/-VOID Cleanup()if( g_pVB != NULL )g_pVB-Release();if( g_pd3dDevice != NULL ) g_pd3dDevice-Release();if( g_pD3D != NULL ) g_pD3D-Release();VOID Render()g_pd3dDevice-Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );if( SUCCEEDED( g_pd3dDevice-BeginScene() ) )g_pd3dDevice-SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );g_pd3dDevice-SetFVF( D3DFVF_CUSTOMVERTEX );g_pd3dDevice-DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );if ( SUCCEEDED( g_pSprite-Begin(D3DXSPRITE_ALPHABLEND) ) ) rct.right +=1; rct.left +=1; g_pSprite-Draw(g_pTexture, &rct, NULL, NULL, 0xffffffff); g_pSprite-End(); g_pd3dDevice-EndScene(); g_pd3dDevice-Present( NULL, NULL, NULL, NULL );LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )switch( msg )case WM_DESTROY:Cleanup();PostQuitMessage( 0 );return 0;return DefWindowProc( hWnd, msg, wParam, lParam );INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT ) WNDCLASSEX wc = sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,GetModuleHandle(NULL), NULL, NULL, NULL, NULL,D3D Tutorial, NULL ;RegisterClassEx( &wc );HWND hWnd = CreateWindow( D3D Tutorial, D3D Tutorial 02: Vertices,WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,GetDesktopWindow(), NULL, wc.hInstance, NULL );if( SUCCEEDED( InitD3D( hWnd ) ) )if( SUCCEEDED( InitVB() ) ) ShowWindow( hWnd, SW_SHOWDEFAULT );UpdateWindow( hWnd );MSG msg;ZeroMemory( &msg, sizeof(msg) );while( msg.message!=WM_QUIT )if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )TranslateMessage( &msg );DispatchMessage( &msg );elseRender();UnregisterClass( D3D Tutorial, wc.hInstance );return 0;窗体顶端注册: 2004-10 状态: Offline2 Top窗体底端鼯鼠Exp:504下士发表于:2005-8-11 2:21:00 档案 | 短信 | 树状 | 收藏 | 编辑 | 删除 | 引用Re:通过ID3DXSprite来实现DirectX 9.0C绘制2D动画非常感谢Fenger的指导,最后的程序调试Fenger还帮忙修改了一个错误,在这里表示感谢!鼯鼠 2005-8-11 2:23:05窗体顶端注册: 2004-10 状态: Offline3 Top窗体底端gotoschoolExp:20新成员发表于:2005-12-15 21:32:00 档案 | 短信 | 树状 | 收藏 | 编辑 | 删除 | 引用Re:通过ID3DXSprite来实现DirectX 9.0C绘制2D动画超级马里奥.net 源 哪有的下啊楼主传给我一个 窗体顶端注册: 2005-12 状态: Offline4 Top窗体底端大元帅Exp:518下士发表于:2007-8-14 22:26:00 档案 | 短信 | 树状 | 收藏 | 编辑 | 删除 | 引用Re:通过ID3DXSprite来实现DirectX 9.0C绘制2D动画看不懂,VC对我来说就是鸟文窗体顶端注册: 2007-7 状态: Offline5 Top窗体底端wangyue66Exp:4新成员发表于:2007-11-17 22:38:00 档案 | Email | 短信 | 树状 | 收藏 | 编辑 | 删除 | 引用Re: 通过ID3DXSprite来实现DirectX 9.0C绘制2D动画很好啊,但怎么才能把IDirect3DSprite在三维中应用呢?希望高手指点摘要 本文将介绍一种简单而有效的多线程方案,能加速大量的3D模型的动画渲染。此方案通过使用线程池、双缓冲、间隔更新等方法显著提升了骨骼动画的性能。尤其值得一提的是,此方案可以使基于CPU的骨骼动画在多核系统上获得与基于GPU动画接近的性能,从而在某些情况下可成为除基于GPU动画外的另一种良好选择。介绍 在现代游戏中,动画扮演着重要的角色,它使3D模型看上去更加真实。骨骼动画可能是今天我们使用的最高级的实时动画技术之一。在这种技术中,定义模型外形的蒙皮通常被称为皮肤,而支撑皮肤的结构通常被称为骨骼,皮肤的形状和位置随着骨骼的变化而变化。由于这种技术的算法涉及大量的矩阵运算1,因此骨骼动画的计算密集性相当高。而且,大型多人在线角色扮演游戏中通常有一些大的游戏场景,比如集市,战场,闹市区等。这些场景中有很多动态的3D模型。因此处理这些模型的骨骼动画将成为游戏中一个显著的性能瓶颈。 当前,已经有一些软硬件技术被用于优化骨骼动画的性能。比如对模型骨骼使用LOD(细节分层)技术能减少远处模型的动画复杂性。而在骨骼动画的算法实现中使用SSE指令能获得比原先C实现的代码至少高两倍的性能。对于支持顶点着色器(vertex shader)的显卡,大部分动画渲染工作能从CPU移到GPU上,并获得显著的性能提升。 在过去的几年里,PC业界有两种趋势,一种是越来越多的台式机和笔记本的处理器是多核的,这意味着现在开发的游戏将在一个主流为多核处理器的市场上发布;另一个趋势是笔记本市场的增长速度明显超过了台式机。这意味主要配备集成显卡的笔记本将在游戏玩家中越来越普遍。因此,如何合理利用多核系统的CPU和GPU资源将是游戏开发者需要认真考虑的问题。 本文提出了一种模型动画的多线程方案。此方案能通过利用多核处理器资源改善游戏的性能。此方案通过线程池、双缓冲和间隔更新的方法把骨骼动画的渲染管线并行化。而且,一个渲染大量动态3D模型的演示程序被开发用于验证此方案的有用性。测试表明此方案既有利于基于CPU的骨骼动画,又有利于基于GPU的骨骼动画,特别是对基于CPU的动画,通过使用这个方案,能使性能大大优于传统单线程的实现;并且,在某些高端显卡上,使用此方案的基于CPU的动画能体现了与基于GPU的动画近似的性能,而在主流的低端显卡上,更是显示了较明显的性能优势。 本文接下来的章节组织如下:第二部分介绍骨骼动画的技术和基于CPU和基于GPU实现的优缺点;第三部分阐述此方案及其实现细节,然后第四部分将介绍开发的演示程序,第五部分分析此方案的性能。第六部分提出了一些额外的考虑。最后第七部分是本文的总结。 对我有用0 丢个板砖0 引用 举报 管理 TOP 回复次数:13 lehedele (嘛钱不钱的,乐呵乐呵得了!) 等级: #1楼 得分:0回复于:2008-09-26 14:40:48骨骼动画 骨骼动画可能是今天最常用的高级实时动画技术之一。在骨骼动画中,称为“皮肤(skin)”的多边形网格随着称为“骨骼(skeleton)”的支持结构的改变而不断变换。这种根据骨骼的动画而实现的皮肤转换处理成为“蒙皮(skinning)”技术。骨骼动画系统使用转换矩阵表示一根骨骼的坐标系相对于其父骨骼的坐标系的转换关系。这些转换矩阵通常保存在模型空间中。骨架中所有骨骼的转换矩阵组成一个时间点的骨骼动画帧。每个动画集都由一系列时间点的动画帧组成。通常游戏逻辑决定当前时间内模型使用什么样的动画集,然后启动骨骼动画的渲染管线去渲染模型。这条渲染管线能被分为三个基本阶段。它们分别是“骨骼变换”、“蒙皮”和“绘制”。 第一个阶段的主要任务是变换骨骼并获得在世界空间中的骨架转换矩阵。在此阶段中,首先从一个动画集中选择两个时间点的动画帧(骨骼转换矩阵),保证当前时间位于这两个时间点中间,然后当前时间的动画帧由前后两个时间点的动画帧通过插值获得。如果此模型关联多个动画集的话,则所有插值后的动画帧被混和形成当前动画帧。最后,递归地沿着骨架层次,当前动画帧的每个骨骼的转换矩阵被转化为相对与世界坐标系的转换矩阵。通常,第一阶段在CPU上执行。 第二个阶段被称为“蒙皮(skinning)”。由于皮肤顶点相对于所在骨骼是静止的,所以可以通过变动骨骼获得新的皮肤形状。由于缺省的皮肤保存在模型空间中,因此需要根据骨骼的世界转换矩阵,把皮肤顶点也转换到世界空间中去。在阶段二的实现中,模型空间的皮肤顶点首先通过一个偏移量矩阵转换为相对于所在骨骼的坐标,然后根据第一阶段输出的骨骼的世界转换矩阵,转换为在世界空间中的皮肤顶点。有时一个皮肤顶点受多个骨骼的影响,此时要对骨骼矩阵和偏移量矩阵的乘积进行加权求和。“蒙皮”可以在CPU上执行,也可以在具有顶点着色器的GPU上执行。本文中,“基于CPU的骨骼动画”意味着由CPU处理蒙皮,而“基于GPU的骨骼动画”则表示由GPU处理蒙皮。 随着GPU的速度迅速增加以及最大程度的平行性被开发出来,用GPU处理蒙皮在诸多情况下都是有利的。一般来说,在今天的中高端独立显卡上,基于GPU的蒙皮比基于CPU的蒙皮更快并且更加节省的系统内存。然而,对于某些应用,在CPU上执行蒙皮更有好处1。在CPU上执行蒙皮能提高应用对大部分系统的兼容性。老系统上可能有不支持基于GPU蒙皮的显卡(比如GeForce2 和GeForce4MX)。而且,许多应用为了阴影体(shadow volumes)生成和冲突检测需要使用转换后的数据,但当前的显卡并不能很好地支持从显卡中大量获得已经处理过的数据。而在CPU上蒙皮允许应用很容易地访问动画后的蒙皮数据,且允许GPU做光照和裁减等运算。当然,计算阴影体可以完全放到有些显卡上,但是这种方案在今天的主流显卡上并不是特别有效。允许在GPU上进行蒙皮的显卡也可能由于一些资源上的限制,要求大的骨骼模型被分为多块小的网格才能渲染,这样会降低效率。在CPU上进行蒙皮没有上述限制,并且可以通过使用SSE指令优化和多线程优化使性能接近基于GPU的实现。正由于这些原因,一些游戏如DOOM III和Quake 4采用了基于CPU的蒙皮,使得游戏能运行在最广泛的系统配置上。 最后一个阶段是把皮肤顶点画到屏幕上。在此阶段中,在世界空间的皮肤顶点经过裁减、栅化、着色等步骤,最终画到屏幕上。此步骤由GPU完成。 对我有用0 丢个板砖0 引用 举报 管理 TOP 精华推荐:10家不错的iphone编程资源站 lehedele (嘛钱不钱的,乐呵乐呵得了!) 等级: #2楼 得分:0回复于:2008-09-26 14:41:23方案 本方案的主要目标是基于软件最大程度地挖掘骨骼动画渲染管线的并行性。方案的设计来自于一些对骨骼动画渲染管线的观察。一方面,由于涉及大量的矩阵运算,此管线是计算密集的;另一方面,不同动态模型的渲染过程通常是独立的。因此,多线程能有利于骨骼动画渲染管线的性能。而且,临近的很小时间间隔中的动画数据(例如骨架的形状)通常非常相似,因此在许多情况下(尤其是在MMORPG中),不一定需要每帧都更新模型动画。间隔地更新模型动画能减轻总线压力,改善CPU和GPU之间的并行性。 此方案包含三个部分:“线程池”、“双缓冲”和“间隔更新”。线程池中的动画线程执行动画渲染管线的第一阶段和第二阶段1。第三阶段由主线程执行,因为这个绘制阶段包含大量对图形API(例如DirectX和OpenGL)的调用,由于性能方面的问题,这些调用通常不合适放在不同的线程中执行4。此方案使用双缓冲最大化阶段三和阶段一、二之间的并行性,且简化它们的同步。最后,“间隔更新”的技巧是可供选择的,它能控制动画更新的频率。 下面的章节将描述这三大部分的细节,以及本方案的资源管理策略,此策略与传统的管理动画资源的策略略有不同。3.1 线程池 在本方案中,当渲染一个动态模型时,有一个被称为动画线程的独立线程会分配给这个模型去处理骨骼变换和蒙皮。为了并行渲染大量的动态模型,本方案采用了线程池。这主要基于如下一些优点:首先,线程池可以避免频繁创建和销毁动画线程所致的沉重代价。其次,通过使用线程池,动画线程的数目可以随着动态模型的数目和处理器核心的数目的变化,具有良好伸缩性。另外,线程池提供了一个简洁的编程接口,通过它,主线程只需要把动态模型提交到线程池的任务队列中,而不需要处理线程调度等方面的问题,这些都由线程池自动完成。使用一个良好封装的线程池,比如WIN32系统线程池,你只需要对模型类的定义做少量修改即可象如下代码所示那样实现多线程。 对我有用0 丢个板砖0 引用 举报 管理 TOP 精华推荐: 帮忙改改吧,我实在弄不出了 lehedele (嘛钱不钱的,乐呵乐呵得了!) 等级: #3楼 得分:0回复于:2008-09-26 14:43:16从上面的代码中可以看到,在类方法Animate中,通过调用一个WIN32线程池API,QueueUserWorkItem2,模型被提交到线程池。并且,通过使用这个API的第三个参数,可以说明线程池中的最大线程数。一般来说,一个应用中的活动线程数应该不大于处理器核心的数目。由于线程的切换开销,过多的线程并不会带来更多性能。 在骨骼动画的渲染管线中,由动画线程执行的阶段一和阶段二的输出,将被作为由主线程执行的阶段三的输入。因此主线程必须与动画线程同步以避免数据竞争(data racing )。上面的代码中建议了一种简单有效的同步方法:定义一个计数器计算线程池中的模型数,主线程和动画线程通过轻量级的WIN32“Interlock”同步方法3互斥地访问这个计数器。只有当这个计数器为零的时候,主线程才能开始绘制模型。3.2 双缓冲 尽管上面的同步方法避免了多线程化的管线中的数据竞争。但它使阶段三和阶段一、二只能串行执行。为了使得阶段三和阶段一、二能并行执行,本方案采用了双缓冲技术。 在模型动画中可以使用双缓冲主要基于如下假设:动画数据,例如骨架姿势和皮肤顶点,在临近的帧中是非常接近的。因此主线程可以使用前帧产生的动画数据,而不必等当前帧的最新数据。对于动画的视觉效果来说,一帧或几帧延迟的可预测的一致性行为不会影响游戏体验。 在双缓冲的实现中,被主线程和动画线程共享的所有模型动画数据都有两个拷贝存放在双缓冲中。一个缓冲被称为读缓冲,在这里主线程把动画数据读到管线的阶段三中;另一个缓冲被称为写缓冲,在这里动画线程写入管线的阶段一、二的输出数据(见图一)。两个缓冲每隔一帧或几帧被交换一次。 对我有用0 丢个板砖0 引用 举报 管理 TOP 精华推荐:【赢限量版好礼】有奖参与活动火热进行中!英特尔论坛你的充电加油站! majiajun_no_13 (majiajun_no_10) 等级: #4楼 得分:0回复于:2008-09-26 14:51:12说我恶意刷楼,冤枉啊非要我使出杀手锏不可!图1: 双缓冲的机制 当模型第一次进入摄像机的视域,模型的读缓冲中的动画数据可能要么没有准备好、要么太陈旧以至不能被主线程用来进行绘制。为了解决这个问题,每个缓冲都附带一个生命周期。当其中的动画数据被更新后,缓冲将被赋予一个新的生命周期,然后在接下来的每帧中,这个生命值会被递减。而主线程只使用生命值非负的缓冲去绘制模型。 下面的代码描述了双缓冲在模型类中的实现: 对我有用0 丢个板砖0 引用 举报 管理 TOP 精华推荐:怎么在本地用设备仿真器浏览wap网页 majiajun_no_13 (majiajun_no_10) 等级: #5楼 得分:0回复于:2008-09-26 14:52:09双缓冲避免了骨骼动画渲染管线中阶段三和阶段一、二之间的数据竞争,并且使主线程和动画线程之间的同步从帧内转移到帧间。因此在游戏循环开始的时候,主线程需要执行一些操作更新双缓冲的状态。下面的代码是双缓冲在游戏循环中的实现。 双缓冲开发了主线程和动画线程之间的最大的并行性。而且,它能方便多线程编程。例如,程序员可以假设动画数据总是可被主线程使用;以及处理一个模型的动画线程能够从另一个模型的读缓冲中获得动画数据,这使得其他并行处理得以实现,比如并行的模型间冲突检测。双缓冲技术的主要缺点是额外的内存消耗。例如,当使用基于CPU的蒙皮技术渲染100个模型时,假设每个模型有5000个顶点,每个顶点有32字节,那么额外的内存开销有16兆字节。 对我有用0 丢个板砖0 引用 举报 管理 TOP 精华推荐:windows mobile上用C+开发GUI应用有什么成熟的常用的界面库吗? majiajun_no_13 (majiajun_no_10) 等级: #6楼 得分:0回复于:2008-09-26 14:53:253.3 间隔更新 在一些MMORPG的游戏场景中有大量的动态3D模型,这些模型通常被称为PC (Player-Character,玩家角色) 或NPC (Non-Player-Character,非玩家角色)。NPC由游戏控制。在许多情况下,这些NPC的动作经常是简单的、并非快速移动的。由于临近的短时间间隔中的动画数据(例如骨架姿势)非常接近,因此,在这些情况下,并不必要每一帧都更新这些模型的动画。实事上,传统基于CPU的蒙皮常慢于基于GPU的蒙皮的一个主要原因是大量的皮肤顶点频繁地上传到显卡,以至于CPU与GPU之间的总线带宽成为瓶颈。本方案建议了一个技巧:每隔几帧才更新某些模型的动画数据,这样能减轻总线流量的压力,且提高渲染的效率。下面的代码是间隔更新技巧在主循环中的实现。下面的代码是间隔更新技巧在模型类中的实现。 对我有用0 丢个板砖0 引用 举报 管理 TOP majiajun_no_99 (马甲军) 等级: #7楼 得分:0回复于:2008-09-26 15:05:14巨汗,这帖子发了半小时还没发完,郁闷!还得不停的借别人的号才能继续发帖!强烈鄙视!实际的更新模型动画的频率等于帧速率除以更新间隔。当间隔为1,本方案即与传统方法一样每帧更新动画。当间隔增加时,帧速率通常也会相应增加,但更新频率有可能下降。因此在实际游戏中,开发者需要选择合适的更新间隔,使动画更新的频率保持在一个合理的范围内。 除了减轻总线传输的压力外,间隔更新与多线程结合时还体现了另一个好处。由于间隔更新允许动画任务的执行时间跨越多个帧,这使动画线程能有足够的时间处理一些耗时的动画任务,并且很少影响主线程的速度。3.4 资源管理 3D 模型的资源包含顶点缓冲,索引缓冲和纹理等。在处理模型动画时,CPU 和 GPU 会经常访问这些资源,因此这些资源的位置和使用方式将对骨骼动画渲染管线的性能产生重要的影响6。 对于基于 GPU 的动画,渲染管道的大部分负载由显卡承担。在DirectX9中,这些资源通常作为“默认资源”或“托管资源”保存在本地显存中,使GPU能快速存取。此策略仍适用于本文建议的方案。 对基于CPU的动画,诸如网格顶点缓冲的资源会被CPU频繁更新。通常情况下,最好将这类资源作为“动态默认资源”置于非本地显存(如 AGP 显存)中。例如,在具体实现中,可以使用DirectX的POOL_DEFAULT标记和USAGE_DYNAMIC提示创建模型网格的顶点缓冲5。尽管上述资源管理策略最有利于传统基于CPU的动画,但获得的性能在大多数情况下依然无法和基于GPU的动画相比,这是由几方面的因素导致的。在资源管理方面有两个主要原因:1)GPU对“本地”显存的存取速度要远高于“非本地”显存;2)基于CPU动画每帧都需要上传网格顶点数据到GPU,这容易使总线成为瓶颈。 本文建议的方案能间隔地更新模型动画。这样网格顶点等资源不需要每帧都上传到显卡中。通过间隔更新,此方案使模型动画的动态资源转变为半动态的资源。通常把这类资源作为DirectX的“托管资源”而不是“动态默认资源”来管理更加合理。DirectX会把这类资源放在恰当的位置,使CPU和GPU能高效地访问它们。 使用“托管资源”的另一个理由是它使DirectX与本方案的多线程上下文具有更好的兼容性。演示应用 为了检验此方案是否行之有效,我们开发了一个渲染大量3D模型动画的演示应用。这个演示程序改进了DirectX的例程“MultiAnimation”7,实现了基于CPU和基于GPU的骨骼动画,并且同时支持单线程和多线程版本。 本演示展示了许多模型在一个平面地板上漫步的场景。用户或应用(在缺省状态下)可以控制这些模型。每个模型都拥有三个动画集,即闲走、行走和慢跑。动画控制器会将这些动画集融合在一起,确保每个动画可以平滑过渡至下一个动画。这些模型之间会做碰撞检测,可以互相阻碍彼此的运动。通过回调系统,模型可在动画中适当的情况下播放脚步声。在本演示中,动画线程执行的动画任务包括动画集融合、骨架变换和蒙皮(针对基于 CPU 的解决方案)三项工作。演示程序只处理在摄像机视截体中的模型的动画和绘制。在应用控制的模式下,能通过“箭头”键移动摄像机。在用户控制模式下,可以通过“A/W/D”键控制某个被选模型的移动,而摄像机则会跟随模型。图 2: 演示应用的屏幕截图 一个配置文件用于初始化演示应用进入各种运行模式。您可以采用下列 4 个选项配置演示程序:Method:选择基于 CPU 的蒙皮或基于 GPU 的蒙皮;Threads:线程池中的动画线程的数量。“非零”表示使用本文建议的多线程方案;“零”表示传统的单线程版本;Models:初始的模型数量;Interval:一个动画更新间隔所包含的帧数。此选项只在本文建议的方案中有效。 对我有用0 丢个板砖0 引用 举报 管理 TOP majiajun_no_99 (马甲军) 等级: #8楼 得分:0回复于:2008-09-26 15:09:06性能分析表 1: 测试平台配置性能测试和等级评定均使用特定的计算机系统和/或组件进行测量。这些测试反映了英特尔产品的大致性能。系统
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 初中数学《平方根与立方根》(第4课时)课件+北师大版八年级数学上册
- 重庆法律知识培训报价课件
- 重庆播音主持课件
- 重庆山体滑坡应急课件
- 新解读《GB-T 2816-2014井用潜水泵》
- 重庆一中课件跑操
- 老年人防护知识培训课件
- 重卡新能源产品知识培训课件
- 社会科学研究方法 课件 第三章 选题与文献回顾
- 企业中高层领导培训之企业文化落地
- 2025至2030中国竹纤维行业市场行业市场深度研究及发展前景投资可行性分析报告
- 豆芽成长记录课件
- 公路施工应急预案
- 2025年工业机器人操作员技能考核题库及参考答案解析
- 2024-2025学年北京市海淀区七年级下英语期末考试题(含答案和音频)
- 2025年本科院校基建处招聘笔试预测试题及答案
- 商业租赁纠纷常见法律问题实务分析
- 2025-2026学年青岛版(2017)小学科学五年级上册教学计划及进度表
- 市场监管局计量监管课件
- 直肠恶性肿瘤护理查房
- 浙江省杭州市钱塘区八年级下学期期末科学试卷
评论
0/150
提交评论