`

写一个DX8的屏幕保护程序-------Alpha 闪烁效果

 
阅读更多
<iframe align="center" marginwidth="0" marginheight="0" src="http://www.zealware.com/csdnblog.html" frameborder="0" width="728" scrolling="no" height="90"></iframe>

Alpha 闪烁效果

Philip Taylor
2000年9月

下载本文的源代码 (521 KB)

欢迎阅读 Driving DirectX。这个月,我将通过开发一个使用 alpha 的 Direct3D 屏幕保护程序继续对 alpha 混色进行探索。

Sparkles 屏幕保护程序的屏幕快照

图 1. MSDNSparkles 屏幕快照

图 1 显示了该示例的一个屏幕快照;要想真正欣赏这些图像,您必须花上一定的时间来观察屏幕保护程序的形态变化。

根据 Direct3D "ScreenSaver" 示例,MSDNSparkles 屏幕保护程序将一个粒子系统与一些随机的戏法结合起来;如果这种方式与 alpha 混色相结合,就会产生梦幻般的图像。这是一个使用 ONE:ONE 操作符进行加色的示例,这会产生一些确实有趣的发光效果。

在本专栏中,我将简要概括 Direct3D 屏幕保护示例的框架,然后深入介绍 MSDNSparkles 实现其戏法的细节。我不会涉及编写 Win32 屏幕保护程序的细节,但您可以在 MSDN 上搜索讨论这一主题的文章。

引言

Direct3D 屏幕保护程序的框架由两部分组成:骨架和应用程序提供的函数,这些函数由每个屏幕保护程序覆盖。图 2 显示了 SDK 的屏幕保护程序样本工程视图。Screensaver.cpp 提供了一个使 D3DFrame 屏幕保护程序能够运行的骨架,如 d3dapp.cpp,而 d3dapp.cpp 反过来又提供了 D3DFrame 应用程序的骨架。只要提供覆盖的函数就可以得到一个屏幕保护程序。请记住,如果要对屏幕保护程序进行测试,则需要使用一个命令行参数 –s 从 Visual C++ 中将其启动。

屏幕快照

图 2. Direct3D 屏幕保护程序样本项目视图

该骨架使用了一些类似于那些 D3DFrame 应用程序用于执行初始化、关闭和着色的函数。这些函数的原型—Initialize3DEnvironmentCleanup3DEnvironmentRender3DEnvironment— 如下所示。

//--------------------------------------------------------------------------// 局部函数原型//--------------------------------------------------------------------------HRESULT Initialize3DEnvironment( HWND );HRESULT Render3DEnvironment( HWND );VOID    Cleanup3DEnvironment( HWND );

这三个函数将完成设置 Direct3D、关闭 Direct3D 和对场景进行着色的所有操作。屏幕保护程序必须完成的所有工作就是实现可以被覆盖的函数。这些函数类似于我们已经逐渐了解和喜爱的 D3Dframe 对应函数;请参见下面的函数原型。

//--------------------------------------------------------------------------// 外部函数原型//--------------------------------------------------------------------------HRESULT App_ConfirmDevice( DDCAPS*, D3DDEVICEDESC* );HRESULT App_OneTimeSceneInit();VOID    App_DeleteDeviceObjects( HWND, LPDIRECT3DDEVICE7 );HRESULT App_InitDeviceObjects( HWND, LPDIRECT3DDEVICE7 );HRESULT App_FrameMove( LPDIRECT3DDEVICE7, FLOAT );HRESULT App_Render( LPDIRECT3DDEVICE7 );HRESULT App_RestoreSurfaces();HRESULT App_FinalCleanup();

我使用了示例中的 screensaver.cpp,并做了最少的改动。我的确发现,从注册表中读取配置数据的调用需要将参数由:

      if( ERROR_SUCCESS == RegOpenKeyEx( HKEY_CURRENT_USER, strRegPath,                                           KEY_READ, NULL, &hKey ) )

调换为:

      if( ERROR_SUCCESS == RegOpenKeyEx( HKEY_CURRENT_USER, strRegPath,                                           NULL, KEY_READ, &hKey ) )

该示例也未能对着色窗口可能的移动进行处理,因此我在调用 TestCooperativeLevel() 之后把以下程序块加入了 Render3Denvironment() 函数。

   //请确保在屏幕控制面板中进行操作,监视事物的移动   RECT rTmp;   GetWindowRect( hWnd, &rTmp );      g_pFramework->Move(rTmp.left, rTmp.top );

Direct3D 屏幕保护程序框架确实给出了 ConfigureDialog 函数的开始部分以及一种用于存储配置数据的方法,但我尚未针对 MSDNSparkles 对其进行扩充,因为它不是一个关键细节。

样例屏幕保护程序的另一个“特征”是:它使用 WM_TIMER 对着色进行控制。在基于 Windows 2000 的操作系统上,这会产生一个适当的帧速率,但基于 Windows9x 的操作系统并不具有这样一个允许使用良好帧速率的 WM_TIMER 间隔尺寸。考虑到这种情况,我重新编写了这个屏幕保护程序,使其使用线程对着色进行控制。我没有将这部分代码包括进来,因为它是一个简单明了的线程实现。有兴趣的程序员可以考虑增加多监视器功能、电源管理和口令,因为 Direct3D 屏幕保护程序框架没有提供这些功能。

高级别视图

既然这些细节已不成为问题,我们就可以开始了。图 3 显示了 Visual Studio Workspace 窗口针对 MSDNSparkles 示例的内容。该项目由 screensaver.cpp 文件(它是从 Direct3D 示例中得到的,如上面的讨论所述)以及 sparkles.cpp 组成。

屏幕快照

图 3. MSDNSparkles项目视图

Sparkles.cpp 包含两组函数。第一组是可以覆盖的函数,我会在后面对其进行考查。第二组包含了闪烁效果函数。为了对闪烁效果函数进行处理,MSDNSparkles 定义了它自己的小型 API,它们是 RandomTextureRandomSparkleInitSparklesUpdateSparkleDrawSparkle

// 闪烁效果函数Int RandomTexture(int overflow);Sparkle RandomSparkle(void);Void InitSparkles(void);Void UpdateSparkles(void);BOOL DrawSparkles(LPDIRECT3DDEVICE7 lpDev, D3DVECTOR from, D3DVECTOR at);

除了 RandomTexture 以外,所有这些函数都对 Sparkle 结构进行操作。Sparkle 结构包含用于每个粒子的外观和行为的信息,而每一个粒子都作为粒子系统的一部分。

//闪烁效果的结构typedef struct t_sparkle {   int         texture;   int         age, cur_age;  // start at age and tick down to 0   float       scale, delta_scale;   D3DVECTOR   position;   D3DVECTOR   velocity;   D3DVECTOR   color;} Sparkle;

元素 positionvelocity,随同 scaledelta_scale 一起由粒子系统使用,用于生成粒子的各个位置。元素 texturecolor 定义作为外观随机化算法一部分的粒子外观。

外观随机化通过使用一个衰老系统对转换进行控制,其中,元素 agecur_age 给出了一个倒计时系统。转换发生的方式有三种:

  • 当某纹理的时限到期时,从列表中随机选择一种纹理。

  • color_mode 用来生成一种基色。

  • color_modifier_mode 用来以一些有趣的方式对基色进行修改。

这些随机纹理和色彩随后会对粒子的外观进行完整定义。某些精巧的随机数学方法所生成的内容确实相当奇妙。

RandomTexture 用来帮助从纹理列表中选择一种纹理。

int RandomTexture(int texture, int overflow){      int retVal;      if (texture == NumTextures)       {            retVal = overflow;// init to random from the n case, overflow      }       else       {            retVal = texture; // init to current in the 0..n-1 case      }      return retVal;}

RandomSparkle 通过生成一些颜色增量值开始。它随后开始着手置入一个 Sparkles 结构,该结构用时限、标度和位置值来表示粒子。闪烁效果的纹理是通过调用 RandomTexture 选择的。随后,color_modecolor_modifier_mode 被用来生成该粒子的颜色。

Color_mode 确定哪一种方法被用于生成基本颜色,随机模式还是 rgb 颤动模式。随机模式只是随机地选取一种颜色。而 RGB 颤动模式则进行一些精巧的颜色增量计算,在某一颜色范围内平滑地移动。Color_modifier_mode 控制着基色的修改。可以选择四种变量:饱和色、宝石色、柔和色或亮色。这些模式中的每一种都执行一种略微不同的计算,借以对基色进行修改。

Sparkle RandomSparkle(void){      Sparkle     ret;      static float      red = 1.0f, grn = 1.0f, blu = 1.0f;      static float      d_red = -(min_color_delta + rnd()*max_color_delta);      static float      d_grn = -(min_color_delta + rnd()*max_color_delta);      static float      d_blu = -(min_color_delta + rnd()*max_color_delta);      ret.age           = min_age + (int)(rnd() * (max_age-min_age));      ret.cur_age       = ret.age;      ret.scale         = start_scale;      ret.delta_scale   = min_delta + rnd() * (max_delta - min_delta);      ret.position      = D3DVECTOR(world_size * (rnd()-rnd()),                                     world_size * (rnd()-rnd()),                                     world_size * (rnd()-rnd()));      ret.velocity      = D3DVECTOR(0.0f);      ret.texture       = RandomTexture(rand() % (NumTextures-1));      switch (color_mode) {            case 0 : //随机                  ret.color = D3DVECTOR(rnd(), rnd(), rnd());                  break;            case 1 : //rgb 颤动                  red += d_red;                  if (red > 1.0f) {                        red = 1.0f;                        d_red = -(min_color_delta + rnd()*max_color_delta);                  } else if (red  1.0f) {                        grn = 1.0f;                        d_grn = -(min_color_delta + rnd()*max_color_delta);                  } else if (grn  1.0f) {                        blu = 1.0f;                        d_blu = -(min_color_delta + rnd()*max_color_delta);                  } else if (blu 

InitSparkles 选择起始纹理,然后为粒子列表分配内存。一个粒子基本上是由两个三角形构成的四边形。对粒子的说明,请参见图 4。

粒子示意图

图 4. 粒子

接下来,每个闪烁效果都通过 RandomSparkle 被随机地初始化。最后,为每个粒子生成索引绘图的下标。

void InitSparkles(void){    texture = 1;// 以 dx7 位图开始   sparkle = (Sparkle *)malloc(nMaxNumSparkles * sizeof(Sparkle));   for (UINT i=0; i<ncurnumsparkles i sparkle randomsparkle for s_indices initsparkles><p><b><font face="arial">UpdateSparkles</font></b> 将 <b>texture_age</b>、<b>color_age</b> 和 <b>color_modifier_age</b> 的当前值递减。随后,如果时限值已经倒数至 0,则会生成 <b><font face="arial">texture</font></b> (使用 <b><font face="arial">RandomTexture</font></b>)、<b><font face="arial">color_mode</font></b> 以及 <b><font face="arial">color_modifier_mode</font></b> 的新的随机值。此操作一旦完成,<b><font face="arial">RandomSparkle</font></b> 将被再次用来随机生成每个粒子下一帧的位置、纹理和颜色。最后对标度进行调整。</p>
<pre class="clsCode">void UpdateSparkles(void){   UINT  i;//0..n 0..n-1==当前,n==随机   texture_age--;   if (texture_age == 0) {      texture_age = min_texture_age + (unsigned int)(rnd() * (max_texture_age - min_texture_age));      texture = rand() % (NumTextures);      texture = RandomTexture(rand() % (NumTextures-1));   }//0..1 0==随机,1==rgb 颤动   color_age--;   if (color_age == 0) {      color_age = min_color_age + (int)(rnd()*(max_color_age – min_color_age));      color_mode = rand() % NumColorModes;   }//0..5 0==无变化,1==饱和色,2==宝石色,3==柔和色,   //     4==亮色,5==暗色和冷色,<br>但不适用于大多数情况,   color_modifier_age--;   if (color_modifier_age == 0) {      color_modifier_age = min_color_modifier_age + (int)(rnd()* (max_color_modifier_age - min_color_modifier_age));      color_modifier_mode = rand() % NumColorModifierModes;   }   //更新闪烁效果   for (i=0; i<ncurnumsparkles i sparkle if randomsparkle updatesparkles><p><b><font face="arial">DrawSparkles</font></b> 对粒子系统定位代码中使用的前面方向进行计算。该值被用来生成每个粒子各顶点的偏移量。图 5 对此进行了说明。</p>
<img alt="粒子定位示意图" border="0" height="300" src="http://www.microsoft.com/china/msdn/images/directx0900-5.gif" width="300"><p><b>图 5. 粒子定位</b></p>
<p>为了提高效率,闪烁效果按绘制的纹理进行排序。索引列表及 <b><font face="arial">DrawIndexedPrimitive</font></b> 用来绘制粒子系统的四边形。</p>
<pre class="clsCode">BOOL DrawSparkles(LPDIRECT3DDEVICE7 lpDev, D3DVECTOR from, D3DVECTOR at){      D3DVECTOR   view_dir, position, dx, dy;      UINT        i;      view_dir = Normalize(at - from);      dx = CrossProduct(view_dir, D3DVECTOR(0.0f, 1.0f, 0.0f));      dy = CrossProduct(view_dir, dx);      dx = CrossProduct(view_dir, dy);      // 绘制闪烁效果      // 为提高效率,我们要将所有使用相同纹理的闪烁效果      // 批量处理并只进行一次 DrawPrim 调用      int   flags[NumTextures];      for (int tex=0; tex<numtextures tex flags for i if continue lpdev->SetTexture(0,g_ptexSparkleTextures[tex]);                        //建造用于批处理的四边形            int   num = 0;            for (i=0; i<ncurnumsparkles i if tex continue d3dvector sx="dx" sparkle sy="dy" float color_scale="(float)sparkle[i].cur_age" cur_color="sparkle[i].color" d3dcolor color="D3DRGB(cur_color[0]," position="sparkle[i].position;" s_mesh d3dlvertex num>DrawIndexedPrimitive(D3DPT_TRIANGLELIST,                                           D3DFVF_LVERTEX, (LPVOID)s_mesh,                                           4*flags[tex], s_indices,                                           6*flags[tex], 0) != D3D_OK)                  return FALSE;      }      return TRUE;}     // DrawSparkles() 结束</ncurnumsparkles></numtextures></pre>
<p>图 6 和图 7 显示了由 alpha 混色粒子系统产生的图像的附加屏幕快照。</p>
<img alt="屏幕保护程序的屏幕快照" border="0" height="338" src="http://www.microsoft.com/china/msdn/images/directx0900-6.jpg" width="450"><p><b>图 6. <font face="arial">MSDNSparkles</font> 屏幕快照 2</b></p>
<img alt="屏幕保护程序的屏幕快照" border="0" height="338" src="http://www.microsoft.com/china/msdn/images/directx0900-7.jpg" width="450"><p><b>图 7. <font face="arial">MSDNSparkles</font> 屏幕快照 3</b></p>
<p><b><font class="105v"><font face="arial">MSDNSparkles 的内部构件</font></font></b> </p>
<p>让我们继续探讨过载应用程序函数的实现过程。我在下面重新列出了函数的原型,这样您就不必回卷到本文开始的地方。我将对 Direct3D 屏幕保护程序框架允许覆盖的每个过载函数进行考查。</p>
<pre class="clsCode">//--------------------------------------------------------------------------// 外部函数原型//--------------------------------------------------------------------------HRESULT App_ConfirmDevice( DDCAPS*, D3DDEVICEDESC* );HRESULT App_OneTimeSceneInit();VOID    App_DeleteDeviceObjects( HWND, LPDIRECT3DDEVICE7 );HRESULT App_InitDeviceObjects( HWND, LPDIRECT3DDEVICE7 );HRESULT App_FrameMove( LPDIRECT3DDEVICE7, FLOAT );HRESULT App_Render( LPDIRECT3DDEVICE7 );HRESULT App_RestoreSurfaces();HRESULT App_FinalCleanup();</pre>
<p><b><font face="arial">ConfirmDevice</font> </b></p>
<p>MSDNSparkles <b><font face="arial">App_ConfirmDevice</font></b> 函数验证设备是否能够进行 ONE:ONE alpha 混色。这是 alpha 最简单的形式 — 并且,根据我的经验,所有的显卡都可以执行这种 alpha 混色。下面是 MSDNSparkles 实现 <b><font face="arial">App_ConfirmDevice</font></b> 的过程。</p>
<pre class="clsCode">HRESULT App_ConfirmDevice( DDCAPS* pddDriverCaps,                           D3DDEVICEDESC7* pd3dDeviceDesc ){   // 获取 triangle caps(硬件或软件),并检验 alpha 混色   LPD3DPRIMCAPS pdpc = &amp;pd3dDeviceDesc-&gt;dpcTriCaps;   if( 0 == ( pdpc-&gt;dwSrcBlendCaps &amp; pdpc-&gt;dwDestBlendCaps &amp; D3DBLEND_ONE ) )      return E_FAIL;    return S_OK;} </pre>
<p><b><font face="arial">OneTimeSceneInit</font> </b></p>
<p><b><font face="arial">App_OneTimeSceneInit</font></b> 函数首先给随机数生成器播种,并设置背景颜色和初始化纹理列表。然后,它使用纹理列表创建 MSDNSparkles 使用的纹理。最后,调用 <b><font face="arial">InitSparkles</font></b> 对粒子系统进行初始化。</p>
<pre class="clsCode">HRESULT App_OneTimeSceneInit(){   // 给随机数生成器播种   srand(time(0));   //初始化背景颜色   bckColor = D3DRGB(0,0,0);   //装载纹理数据   memcpy(g_szSparkleTextures[0],"dx5.bmp",sizeof("dx5.bmp"));   memcpy(g_szSparkleTextures[1],"dx7.bmp",sizeof("dx7.bmp"));   memcpy(g_szSparkleTextures[2],"flare1.bmp",sizeof("flare1.bmp"));   memcpy(g_szSparkleTextures[3],"flare2.bmp",sizeof("flare2.bmp"));   memcpy(g_szSparkleTextures[4],"flare3.bmp",sizeof("flare3.bmp"));   memcpy(g_szSparkleTextures[5],"flare4.bmp",sizeof("flare5.bmp"));   memcpy(g_szSparkleTextures[6],"flare5.bmp",sizeof("flare5.bmp"));   memcpy(g_szSparkleTextures[7],"flare6.bmp",sizeof("flare6.bmp"));   memcpy(g_szSparkleTextures[8],"flare7.bmp",sizeof("flare7.bmp"));   memcpy(g_szSparkleTextures[9],"flare8.bmp",sizeof("flare8.bmp"));   memcpy(g_szSparkleTextures[10],"shine1.bmp",sizeof("flare1.bmp"));   memcpy(g_szSparkleTextures[11],"shine2.bmp",sizeof("flare2.bmp"));   memcpy(g_szSparkleTextures[12],"shine3.bmp",sizeof("flare3.bmp"));   memcpy(g_szSparkleTextures[13],"shine4.bmp",sizeof("flare5.bmp"));   memcpy(g_szSparkleTextures[14],"shine5.bmp",sizeof("flare5.bmp"));   memcpy(g_szSparkleTextures[15],"shine6.bmp",sizeof("flare6.bmp"));   for ( int i = 0; i <p><b><font face="arial">InitDeviceObjects</font> </b></p><p><b><font face="arial">App_InitDeviceObjects</font></b> 函数使用 helper 函数 <b><font face="arial">SetTextureState</font></b>、<b>SetRenderState</b> 和 <b>SetViewState</b>。这些函数分别对纹理列表、应用程序所使用的着色状态和查看系统进行设置。请注意,已启用了alpha 混色,混色状态将为加色而设置成 ONE:ONE。</p><pre class="clsCode">void SetTextureState(LPDIRECT3DDEVICE7 pd3dDevice ){   // 设置纹理状态    D3DTextr_RestoreAllTextures( pd3dDevice );   // 装载纹理表面   for( int i=0; i<numtextures i g_ptexsparkletextures d3dtextr_getsurface g_szsparkletextures setrenderstate pd3ddevice alpha pd3ddevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);      pd3dDevice-&gt;SetRenderState(D3DRENDERSTATE_SRCBLEND,  srcBlend);   pd3dDevice-&gt;SetRenderState(D3DRENDERSTATE_DESTBLEND, dstBlend);   // 过滤器状态   pd3dDevice-&gt;SetTextureStageState(0,D3DTSS_MINFILTER, D3DFILTER_LINEAR);   pd3dDevice-&gt;SetTextureStageState(0,D3DTSS_MAGFILTER, D3DFILTER_LINEAR);   pd3dDevice-&gt;SetTextureStageState(0,D3DTSS_MIPFILTER, D3DFILTER_LINEAR);   // 设置非纹理着色状态   pd3dDevice-&gt;SetRenderState(D3DRENDERSTATE_DITHERENABLE, FALSE);   pd3dDevice-&gt;SetRenderState(D3DRENDERSTATE_SPECULARENABLE, FALSE);   pd3dDevice-&gt;SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, FALSE);   pd3dDevice-&gt;SetRenderState(D3DRENDERSTATE_ZENABLE, FALSE);   pd3dDevice-&gt;SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);   // 注:在 DX7 中,要关闭顶点照明,需要将 D3DRENDERSTATE_LIGHTING 设置为 FALSE   // (并改用 D3DLVERTEX 中的颜色)   pd3dDevice-&gt;SetRenderState( D3DRENDERSTATE_LIGHTING, FALSE );}void SetViewState(LPDIRECT3DDEVICE7 pd3dDevice ){   // 获取宽高比   pd3dDevice-&gt;GetViewport(&amp;vp);   FLOAT fAspect = ((FLOAT)vp.dwHeight) / vp.dwWidth;   // 设置变换矩阵   D3DUtil_SetProjectionMatrix( proj,                          g_PI/4,//1.0f;                         fAspect,                          1.0f, MAX_DIST );   pd3dDevice-&gt;SetTransform( D3DTRANSFORMSTATE_PROJECTION, &amp;proj);   D3DUtil_SetViewMatrix( view, from, at, up );   pd3dDevice-&gt;SetTransform( D3DTRANSFORMSTATE_VIEW, &amp;view);   D3DUtil_SetIdentityMatrix( world );   pd3dDevice-&gt;SetTransform( D3DTRANSFORMSTATE_WORLD, &amp;world);}HRESULT App_InitDeviceObjects( HWND hWnd, LPDIRECT3DDEVICE7 pd3dDevice ){    // 检查参数    if( NULL==pd3dDevice )        return E_INVALIDARG;   // 设置纹理状态    SetTextureState( pd3dDevice );   // 设置着色状态    SetRenderState( pd3dDevice );      // 设置查看系统    SetViewState( pd3dDevice );    return S_OK;}</numtextures></pre><p><b><font face="arial">FrameMove</font> </b></p><p><b><font face="arial">App_FrameMove</font></b> 函数使用 <b><font face="arial">UpdateSparkles</font></b> 对粒子系统模拟进行更新。</p><pre class="clsCode">HRESULT App_FrameMove( LPDIRECT3DDEVICE7 pd3dDevice, FLOAT fTimeKey ){   // 好,现在可以使用闪烁效果了   UpdateSparkles();       return S_OK;}</pre><p><b>着色 </b></p><p><b><font face="arial">App_Render</font></b> 函数相当简单。首先,我们使用时间和 <b><font face="arial">RandomViewpoint</font></b> 随时间的推移对视点进行修改。然后我们让 <b><font face="arial">DrawSparkles</font></b> 绘制粒子系统。太简单了!</p><pre class="clsCode">void RandomViewpoint(LPDIRECT3DDEVICE7 pd3dDevice,float tic){   float fromX, fromY, fromZ;   fromX = (float)sin(tic*0.59);   fromZ = (float)cos(tic*0.59);   if ( texture SetTransform( D3DTRANSFORMSTATE_VIEW, &amp;view);}HRESULT App_Render( LPDIRECT3DDEVICE7 pd3dDevice ){   static float      tic = -rnd() * 10000.0f;   // 清除取景框   pd3dDevice-&gt;Clear( 0UL, NULL, D3DCLEAR_TARGET, bckColor, 1.0f, 0L );   // 开始场景   if( FAILED( pd3dDevice-&gt;BeginScene() ) )      return S_OK; // Don't return a "fatal" error      // tic 来回移动物品   tic += 0.005f;   // 在随机定位中使用   start_scale = 0.05f + (float)(sin(tic * 0.100) + 1.0f)*0.4f;   world_size  = 0.10f + (float)(cos(tic * 0.072) + 1.0f)*10.0f;   // 修改取景框   RandomViewpoint(pd3dDevice,tic);   // 绘制闪烁效果   if (!DrawSparkles(pd3dDevice, from, at))       return E_FAIL;    // 结束场景   pd3dDevice-&gt;EndScene();   return S_OK;}</pre><p><b><font face="arial">DeleteDeviceObjects </font></b></p><p><b><font face="arial">App_DeleteDeviceObjects</font></b><i> </i>函数使纹理列表中的纹理失效。</p><pre class="clsCode">VOID App_DeleteDeviceObjects( HWND hWnd, LPDIRECT3DDEVICE7 pd3dDevice){    D3DTextr_InvalidateAllTextures();}</pre><p><b><font face="arial">RestoreSurfaces </font></b></p><p>对于 MSDNSparkles 示例,<b><font face="arial">App_RestoreSurfaces</font></b> 为空操作。</p><pre class="clsCode">HRESULT App_RestoreSurfaces(){      return S_OK;}</pre><p><b><font face="arial">FinalCleanup</font> </b></p><p><b><font face="arial">App_FinalCleanup</font></b> 函数删除闪烁效果列表所使用的内存。</p><pre class="clsCode">HRESULT App_FinalCleanup(){   free(sparkle);    return S_OK;}</pre><p>MSDNSparkles 的实现过程到此结束。当您构建这个项目时,可以通过用鼠标右键单击 MSDNSparkles.scr 文件,对产生的屏幕保护程序进行测试、配置和安装。图 6 对此进行了说明。结果是基本的,但也不无快意。</p><p><a href="http://www.microsoft.com/china/msdn/images/directx0900-8.gif" target="_blank">单击可查看较大的图像 (14.8 KB)</a></p><img alt="显示“右键单击”菜单的屏幕快照" border="0" height="280" src="http://www.microsoft.com/china/msdn/images/directx0900-8a.gif" width="400"><p><b>图 8. 单击右键可对屏幕保护程序进行测试、配置和安装</b></p><p><b><font class="105v">结语</font></b> </p><p>欢迎您反馈意见。欢迎通过下面的地址给我写信,请附上您的意见、问题、对专题的看法,或是您自己关于本专栏所涉及专题的观点变化的链接。尽管如此,请不要期待个别回信或向我发送需求技术支持的问题。请记住,Microsoft 保持着一个活跃的邮件列表 <b><font face="arial">DirectXDev</font></b>,它是一个志趣相投的开发人员共享信息的论坛。可以在 <a href="http://discuss.microsoft.com/archives/DIRECTXDEV.html">http://DISCUSS.MICROSOFT.COM/archives/DIRECTXDEV.html</a>(英文)找到相应的 Web 界面。提问前请阅读 <a href="http://msdn.microsoft.com/library/default.asp%20URL=/library/techart/dxfaq2.htm">http://msdn.microsoft.com/library/techart/dxfaq2.htm</a>(英文)上的常见问题解答。</p><br><br><br></pre></ncurnumsparkles></pre></ncurnumsparkles>
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics