小技巧:使用DirectX9进行遮盖剔除-游戏开发频道-中国IT实验室-技术·资讯·教育·服务·社区
首页 | 互联网 | IT动态 | IT培训 | Cisco | Windows | Linux | Java | .Net | Oracle | 软件测试 | C/C++ | 嵌入式开发 | 存储世界 | 服务器
网络设备 | IDC | 安全 | 求职招聘 | 数字网校 | 网页设计 | 平面设计 | 技术专题 | 电子书下载 | 教学视频 | 源码下载 | 搜索 | 博客 | 论坛
 您现在的位置: 中国IT实验室 >> 游戏开发 >> 游戏开发入门 >> 正文
小技巧:使用DirectX9进行遮盖剔除
来源:ChinaItLab 作者: 时间:2004-12-27


  对象剔除是图形编程中一个重要的方面。渲染那些看不见的物体是十分耗时的。然而,就目前来说当务之急是优化剔除算法本身。因为通常剔除算法会消耗大量的处理时间。
  
  传统的算法对于一般情况的处理已经提升得很快了也改进得足够多了,但还是留下了些许遗憾。一些算法剔除了太多的物体,而另一些剔除的数量却不够多。
  
  遮盖剔除的原理告诉我们一个事实,那就是一个物体即便在视锥内,仍有可能被遮住而看不见。
   
  这里,如图1.1所示,有五个多边形被显示在屏幕上。然而,在最后的渲染结果中(如图1.2所示),实际只有三个物体可以看得见。简单的视锥剔除算法会导致所有的物体都被渲染,原因是它们都在视锥内。就象在图1.1中一样,即使另外两个物体完全被遮住,它们仍会被渲染,这将耗费许多时间。
  
  遮盖剔除通常会判断哪个物体会真正看得见,只有这些物体才会被渲染,从而节省了大量的时间。遮盖物(occluder)就是那些以遮住其它物体的东西(比如:图1.1中的那个巨大的红色盒子)。部分被遮盖的物体就是那些只能部分看见的物体(蓝色的五边形和紫色的楔形),这是需要被渲染的。完全被遮的物体就是完全看不见的物体(绿色的球体和桔红色的盒子),它们在渲染过程中将被排除掉。
  
  关于遮盖剔除的更多信息,请参看由Tomas Möller 和 Eric Haines写的Occlusion
  
  Culling Algorithms地(Occlusion Culling Algorithms)
  
  介绍IDirect3DQuery9
  
  IDirect3DQuery9 接口是Directx9的一个新特性。它允许开发人员能访问大量的统计数据,这其中包括优化信息、由资源管理器所处理的对象以及三角形处理信息。
  
  IDirect3DQuery9 还能执行遮盖请求,它将计算在屏幕上可见的象素数目。只有在请求开始和请求结束之间渲染的象素才会被计算在内。如果计算的结果为0,那么说明物体的所有顶点都被遮住了,这个物体就当前摄像机所处的位置来说是看不见的。另外,如果计算的结果是大于0的,那么物体是可见的。
  
  Query Type Datatype Use
  D3DQUERYTYPE_VCACHE D3DDEVINFO_VCACHE Information about optimization,
  
  pertaining to data layout for vertex caching
  D3DQUERYTYPE_RESOURCEMANAGER D3DDEVINFO_RESOURCEMANAGER Number of objects
  
  sent, created, evicted, and managed in video memory
  D3DQUERYTYPE_VERTEXSTATS D3DDEVINFO_D3DVERTEXSTATS Number of triangles that
  
  have been processed and clipped
  D3DQUERYTYPE_EVENT bool For any and all asynchronous events issued from API
  
  calls
  D3DQUERYTYPE_OCCLUSION DWORD The number of pixels that pass Z-testing, or
  
  are visible on-screen.
  Table 2.1: Uses of IDirect3DQuery9
  
  ATI的Occlusion Query(http://www.ati.com/developer/samples/dx9/OcclusionQuery.html)演示给出了使用IDirect3DQuery9的基础。
  
  使用 DirectX9进行遮盖剔除
  IDirect3DQuery9的出现提供了一个简单而有效的遮盖剔除的方法。基本过程如下:
  
  1. 渲染各物体的包围网格(bounding mesh)。
  2. 对每一个物体执行如下操作:
  A。开始询问。
  B。再一次渲染各物体的包围盒。
  C。终止询问。
  D。获取遮盖询问的数据。如果物体可见那么数据会大于0,此物体需要进行实际的渲染。否则物体将被排除。
  
  第一步:
  对于遮盖测试物体的实际网格包含了太多的顶点,而包围网格的顶点数要少得多,它将被用作替代物。那为什么用包围网格而不是包围盒或包围球呢?
  
  图3.1各种类型的包围体
  
  图3.1展示了多种类型的包围体,包括盒体、球体和网格。注意在这个特定的例子中包围网格和包围球的顶点数目是一样的。可是,即使顶点数目比较接近,在体积的接近程度上,包围网格的体积上和原始网格的的体积是最接近的。这在遮盖处理中很重要,要不大量的顶点会错误地渲染或剔除掉。
  
  然而包围网格不能像包围盒或包围球那样通过某个算法来产生。它需要实时地建模和加载,就象普通的网格一样。每一个对象的包围网格先渲染一次以确保Z-buffer中有整个场景的深度信息。如果遮盖询问在整个场景的深度信息加入Z-buffer之前就开始了,那么即使被要求询问的物体在最终的场景里完全被遮挡住,可能也会被错误地认为是可见的。
  
  第二步:
  现在所有物体的包围网格深度数据已经在Z-buffer中了,我们还要再做一次同样的事,这一次遮盖询问将被用来判断每个物体的可视状态。如果询问后发现没有可见的象素,这个物体最后将不会被渲染。如果发现有一个或多个可见的象素点,那这个物体就会被加入到渲染处理过程里。
  
  需要重点注意的是遮盖剔除的渲染不应在全尺寸的主缓冲里进行。用一个小些的缓冲(320 X 240可以很好地工作)可以提升效率。
  
  代码
  
  类型声明
  Sobject(代码表4.1)是主对象实体。CMesh是一个封装了加载、渲染和释放ID3DXMesh接口的类。
  
  struct SObject
  {
  CMesh* meshReference;  // Reference to a mesh object
  CMesh* boundingMesh;   // Reference to low-poly bounding mesh
  
  D3DXVECTOR3 pos;     // Position of this object
  D3DXMATRIX matTranslate; // Translation matrix for this object
  
  bool render;       // If true, render the object
  float distanceToCamera; // The distance to the camera (player position)
  
  // Constructor
  SObject( CMesh* meshRef, CMesh* boundMesh, D3DXVECTOR3 position )
  {
    meshReference = meshRef;
    boundingMesh = boundMesh;
    pos = position;
    render = false;
    distanceToCamera = 0.0f;
  }
  };
  Code Listing 4.1: SObject definition
  
  对象声明
  遮盖剔除的处理过程中,我们还需要声明LPDIRECT3DQUERY9, LPD3DXRENDERTOSURFACE, LPDIRECT3DSURFACE9, 和 LPDIRECT3DTEXTURE9
  
  LPDIRECT3D9 d3dObject;         // Direct3D Object
  LPDIRECT3DDEVICE9 d3dDevice;      // Direct3D Device
  
  LPDIRECT3DQUERY9 d3dQuery;       // The occlusion query
  LPD3DXRENDERTOSURFACE occlusionRender; // Occlusion's render to surface
  LPDIRECT3DSURFACE9 occlusionSurface;  // Occlusion's surface that it uses
  LPDIRECT3DTEXTURE9 occlusionTexture;  // Texture to get surface from
  
  std::vector<SObject> objects;     // Vector of objects
  Code Listing 4.2: Declarations of objects pertaining to the occlusion
  
  culling procedure
  
  设置遮盖对象
  首先询问要被创建,此外还有纹理和要渲染的缓冲。在创建纹理过程里我们要用到D3DUSAGE_RENDERTARGET ,因为我们要在其上进行渲染。而缓冲通过LPDIRECT3DTEXTURE9 中的GetSurfaceLevel()来获得。我们还要用LPD3DXRENDERTOSURFACE 接口把Z-buffer的格式值设置成D3DFMT_D16。
  
  //-----------------------------------------------------------------------------
  // Name: SetupOcclusion()
  // Desc: Create the objects needed for the occlusion culling
  //-----------------------------------------------------------------------------
  HRESULT SetupOcclusion()
  {
  // Create the query
  d3dDevice->CreateQuery( D3DQUERYTYPE_OCCLUSION, &d3dQuery );
  
  // Get the display mode to obtain the format
  D3DDISPLAYMODE mode;
  d3dDevice->GetDisplayMode( 0, &mode );
  
  // Create the texture first, so we can get access to it's surface
  if( FAILED( D3DXCreateTexture( d3dDevice, 320, 240, 1,
  
  D3DUSAGE_RENDERTARGET,
                  mode.Format, D3DPOOL_DEFAULT,
  
  &occlusionTexture ) ) )
  {
    return E_FAIL;
  }
  
  // Obtain the surface (what we really need)
  D3DSURFACE_DESC desc;
  occlusionTexture->GetSurfaceLevel(0, &occlusionSurface);
  occlusionSurface->GetDesc(&desc);
  
  // Create the render to surface
  if( FAILED( D3DXCreateRenderToSurface( d3dDevice, desc.Width,
  
  desc.Height, desc.Format,
                      TRUE, D3DFMT_D16,
  
  &occlusionRender ) ) )
  {
    return E_FAIL;
  }
  
  return S_OK;
  }
  Code Listing 4.3: The SetupOcclusion() function
  
  剔除物体
  Occlusion
【责编:admin】

中国IT教育热线咨询

相关文章
dx8中关于用索引缓冲渲染索引图元
作为一个状态机的OpenGL
OGRE中的四元数与旋转
[RGSS]Sprite类方法教学
[RGSS]去掉“战斗|逃跑”选项
推荐文章

 精彩友情推荐
·Asp源码 PHP源码
·CGI源码 JSP源码
·建站书籍教程
·服务器软件 .net源码
·建站工具软件
·IDC资讯大全
·机房品质万里行
·IDC托管必备知识
·全国IDC报价
·网站推广优化
 基础入门  开发文档
 最新推荐
  多数的Windows程序都需要Windows.h和Windowsx.h这两个头文件,要确保使用它们。当然,你还需要其它......
游戏引擎演化史
在Windows上安装OGRE的方法
关于滤镜遮罩概念,Sobel 遮罩
游戏开发新手入门之Windows编程
游戏开发新手入门之位图化图形
教你实现卡通渲染的另类勾边方法
游戏设计大师谈如何成为一名游戏设
Visual C#编写 3D游戏框架示例
真正的 Java 学习从入门到精通
游戏开发经验——游戏开发的基本常
  为什么要研究攻击行为在人类有记载的5600年的历史中,共计发生了14,400次战争;今天,平均一天要发生............
游戏开发中显示对话的特殊句法
游戏原型设计的介绍
网络游戏中的攻击行为
谈动作类游戏的必要条件
规则的多元分析模式
载入位图文件到DirectDraw
Archer Game Suite 是什么?
浅谈游戏企划-新手入门篇
暴雪称霸游戏业界的六大秘密绝招
骨骼动画及示例Skinned Mesh的解析
  培训中心