GAIA引擎是Greg Snook在书籍 Real-Time 3D Terrain Engines Using DirectX 9 中随书附带的一个地形引擎。该书后来又被承天一翻译成了中文版,名叫《实时地形引擎》。
参考:https://blog.csdn.net/hefengscu/article/details/38314993
参考2:https://www.cnblogs.com/wonderKK/archive/2012/02/15/2353079.html
参考3:https://dev.gameres.com/Program/Visual/3D/RealTime3DTerrainEngines1_6.pdf
目录
感谢 7
【第一部分】 3D 基础知识 8
第一章 DirectX 9.0 和 D3DX 入门 9
设置 Visual Studio.Net 10
Direct3D 示例程序框架 11
使用 D3DX 数学库 12
Direct3D 坐标系统 13
D3DX 向量和点 14
标准向量 15
点乘 18
叉乘 18
D3DX 矩阵 20
四元数旋转 21
参考
第二章 基本三维物体 22
基本 Direct3D 对象 23
使用 D3DX 加载和显示模型 24
使用 Direct3D 效果(Effect)文件 24
D3DX 框架(FRAME)和网格容器 30
骨骼动画和蒙皮网格 32
参考 34
第三章 高级着色语言 35
HLSL 着色器格式 36
变量和数据类型 37
表达式和内置函数 39
和纹理和采样器打交道 40
过程纹理(Procedural Texture)着色器 41
考虑旧式硬件 42
效果文件里的 HLSL 函数 42
第四章 Gaia 引擎总览 46
认识 Gaia,3d 地形引擎 47
主应用程序(application host) 47
创建数据池 48
管理共享数据资源 54
资源基类 57
纹理资源和表面材质 58
渲染方式资源 59
索引和顶点缓存 60
模型资源 61
场景节点和物体 63
渲染队列 63
模型编辑器 75
参考 76
【第二部分】 地形系统介绍 77
第五章 世界管理 78
场景组织背后的动机 79
基本四叉树 81
提升四叉树 82
为四叉树加入一个维度 84
快速四叉树搜索 85
慢速四叉树搜索 87
参考 91
第六章 基本地形几何体 92
以高度位图作为地形输入数据 93
程序生成的高度位图 94
中点置换法 94
柏林噪音 96
处理高度位图数据 103
地形几何体基本类 106
地形几何体的索引缓存 107
地形几何体的顶点缓存 109
渲染地形区块 114
基本地形演示 118
参考 119
第7章 THE ROAM TERRAIN SYSTEM 153
Rea-Time Optimal Adapting Meshes 154
Split Decisions 157
Implementing ROAM 159
Building ROAM Display Geometry 165
References 168
第8章 TILED GEOMETRY TECHNIQUES 169
Chunked Terrain 170
Managing Chunks of Geometry 172
Tesellting Terrain Chunks 180
Interlocking Terrain Tiles 189
A Note on LOD Popping 194
References 195
第9章 TEXTURING TECHNIQUES 197
A Great Big Blurry World 198
Blending Surface Textures 201
Nature Is Noisy 215
Frame Buffer Compositing 215
PART ||| EXTENDING THE ENGINE 221
CHAPTER 10 BIG SKY COUNTRY 223
Sky Box Methods 224
The Sky Dome 231
Animated Clouds 233
Lens Flare 235
CHAPTER 11 RENDERING 0UTD0OR SCENES 241
A Multistage Approach 242
Ambient Light 243
Bump Mapping 247
Approximating Outdoor Light 254
Bringing lt All Together 261
References 262
CHAPTER 12 THE 3D GARDENER 263
Vegetation Impostors 265
Grass |s Mother Nature's Fur 267
Amber Waves of Grain 269
CHAPTER 13 0CEAN WATER 273
An Island at Sea 274
The Water Tile 276
Animating Water 277
Rendering Water 287
The End of the Road 292
References 292
APPENDIX A GAIA UTILITY CLASSES 293
Monitoring Bit Flags 293
The Singleton Class 296
Strings 300
System Data 303
Assert, Warnings and Comments 313
Compile-Time Asserts Debug Text Messages 322
Code Timing 327
References 333
APPENDIX B FLOATING-POINT TRICKS 335
Examining Floating-Point Data 336
The Sign Bit 339
Conversion from Floating-Point to Integer Values 340
Limiting Floating-Point Precision 342
Clamping Floating-Point Numbers 344
Floating-Point Powers of TWO 347
APPENDIX C PROGRAMMING REFERENCE SHEETS 349
Intel CPU ldentification Codes 349
Direct3D HLSL Data Types 351
Direct3D HLSL Expressions 352
Direct3D HLSL Intrinsic Functions 353
Direct3D HLSL Sampler Settings 358
APPENDIX D RECOMMENDED READING 359
Mathematics 359
3D Programming 359
Academic Research 360
Other Useful Web Sites 360
Tools and Utilities 360
【第一部分】 3D 基础知识 8
要想从头开始建立一个引擎的话,我们首先得需要有良好的基础。在这一部分,我们将介绍最新的 DirectX 9.0 并且好好看一下其 SDK 里提供的 DirectX 示例框架。出于简化的考虑, 我们将把引擎建立在微软提供好的一些类上。除此以外,我们还将研究一下 DirectX9.0 的一 部分,Direct3D 扩展库(D3DX)。这个工具库将满足我们对 3D 数学库的基本需要,同时也 给我们提供了加载,维护我们游戏资源的方法。
在 DirectX 9.0 中,我们也将深入地研究 HLSL 语言,HLSL 语言是类似与 C 语言的开 发语言,它可以使着色器程序员在不借助底层汇编渲染代码的情况下编写顶点和像素着色器。 这是介绍我们今天的图形硬件 3D 着色器编程的好方法。鉴于其易用性和可读性,这本书将 集中介绍 HLSL 语言的使用而非底层汇编语言。
对于那些想要学习底层汇编语言的读者,HLSL 也可以作为一种辅助的学习手段。DirectX SDK 里的命令行式的 HLSL 编译器(fxc.exe)通过使用/Fc 命令选项可以将 HLSL 程序转换为汇 编语言文件。通过编写 HLSL 代码和查看对应的汇编代码,读者就能够更加了解这两门语言。 将某些特定的代码改由汇编代码编写也可以大大地提高 HLSL 代码的效率。
借由 DiretX 示例框架和 D3DX 扩展库我们可以快速地建立和运行我们的引擎。尽管这些 库可以满足我们这个单独程序的要求,但是它们的设计是以通用为主,而且在某种情况下是 以牺牲一定的速度来换取这种灵活性的。而当我们用地形引擎建立一个单独程序时,可能会 发现在我们的程序里或是在目标平台上有一些使用手写的方法来替代D3DX组件从而让我们 能够简化部分程序或者获取到更快的速度。为了处理好这个问题,我们将把库建立于 D3DX 和其示例框架之上来提供我们的自定义接口。稍后如果发现我们需要的与微软库提供的不符, 这一分离层设计就可以让我们重写内部实现而不需改变外层接口。
除了建立在D3D实例框架库和D3DX库之上的代码外我们还提供了自己的工具函数和一 些有用的底层类库。这些核心库提供了用来操作数值,处理浮点数,分配内存的重要接口。 除此之外,我们还提供了一些了调试,分析类让整个编码过程更加简便。在实际的编码过程 中,这些调试和分析类将帮助除去所有将来可能成为大问题的“臭虫”。
上述这些函数和类型,被称为核心库组件,你可以在附带的光盘中找到。它们的结构明 了,而且代码里已经附加上了详尽的注释。因此,在书中我们不会再细讲它们。这也就可以 让我们把更多的时间放在建立一个健壮的 3D 地形引擎上。当你在源代码里遇到这些类的时 候,请参考相关的源代码来更好的理解它们的功用吧。附录 A“Gaia 工具类”也提供了其中 一些比较常用工具类的概括介绍。同时附录 B“浮点数技巧”解释了我们引擎中部分对浮点 数类型的操作。
在这一部分的最后,我们将为第一个演示程序构建其所有的部分。这个程序是一个模型 查看工具,用来加载常用的 Direct3D X 文件格式(*.X),附上纹理,查看动画。它同时也提 供了加载和查看包含了我们将编写的 HLSL 着色器的 D3DX 效果文件(*.fx)。
第一章 DirectX 9.0 和 D3DX入门
先向那些初入微软视窗平台的三维图形编程的读者介绍一下,DirectX 是高性能的底层 库,它给我们提供了面向多种底层硬件的应用程序接口(API)。DirectX 以面向组件的方式构 成,用来直接与 PC 的关键硬件组件进行交互。对于我们的引擎,我们主要关心的是其中的 一部分,DirectX Graphics。再者,我们将与 DirectX Graphics 的 3D 功能打交道,其通常被称 为 Direct3D。DirectX 还提供了其他接口,譬如读取用户输入,产生音效,提供网络连接,但 这些都不是本书讨论的范围。
在我们进入本书之前,我们默认读者已经对 DirectX 有了大致的了解。尽管我们会提供 关于我们将使用到的 DirectX 组件的大致介绍,不过读者还是可能需要查阅 DirectX 9.0 SDK 的帮助文档来了解关于 DirectX 和 3D 编程的更多细节。一旦 SDK 安装之后,我们就可从视窗的开始菜单中打开帮助文档了。
D:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Documentation\DirectX9
第二章 基本三维物体
在对 Direct3D 示例框架和 Direct3D 扩展库有了一个扎实的了解后,我们将进一步讨论 一些我们的引擎中将使用的一些 D3DX 特性。在这一章里,我们将讨论一些在引擎中用来加 载,渲染,和保存我们的世界模型的 D3DX 类对象。我们也将讨论两种 Direct3D 主要的文件 格式,以及用来获得它们中的数据的对象。它们就是 Direct3D 效果对象及其文件格式(.fx 文件),和 Direct3D X 文件(文件扩展名为.x)。本章最后,我们会看到如何使用 D3DXFRAME 和 D3DXMESHCONTAINER 这两个结构体来为复合对象创建层次对象和骨骼动画。
如今可以说由硬盘加载模型和着色器信息的能力对于所有 3D 引擎都是很重要的。尽管 我们可以设计自己的文件格式,但既然 DirectX 已给我们提供了一种灵活的文件格式,那我 们又何必事必躬亲呢?我们还会改进用来操作 DirectX 文件的工具。这里面包含了对于流行 3D 模型和动画包的导出器,以及 DitectX SDK 提供用以编辑和查看.x 模型文件和.fx 效果 文件。Direct3D 也能够让我们用自己的数据来扩展 X 文件格式。这就为我们提供了很大的 灵活性,同时也就可以让 X 格式在将来依旧可以被我们使用而不被淘汰。
基本 Direct3D 对象
在三维空间中显示一个物体的基本三要素是:模型自身,描述模型表面的材质,可选的覆盖于模型上的纹理。先不说光照和着色,这三者就是 3D 模型渲染的基石。D3DX 提供了一 些对象来表示这些元素,以及一系列加载,操作它们的方法。
DirectX SDK 提供了对这些 D3DX 类对象的细致介绍。所以这里我们将只提供一个大概介绍,而读者若是需要了解更多内容的话,请参阅 SDK 文档。
D3DXMaterial 是这三个对象中最简明的一个了。它其实就是一个包含了代表了表面属 性的 D3DMATERIAL9 对象(包含了物体表面反射光的各种色调信息)和对应的一个纹理的文 件名的集合。虽说一个模型只使用单纹理对我们有点过时了,但我们依然使用这个结构来存 储模型基本光照信息。
IDirect3DTexture9 对象给我们提供了在渲染中操作,使用纹理资源的接口。D3DX 库包 含了一系列让程序员更易使用 IDirect3DTexture9 对象的函数。其中之一就是 D3DXCreateTextureFromFile,它可以用来从多种文件中导入纹理信息,包 括.bmp, .dds, .jpg, .png 和.tga 文件。除了支持大量文件格式外,这个 D3DX 纹理加载函 数还可以修改图像的大小,通过在导入过程中使用过滤器来改变色深。D3DX 库也包含一系 列涉及三维体纹理的函数,例如立方体纹理映射。在书后面讲到更高阶的的渲染方法后,我 们会再讨论这个问题。
ID3DXMesh 类是这三个元素的骨干成员。这个类包含了模型的几何体信息,和描述模型 顶点格式的内容。D3DX 提供了一些从 X 文件中加载网格信息的方法。尽管 x 文件的基本格 式已经有点过时了,但基于由 D3DXMATERIAL 结构体提供的每个材质单纹理的策略来说,它 依然是一个不错的用户可扩展格式。此书中,我们将利用这种扩展性来在 X 文件中保存和加 载我们自己的私有数据。
基本的 ID3DXMesh 类就像是存储了模型顶点,由多边形来引用这些顶点的索引缓存,以 及一个包含了把按使用的材质分类的多边形的可选属性表的一个容器。大多数情况下, ID3DXMesh 类和当你创建自己的几何体容器时可能会使用数据存储方法基本一致,那么因此 它就足够满足我们引擎的需要了。然而,在某些情况下,我们会发现引擎的地形几何体不太 适合 ID3DXMesh 的存储方式,,那么我们就需要设计我们自己的几何体格式了。尽管这种情 况会发生,不过我们依然把 ID3DXMesh 作为加载和存储数据的一种直接格式来使用。
D3DX 有着很多种基于不同需要的网格。目前我们讨论的只是对于静态几何体的基本网格容器。除此之外,D3DX 还提供了对于简化网格的自定义类,ID3DXSPMESH 和渐进网格, ID3DXPMESH。通过使用权重来控制模型中各部分顶点的重要性,简化网格可以让用户减少模 型包含的顶点数。当用户要进一步减少模型上的顶点数时,则移除最不重要的部分。由于这 不是一次性可以完成的工作。所以说它在引擎预处理模型阶段非常有用。
渐进网格是对简化网格的一种改进。渐进网格源于 Hughes Hoppe[Hoppe]提出的依赖视 野的渐进网格方法(View Independent Progress Mesh)。Hoppe 的方法记录了一系列三角 形划分,称为分裂(split)。它可以实时地用来增加或减少模型精度。通过融合相邻多边 形然后记录这一过程,模型精度被降低。借由还原这些融合将三角形还原到先前的样子,我 们可以还原其表面精度。这些三角形的分裂和融合操作可以被递归执行,可以让模型平滑地 由高细节程度变到低精度或是执行这一逆向过程。这就可以让离摄像机近的物体使用高精度, 而当其离远之后就降低其精度。
使用 D3DX 加载和显示模型
如 DirectX SDK 教学里一样,使用 D3DX 加载和显示一个简单网格还是相当容易的。对 于不熟悉 ID3DXMesh 的读者,通过学习 SDK 的网格教程绝对是了解这些对象最好的方法。我 们在此大概讲述一下这个 D3DX 类的基本用处,而不会再重申 SDK 已经提供的内容。
一旦我们使用 DirectX 示例框架将程序和 Direct3D 的环境设置好之后,显示网格不过 就是先从硬盘加载网格,然后建立需要被渲染的对象,最后使用这些对象来显示网格内容罢 了。
从 X 文件中读取网格的第一步就是使用函数 D3DXLoadMeshFromFile。这将加载网格几 何体,然后分配内存给网格需要的 D3DXMATERIAL 结构体链表然后填充它。各个材质都包含 一个可选的字符串用以包含纹理的文件名。然后 D3DXLoadTextureFromFile 就可以用这些可 用的纹理名来加载位图数据。若假设没有纹理或者不需要转换模型几何体,那么现在数据就 可等待被渲染了。
渲染网格最简单的方式就是借由蛮力方式(brute-force approach)了。使用这种方法, 我们可以逐一渲染场景内的每个网格,但这种方法就不能按相似渲染状态来分批渲染,换句 话说就是,我们不能通过有效对渲染调用排序来获得性能上的提升。后者则可以在内部将各 个网格细分为多个子集。每个子集都是使用相同材质的多边形集合。因此,如果一个 ID3DXMesh 对象包含了 n 个子集,那么它就可以用加载的材质 n 和纹理 n 的方式来渲染这部 分模型。渲染一个给定的模型,我们简单的遍历所有网格子集,激活合适的纹理和材质,一 旦这些对象被激活,那么我们就可以指示网格使用成员函数 DrawSubset 来渲染指定的子集。
使用 Direct3D 效果(Effect)文件
当建立 3D 引擎之时,我们需要考虑到当今家用计算机广泛的硬件可用性。在一种显卡 上运行良好的的渲染程序也许在另一种上表现糟糕,甚至是不能运行的。那么唯一可行的解决之道便是提供多重渲染程序以确保你的产品能与所有硬件兼容。Direct3D 效果文件便提供了一种途径来将这些不同的渲染方法封装到一个文件里。效果文件里的每个技术 (technique)都是对一个指定渲染方式的高度萃取,其中同时也包含了需要的渲染状态和 任何顶点,像素着色器命令。通过这种途径,效果文件通过模块化定义渲染方式这一手段来 给我们提供了硬件上的向后兼容性。
效果文件其实就是包含了许多可用技术的文本文件。各个技术包含一定数量的路径 (pass),各个路径代表了在一个单独渲染例程中需要的资源和执行的操作。有了这个层次结构,这些文件里就可以写入多个技术,特定技术支持特定硬件,通过各个技术,就可以按需为多重路径包含特定的指令。
效果文件是文本文件这一天性使得它们很容易被编辑并快速写成。它们在运行时被编译然后产生出给硬件执行的渲染状态和着色器指令。效果文件中的技术可以在编译期被确认并找到对于某一指定硬件配置最优的可能技术。这就给我们提供了一个高度模块化的系统,它允许程序员支持多硬件配置,甚至当新硬件可用时,使用额外的效果文件来支持这些将来的新硬件产品。
列表 2.1 显示了一个简单效果文件的内容,它阐述了技术和路径的层次关系。这个例子 里,为简化之,在这个效果文件中我们只设置了纹理状态。这个示例文件表现了考虑硬件兼 容性的多重技术的用法。当下许多显卡在单路径内可使用的纹理数是不同的。列表 2.1 里的 技术都使用六个纹理来产生相同的效果。第一个技术在一个单路径内使用四个纹理,而第二 个技术则在两个路径中使用四个纹理。当这个效果文件在特定的硬件平台上被编译时,仅当 该平台支持每个路径四纹理时,才使用第一个技术。当支持的纹理数小于四个的时候,将不 使用第一个技术,转而程序将指示开启第二个技术。
列表 2.1 包含了单个路径的技术和多个路径的技术的效果文件示例。
// Both of the techniques below use the same // four textures, which we define using the // following variable declarat ions. The program // will set these variable to point to specific // D3DTexture9 objects loaded. texture tex0; texture tex1; texture tex2; texture tex3; // The first technique renders using all four // textures at once. Four complete texture // stages are defined to add the colors // of all four textures. technique t0
{ pass p0
{ // all four textures are loaded // into the texture input parameters Texture[0]= (tex0); Texture[1]= (tex1); Texture[2]= (tex2); Texture[3]= (tex3);
// for the first texture, the
// color values are used as-is
Color0p[0] = SelectArg1;
ColorArg1[0] = Texture;
// for the remaining textures,
// their color values are Added
// to the contents of the previous
// texture channel
Co1or0p[1] = Add;
ColorArg1[1] = Texture;
Col0rArg2[1] = Current;
ColorOp[2] = Add;
ColorArg1[2] = Texture;
Co10rArg2[2] = Current;
Co1or0p[3] = Add;
ColorArg1[3] = Texture;
ColorArg2[3] = Current;
Color0p[4] = Disable;
>>在DirectX 9.0中渲染文字:https://blog.csdn.net/tianxiangyuan/article/details/76038
>>D3DXFRAME:https://learn.microsoft.com/zh-tw/windows/win32/direct3d9/d3dxframe