本系列主要翻译和参考《Real-Time 3D Rendering with DirectX and HLSL》一书(感谢原书作者),同时会加上一点个人理解或拓展。
这里是书中的代码和资源。
DirectX11 渲染管线
一般计算机中共有两个处理器是你可能会对其进行编程的,一个是central processing unit(CPU),一个是GPU。这两个组件有着截然不同的硬件结构和指令集。在图形编程领域,你编写的软件可能两方面都要涉及,对于CPU,你可能会使用到例如C++这样的编程语言,而对于GPU则需要使用诸如HLSL这样的语言。大部分关于图形编程的文章要么集中于CPU方面要么是GPU方面,这些内容其实都是有紧密联系的。在本书中,你将可以同时了解到两方面的内容。
DirectX当中的DirectX 3D API是本书着重关注的部分。Direct3D是用来绘制3D图形的系统接口,他还定义了怎样将实时图形渲染到屏幕的一系列步骤。这些步骤就被称之为DirectX3D图形渲染管线(详见图1.1)。在这张图中,单向箭头标识了数据是怎样从一个阶段传输到下一个,双向箭头则标识了资源和哪些渲染阶段间可以进行数据读写。那些可以用HLSL编程的模块已经用圆角矩形标识出来。接下来的内容将会详细介绍渲染管线中的各个模块。
输入装配阶段:The Input-Assembler Stage(IA)
输入装配阶段是渲染管线的入口,也是第一个阶段,在这个阶段里你需要提供待渲染对象的顶点和索引数据。输入装配阶段将这些数据“装配”成基本类型数据(例如:点列表,线条带,三角列表)并根据需要将数据输出给顶点着色渲染阶段。
Vertex Buffers顶点缓存
一个顶点至少包含了在3D空间中的一个位置。之所以说至少是因为顶点还可以包含颜色信息,法线信息(用于计算光照),纹理坐标信息等等。所有这些数据都可以在输入装配阶段进行顶点缓存。Direct3D中定义的这些顶点信息完全可以由程序员进行操作。你可以定义顶点所要包含的信息并通过input-layout对象定义顶点缓存数据如何流入IA阶段。之后的文章(原书Part III,Rendering with DirectX)中将会介绍如何定义顶点缓存以及input layout对象,现在只是大概的介绍一下这些术语。
两个顶点代表线段的两个端点,三个顶点可以代表一个三角形(如图1.2)。
Index Buffers索引缓存
索引缓存是第二种在输入装配阶段推荐的输入类型。索引缓存的定义关联了顶点缓存中的某些顶点,可以用来减少需要多次使用到的顶点的重复。想象以下场景:你需要渲染一个矩形(或宽泛的说,四边形)。这个四边形至少需要定义四个顶点。但是Direct3D并不支持将四边形作为基础类型(因为根本没有必要专门定义一个四边形,所有的四边形都可以拆分成三角形)。为了渲染这个四边形,你需要将其拆分成两个由三个顶点构成的三角形(如图1.3)。所以,现在你需要总共六个顶点信息,而不是四个,其中必然有两个顶点信息是重复的。但如果定义了索引缓存,你就可以通过定义四个顶点信息和六个与顶点缓存相关的索引信息来完成渲染。
现在,你可能会思考一个问题,“我怎么通过增加索引缓存来减少我所使用的整体数据大小呢?”那么我们需要再考虑两种情况,通过结合上面提到的四边形进行具体数据分析:
- 第一种情况
你的顶点数据只包含3D位置信息(x,y,z),每个轴向需要一个32-bit来保存这个浮点数(每个轴向为4byte),那么每个顶点需要12byte。所以在不包含索引缓存的情况下这个四边形只需要72字节保存(6 vertices * 12 bytes/vertex)。如果加上索引缓存,你的顶点缓存需要的空间是48byte(4 vertices * 12 bytes/vertex)。以16bit的int类型数据来保存索引,则你需要额外12bytes(6 indices * 2 bytes/index = 12 byte)。这时,总共需要60byte来存储这个四边形。这么看的话好像也没节省很多空间。
- 第二种情况
当你的模型中不仅包含位置信息,还可能包含16byte的颜色信息,12byte的法线信息以及8byte的纹理坐标信息。那么每个顶点将需要多花费36byte的空间。或许当模型不是太大的时候并不会有很多影响,但如果模型具有成千上万的点时你会发现多出来的空间占用是相当可观的。还有,你不仅需要考虑空间占用的大小,还有当CPU和GPU之间进行数据传输时,是需要通过图形总线(例如PCI Express)来传输的,这种总线的传输速度通常非常慢(相比于CPU向RAM传输,以及GPU向VRAM传输),所以如何减少数据对你来说将会是至关重要的。
Primitive Types基本类型
当你向IA阶段提供顶点缓存数据时,你也必须定义这些顶点的拓扑结构,这决定了渲染管线将如何解释这些顶点。DirectX3D提供了以下几种基本类型(如图1.4和1.5):
- Point list 点列表:一系列单独渲染毫无关联的点
- Line list 线列表:一系列成对关联的点,这些一对一对的点之间是没有关联的
- Line strip 线条带:一系列成对关联的点,但每对点的末点会和下一对点的起点有关联
- Triangle list 三角列表:是我们最常见的拓扑结构,在三角列表中每三个顶点组成一个独立的三角形。三角形之间公用的点将会重复出现(除非定义了索引缓存)。
- Triangle strip 三角条带:每三个顶点构成一个三角形,公用的顶点将不会重复,所以顶点间会密切的连在一起。
Primitive with Adjacency邻接基元
从DirectX10开始,Direct3D已经加入了包含邻接数据的基本数据。对于邻接基元来说,你不只要定义基本数据,还需要定义围绕在这个基元周围的数据。(如图1.6)这是用来做几何着色器的,这里每个特定的集合着色程序需要访问邻接三角形。临界三角形需要和原始三角形一起被提交给顶点/索引缓冲区,并且用D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ这个拓扑结构。注意到邻接三角形只是被用来作为几何着色器的输入,并不会被画出来。如果没有几何着色器,邻接三角形也还是不会被画出来。
Control Point Patch Lists控制点片
控制点片作为一个拓扑结构提供给细分曲面阶段使用。相关内容将会在后面的几何细分曲面着色器文章中介绍。
参考文章: 关于输入装配阶段的详细内容和具体实现请参考[这篇文章](http://www.aiseminar.com/bbs/home.php?mod=space&uid=3&do=blog&id=2622)。 |
在做完IA部分的资料翻译和整理后发现篇幅比预期长一些,于是剩下的几个渲染阶段将会在下一篇文章中总结。 |