论文部分内容阅读
摘要:随着图形处理器性能的提高及其可编程特性的发展,图形处理流水线的某些处理阶段和图形算法逐渐从CPU向GPU转移。文章介绍了可编程图形硬件基础,分析了基于GPU的光线跟踪技术的实现原理。设计的6个实验场景所包含的三角形面片数,从2016个到60960个成复杂度递增,在3种不同分辨率下,分别实现GPU和CPU的光线跟踪绘制。对实验结果比较、分析后,得到了GPU加速的光线跟踪技术的特点。
关键词:图形硬件;图形处理器;可编程性;光线跟踪
0 引言
光线跟踪是一种图像合成技术,它通过模拟光线与物体表面的交点来实现图像的绘制。目前的一些交互式光线跟踪和全局光照的应用都是基于超级计算机和PC机集群的。这类系统因其昂贵的价格严重阻碍了其发展与推广。随着图形处理器(GPU)性能的大幅度提高以及可编程特性的发展,图形处理流水线的某些处理阶段和图形算法逐渐从CPU向GPU转移。GPU的体系结构是一种高度并行的单指令多数据(singleInstruction Multiple Data,SIMD)指令执行体系,其计算速度非常高。GPU的指令执行方式和CPU不一样,不能直接执行在CPU中实现的算法。图形硬件技术一个最主要的突破是引入了可编程功能,它允许用户编制自定义的着色器程序(shaderProgram)来替换原来固定流水线中的某些功能模块。结合当前GPU特性,文中提出了一种高质量的渲染方法,把光线跟踪表示成一种流计算模式,把目前可编程的图形处理器抽象成通用的流处理器,充分利用了GPU并行处理体系结构的性能优势。
1 可编程图形硬件基础
图形硬件的可编程能力允许用户编写特定的程序来取代固定的图形管道。在图形管道中,有两个可编程单元:点处理单元和片元处理单元。点处理单元由点编程引擎(Vertex ProgramEngine)控制,片元处理单元由片元编程引擎(Fragment ProgramEngine)控制。每个单元可由用户编写的小程序来控制。这个小程序可用汇编语言
或c语言(cg)编写,是一组顺序执行的指令代码。这组指令代码通过图形驱动程序编译,并在图形硬件的相应的编程引擎上执行,从而取代固定图形管道中相应单元的功能。
1.1 点编程引擎
点编程引擎可实现完全控制点的转换、光照计算、复杂的点操作,产生纹理坐标、操作纹理矩阵等功能。这些实现都由图形硬件来处理。用户可用点编程引擎实现用户定制的功能。当点编程被允许时,几何数据流会由点程序来处理,绕过了固定的图形管道。同时,如果用点程序来处理点数据流,就必须处理所有要处理的功能。点程序由严格按顺序执行的SIMD指令组成,不能使用条件语句。点程序代码越少,执行越快。使用点程序的优点有:比软件实现快,一个优化的光照模型的点程序要比固定图形管道提供的光照模型要快。
1.2 片元编程引擎
固定图形管道的片元处理单元用于定义纹理应用、纹理环境、颜色叠加和雾化操作。正像点编程模型中提到的一样,这个固定的处理不能给用户提供更大的灵活性和扩展性。可编程的片元处理单元提供了基于每个片元的灵活的计算。片元程序是一组顺序执行的指令代码,它在像素被渲染时执行。片元程序的指令和点程序的指令非常接近。片元程序不能像点程序那样,单独存在。片元程序在运行的时候,必须有一个点程序被激活。
2 基于GPU的光线跟踪实现
2.1 可编程图形处理器抽象化
纹理内存通常用于存储场景中几何体的纹理。光栅器产生的片元都有自己的纹理坐标。这个纹理坐标可作为包含颜色信息的二维内存区域的索引。这个方法的一个主要限制是:从内存中提取的地址没法通过计算获得,它仅是一个被光栅化了的几何体属性。
为了解决这个问题,本文使用图形处理器中新增加的功能——依赖纹理查找。依赖纹理访问允许由片元程序计算从纹理内存中要提取的地址。同时,它允许纹理查找的结果用于其它内存地址的计算。图形处理器性能的增强,使得在单渲染通道能够实现反射、凹凸映射等效果。
通过依赖纹理查找,能把纹理内存子系统作为一个通用的只读内存来使用,以便在图形硬件上实现通用计算。图形处理器的这个功能使得可在GPU上实现许多包含复杂数据结构的算法,和实现查找这些复杂数据结构中的元素。依赖纹理查找具体的实现方法如图1所示。图中显示了一个简单的三角形网格数据结构,其中to、t1、t2、t3分别表示4个不同的三角形面片,v0、v1、v2、v3、v4分别表示三角形面片的顶点坐标。4个三角形网格使用两个纹理分别存储三角形的顶点编号和顶点坐标。
每个三角形被存储成一个RGB纹理单元,利用R、G、B通道保存每个三角形面片的顶点编号。三角形的顶点坐标同样分别用R、G、B通道存储x、y、z分量。若想获取一个三角形的3个顶点位置,只需完成4次依赖纹理提取:先从三角形纹理中提取顶点编号,后根据纹理中的R、G、B通道中编号,从顶点坐标纹理中分别提取顶点的位置。
目前,图形处理器不支持一维纹理,许多数据结构超过了一维纹理的最大尺寸。本文使用二维纹理来实现纹理内存的抽象。纹理内存的简单抽象能把复杂的数据结构载入显示内存以及使用片元程序进行处理。更重要的是,它使GPU上的纹理内存可作为一个简单的只读内存来使用。这是GPU作为一个通用处理器的关键所在。
用纹理内存的抽象来遍历网格加速结构。每个网格单元包含一个指向这个网格单元中三角形列表的起始地址。若网格单元是空的,则用一个空指针表示。三角形列表用另外一个纹理表示,三角形列表中的每个实体是一个指向表示三角形的顶点数据集合的指针。三角形顶点存储在3个独立纹理的集合中。在系统实现过程中,每个三角形面片的顶点都是独立存储,不共享任何顶点数据。顶点法向量、顶点颜色等渲染数据,顶点位置也是独立存储。纹理内存作为存储系统中不同内核之间传递数据的流缓冲区使用。
2.2 基于流的光线跟踪设计
实现基于流的光线跟踪最大的难度是如何把光线跟踪映射到设计的流计算模型中。GPU有很强的流处理能力,但在GPU上实现递归非常困难。本文把光线跟踪细分成多个内核,内核通过数据流联系在一起。以下将分析如何把光线跟踪形式化为一个流计算。
不管是绘制静态场景还是动态场景,首先要确定光线跟踪能够处理的几何体片元的类型,以及系统实现中所使用的加速结构的类型。假设场景中所有几何体都使用三角形表示。光线跟踪能够渲染由不同几何体片元组成的场景,其中最适合的是三角形。因为图形硬件仅支持三角形渲染,其它表面形状虽能使用,但在渲染之前它们都要被转换成三角形。其次,建模程序和扫描软件产生的模型都是由三角形网格组成的,当只有一种 简单图形单元被允许时,光线跟踪会显得更加简单有效。对于流计算来说,这些限制意味着所有的绘制可以被相同的内核集来处理,这种方式简化了系统的数据流。
为了实现基于流模式的光线跟踪,把基于流实现的光线跟踪细分成4个内核,分别是:视光线产生器、网格遍历、光线与三角形求交和渲染。如图3所示,每个内核的输入显示在盒子的左边,内核之间传输的流数据的类型由虚线所指的内容表示。这种细分的方式在流编程模型中并不是强制性的,因为在目前GPU执行的片元程序还缺乏分支功能(不过最新的Nvidia GeForce6800、Nvidia GeForce7800片元处理器已经支持分支处理功能)。
视光线产生器内核产生一束视光线流,每根视光线都和图像中的某个像素相关联,以此形成光线向量集。网格遍历内核读取由视光线产生器产生的光线流,然后作用光线,使光线一步一步地遍历网格直到碰到一个包含三角形面片的体素,光线和体素对被输出并传递到光线与三角形面片求交测试内核里。
求交测试内核主要负责测试该光线是否和体素中包含的三角形面片有交点。光线和体素对被求交测试器处理后有两种输出情况,若光线和体素包含的三角形面片相交,则交点所在的三角形面片被输出到绘制阶段;若光线与体素中包含的任何三角形面片都没有交点,则光线返回遍历内核并按照遍历算法搜索下一个包含三角形面片的体素。
绘制内核的功能主要是计算颜色值。如果一根光线终止在相交点上,那么把这个相交点的颜色值写进累加的图像上。此外,绘制内核可能产生阴影或次光线,这种情况下,将这些新产生的光线返回到遍历阶段,开始新的跟踪。
3 实验结果与分析
实验目的:在场景复杂度不同的测试环境下,对两种光线跟踪绘制方式(方式1:基于GPU加速;方式2:基于CPU的传统递归方式)的性能进行测试。
算法和数据实验的硬件平台:512M内存和3.0GHzPentium CPU的主机,配备具有64M显存的Nvidia 6800图形显卡。
用Visual C++.NET、OpenGL以及cg语言来实现算法程序。系统中使用的场景加速结构的网格精度都使用了默认模式,即由128*128*128个体素组成。
3.1 实验结果
6个不同复杂度的场景效果图都是基于GPU的光线跟踪绘制实现的。场景1至场景6包含的三角形面片数,从2016个到60960个成复杂度递增。
基于GPU加速的光线跟踪绘制速度的测试不包含加速结构构建的时间,因为实验的目的是测试GPU加速对场景绘制速度的影响。对于静态场景的绘制,加速结构构建可以在预处理阶段完成。以下将对基于GPU加速的光线跟踪绘制进行分析。这两种实现方式在分辨率为256*256、512*512、1024*1024的情况下,分别绘制场景1-6时。
3.2 结果分析
数据结果和系统实现所采用的软硬件环境,对基于GPU加速的光线跟踪实现方法,得出以下结论:
(1)与方式2相比,方式1更适合复杂场景的绘制。场景复杂度越高,GPU高性能的计算能力体现越明显。
(2)当场景复杂度较低时,场景的加速结构中存在大量的空体素(体素中没有包含场景对象)。这导致光线遍历加速结构中的空体素消耗大量的计算时间,且分辨率越高这种消耗越明显。当光线遍历空的加速结构所耗的时间和有效场景绘制所耗的时间达到一定的比例程度时,方式1的整体效果不会得到很好的体现,甚至不如传统的光线跟踪绘制。
(3)在相同的分辨率情况下,当场景复杂度的增加时,方式1消耗时间的增加并不明显。这主要由光线遍历加速结构所致。实验绘制的场景使用的加速结构是由128*128*128个体素组成,不管场景是否复杂,光线遍历加速结构都要耗费一定的时间。
(4)实验所采用的图形硬件还不支持条件分支以及循环,这降低了系统实现的灵活性及其绘制速度。
(5)在选用加速结构时,主要考虑硬件表示的方便性。若要使加速性能更优,则应降低光线遍历加速结构所耗的时间。可从两方面改进系统性能,一是通过使用层次包围盒技术来进一步优化;另一是在现有的加速结构的基础上,通过降低光线遍历空的加速结构的消耗来优化遍历。如果在未来几年,图形硬件的发展速度像过去几年一样迅速,未来图形硬件完全有可能实现实时的光线跟踪。
4 结束语
本文通过对基于GPU加速的光线跟踪技术,设计了6个不同复杂度的场景,在分辨率分别为:256*256、512*512、1024*1024时,实现了GPU和CPU实现光线跟踪绘制。从实验结果可得到基于GPU加速的光线跟踪的优势。基于可编程图形硬件的算法,既达到了实时的效率,也保证了算法的质量。
目前最迫切需要解决的问题是,CPU和GPU之间的数据交换限制与负载均衡算法。在本论文完成之时,PCI-Expres技术已经开始实用化,市场上已经出现了支持PCI-E的显卡。显然,这将有利于解决GPU应用中的带宽限制问题。随着GPU可编程能力的进一步增强,可以将GPU作为CPU的协处理器。
关键词:图形硬件;图形处理器;可编程性;光线跟踪
0 引言
光线跟踪是一种图像合成技术,它通过模拟光线与物体表面的交点来实现图像的绘制。目前的一些交互式光线跟踪和全局光照的应用都是基于超级计算机和PC机集群的。这类系统因其昂贵的价格严重阻碍了其发展与推广。随着图形处理器(GPU)性能的大幅度提高以及可编程特性的发展,图形处理流水线的某些处理阶段和图形算法逐渐从CPU向GPU转移。GPU的体系结构是一种高度并行的单指令多数据(singleInstruction Multiple Data,SIMD)指令执行体系,其计算速度非常高。GPU的指令执行方式和CPU不一样,不能直接执行在CPU中实现的算法。图形硬件技术一个最主要的突破是引入了可编程功能,它允许用户编制自定义的着色器程序(shaderProgram)来替换原来固定流水线中的某些功能模块。结合当前GPU特性,文中提出了一种高质量的渲染方法,把光线跟踪表示成一种流计算模式,把目前可编程的图形处理器抽象成通用的流处理器,充分利用了GPU并行处理体系结构的性能优势。
1 可编程图形硬件基础
图形硬件的可编程能力允许用户编写特定的程序来取代固定的图形管道。在图形管道中,有两个可编程单元:点处理单元和片元处理单元。点处理单元由点编程引擎(Vertex ProgramEngine)控制,片元处理单元由片元编程引擎(Fragment ProgramEngine)控制。每个单元可由用户编写的小程序来控制。这个小程序可用汇编语言
或c语言(cg)编写,是一组顺序执行的指令代码。这组指令代码通过图形驱动程序编译,并在图形硬件的相应的编程引擎上执行,从而取代固定图形管道中相应单元的功能。
1.1 点编程引擎
点编程引擎可实现完全控制点的转换、光照计算、复杂的点操作,产生纹理坐标、操作纹理矩阵等功能。这些实现都由图形硬件来处理。用户可用点编程引擎实现用户定制的功能。当点编程被允许时,几何数据流会由点程序来处理,绕过了固定的图形管道。同时,如果用点程序来处理点数据流,就必须处理所有要处理的功能。点程序由严格按顺序执行的SIMD指令组成,不能使用条件语句。点程序代码越少,执行越快。使用点程序的优点有:比软件实现快,一个优化的光照模型的点程序要比固定图形管道提供的光照模型要快。
1.2 片元编程引擎
固定图形管道的片元处理单元用于定义纹理应用、纹理环境、颜色叠加和雾化操作。正像点编程模型中提到的一样,这个固定的处理不能给用户提供更大的灵活性和扩展性。可编程的片元处理单元提供了基于每个片元的灵活的计算。片元程序是一组顺序执行的指令代码,它在像素被渲染时执行。片元程序的指令和点程序的指令非常接近。片元程序不能像点程序那样,单独存在。片元程序在运行的时候,必须有一个点程序被激活。
2 基于GPU的光线跟踪实现
2.1 可编程图形处理器抽象化
纹理内存通常用于存储场景中几何体的纹理。光栅器产生的片元都有自己的纹理坐标。这个纹理坐标可作为包含颜色信息的二维内存区域的索引。这个方法的一个主要限制是:从内存中提取的地址没法通过计算获得,它仅是一个被光栅化了的几何体属性。
为了解决这个问题,本文使用图形处理器中新增加的功能——依赖纹理查找。依赖纹理访问允许由片元程序计算从纹理内存中要提取的地址。同时,它允许纹理查找的结果用于其它内存地址的计算。图形处理器性能的增强,使得在单渲染通道能够实现反射、凹凸映射等效果。
通过依赖纹理查找,能把纹理内存子系统作为一个通用的只读内存来使用,以便在图形硬件上实现通用计算。图形处理器的这个功能使得可在GPU上实现许多包含复杂数据结构的算法,和实现查找这些复杂数据结构中的元素。依赖纹理查找具体的实现方法如图1所示。图中显示了一个简单的三角形网格数据结构,其中to、t1、t2、t3分别表示4个不同的三角形面片,v0、v1、v2、v3、v4分别表示三角形面片的顶点坐标。4个三角形网格使用两个纹理分别存储三角形的顶点编号和顶点坐标。
每个三角形被存储成一个RGB纹理单元,利用R、G、B通道保存每个三角形面片的顶点编号。三角形的顶点坐标同样分别用R、G、B通道存储x、y、z分量。若想获取一个三角形的3个顶点位置,只需完成4次依赖纹理提取:先从三角形纹理中提取顶点编号,后根据纹理中的R、G、B通道中编号,从顶点坐标纹理中分别提取顶点的位置。
目前,图形处理器不支持一维纹理,许多数据结构超过了一维纹理的最大尺寸。本文使用二维纹理来实现纹理内存的抽象。纹理内存的简单抽象能把复杂的数据结构载入显示内存以及使用片元程序进行处理。更重要的是,它使GPU上的纹理内存可作为一个简单的只读内存来使用。这是GPU作为一个通用处理器的关键所在。
用纹理内存的抽象来遍历网格加速结构。每个网格单元包含一个指向这个网格单元中三角形列表的起始地址。若网格单元是空的,则用一个空指针表示。三角形列表用另外一个纹理表示,三角形列表中的每个实体是一个指向表示三角形的顶点数据集合的指针。三角形顶点存储在3个独立纹理的集合中。在系统实现过程中,每个三角形面片的顶点都是独立存储,不共享任何顶点数据。顶点法向量、顶点颜色等渲染数据,顶点位置也是独立存储。纹理内存作为存储系统中不同内核之间传递数据的流缓冲区使用。
2.2 基于流的光线跟踪设计
实现基于流的光线跟踪最大的难度是如何把光线跟踪映射到设计的流计算模型中。GPU有很强的流处理能力,但在GPU上实现递归非常困难。本文把光线跟踪细分成多个内核,内核通过数据流联系在一起。以下将分析如何把光线跟踪形式化为一个流计算。
不管是绘制静态场景还是动态场景,首先要确定光线跟踪能够处理的几何体片元的类型,以及系统实现中所使用的加速结构的类型。假设场景中所有几何体都使用三角形表示。光线跟踪能够渲染由不同几何体片元组成的场景,其中最适合的是三角形。因为图形硬件仅支持三角形渲染,其它表面形状虽能使用,但在渲染之前它们都要被转换成三角形。其次,建模程序和扫描软件产生的模型都是由三角形网格组成的,当只有一种 简单图形单元被允许时,光线跟踪会显得更加简单有效。对于流计算来说,这些限制意味着所有的绘制可以被相同的内核集来处理,这种方式简化了系统的数据流。
为了实现基于流模式的光线跟踪,把基于流实现的光线跟踪细分成4个内核,分别是:视光线产生器、网格遍历、光线与三角形求交和渲染。如图3所示,每个内核的输入显示在盒子的左边,内核之间传输的流数据的类型由虚线所指的内容表示。这种细分的方式在流编程模型中并不是强制性的,因为在目前GPU执行的片元程序还缺乏分支功能(不过最新的Nvidia GeForce6800、Nvidia GeForce7800片元处理器已经支持分支处理功能)。
视光线产生器内核产生一束视光线流,每根视光线都和图像中的某个像素相关联,以此形成光线向量集。网格遍历内核读取由视光线产生器产生的光线流,然后作用光线,使光线一步一步地遍历网格直到碰到一个包含三角形面片的体素,光线和体素对被输出并传递到光线与三角形面片求交测试内核里。
求交测试内核主要负责测试该光线是否和体素中包含的三角形面片有交点。光线和体素对被求交测试器处理后有两种输出情况,若光线和体素包含的三角形面片相交,则交点所在的三角形面片被输出到绘制阶段;若光线与体素中包含的任何三角形面片都没有交点,则光线返回遍历内核并按照遍历算法搜索下一个包含三角形面片的体素。
绘制内核的功能主要是计算颜色值。如果一根光线终止在相交点上,那么把这个相交点的颜色值写进累加的图像上。此外,绘制内核可能产生阴影或次光线,这种情况下,将这些新产生的光线返回到遍历阶段,开始新的跟踪。
3 实验结果与分析
实验目的:在场景复杂度不同的测试环境下,对两种光线跟踪绘制方式(方式1:基于GPU加速;方式2:基于CPU的传统递归方式)的性能进行测试。
算法和数据实验的硬件平台:512M内存和3.0GHzPentium CPU的主机,配备具有64M显存的Nvidia 6800图形显卡。
用Visual C++.NET、OpenGL以及cg语言来实现算法程序。系统中使用的场景加速结构的网格精度都使用了默认模式,即由128*128*128个体素组成。
3.1 实验结果
6个不同复杂度的场景效果图都是基于GPU的光线跟踪绘制实现的。场景1至场景6包含的三角形面片数,从2016个到60960个成复杂度递增。
基于GPU加速的光线跟踪绘制速度的测试不包含加速结构构建的时间,因为实验的目的是测试GPU加速对场景绘制速度的影响。对于静态场景的绘制,加速结构构建可以在预处理阶段完成。以下将对基于GPU加速的光线跟踪绘制进行分析。这两种实现方式在分辨率为256*256、512*512、1024*1024的情况下,分别绘制场景1-6时。
3.2 结果分析
数据结果和系统实现所采用的软硬件环境,对基于GPU加速的光线跟踪实现方法,得出以下结论:
(1)与方式2相比,方式1更适合复杂场景的绘制。场景复杂度越高,GPU高性能的计算能力体现越明显。
(2)当场景复杂度较低时,场景的加速结构中存在大量的空体素(体素中没有包含场景对象)。这导致光线遍历加速结构中的空体素消耗大量的计算时间,且分辨率越高这种消耗越明显。当光线遍历空的加速结构所耗的时间和有效场景绘制所耗的时间达到一定的比例程度时,方式1的整体效果不会得到很好的体现,甚至不如传统的光线跟踪绘制。
(3)在相同的分辨率情况下,当场景复杂度的增加时,方式1消耗时间的增加并不明显。这主要由光线遍历加速结构所致。实验绘制的场景使用的加速结构是由128*128*128个体素组成,不管场景是否复杂,光线遍历加速结构都要耗费一定的时间。
(4)实验所采用的图形硬件还不支持条件分支以及循环,这降低了系统实现的灵活性及其绘制速度。
(5)在选用加速结构时,主要考虑硬件表示的方便性。若要使加速性能更优,则应降低光线遍历加速结构所耗的时间。可从两方面改进系统性能,一是通过使用层次包围盒技术来进一步优化;另一是在现有的加速结构的基础上,通过降低光线遍历空的加速结构的消耗来优化遍历。如果在未来几年,图形硬件的发展速度像过去几年一样迅速,未来图形硬件完全有可能实现实时的光线跟踪。
4 结束语
本文通过对基于GPU加速的光线跟踪技术,设计了6个不同复杂度的场景,在分辨率分别为:256*256、512*512、1024*1024时,实现了GPU和CPU实现光线跟踪绘制。从实验结果可得到基于GPU加速的光线跟踪的优势。基于可编程图形硬件的算法,既达到了实时的效率,也保证了算法的质量。
目前最迫切需要解决的问题是,CPU和GPU之间的数据交换限制与负载均衡算法。在本论文完成之时,PCI-Expres技术已经开始实用化,市场上已经出现了支持PCI-E的显卡。显然,这将有利于解决GPU应用中的带宽限制问题。随着GPU可编程能力的进一步增强,可以将GPU作为CPU的协处理器。