APP下载

基于GPU加速的水下海洋环境光照模拟的研究

2018-02-03张雨侬秦勃梁艺

电脑知识与技术 2018年2期

张雨侬 秦勃 梁艺

摘要:该文依据FFT(快速傅立叶变换)方法创建水面三角网格,通过加载三角网格数据的计算水下光线,利用OpenGL在屏幕上绘制出水下海洋环境中的光照模拟效果,再使用GPU并行算法对计算过程进行优化加速,最后通过使用OpenGL的VBO(顶点缓冲区对象)和VAO(顶点数组对象)两种方式来实现两者的交互。通过优化数据结构及存储器分配,有效缓解了模拟方法在GPU架构上的性能瓶颈。实验结果表明,该方法能够实时逼真地模拟水下光照,与已有的方法相比处理速度有显著的提升。

关键词:光照模拟;GPU加速;OpenGL;像素緩冲区对象;顶点缓冲区对象

中图分类号:TP302 文献标识码:A 文章编号:1009-3044(2018)02-0271-05

Research on Underwater Marine Environment Lighting Simulation Based on GPU Acceleration

ZHANG Yu-nong, QIN Bo, LIANG Yi

(Department of Computer Science & Technology, Ocean University of China, Qingdao 266100,China)

Abstract: In this paper, according to the FFT (Fast Fourier Transform) method to create the surface triangular grid, by loading triangular grid data to calculate the underwater light, using OpenGL on the screen to draw the underwater marine environment in the light simulation effect, and then use the GPU parallel algorithm pair The process of optimization to accelerate, and finally through the use of OpenGL VBO (vertex buffer object) and VAO (vertex array object) in two ways to achieve the interaction between the two. By optimizing the data structure and memory allocation, effectively alleviate the performance bottleneck of the simulation method on the GPU architecture. The experimental results show that the method can simulate the underwater lighting in real time, and the processing speed is significantly improved compared with the existing methods.

Key words: lighting simulation; GPU acceleration; OpenGL; pixel buffer object; vertex buffer object

1 概述

近年来,“智慧海洋”逐渐成为海洋信息智能化发展最前沿的课题之一。水下光照的模拟是海洋虚拟场景模拟中的一个重要的课题,由于受到海洋复杂多变的环境影响,水下光线可能会产生折射、焦散、衰减等现象,而为了实现更加逼真的渲染效果,如何提高程序的并行性和计算效率、提高渲染的实时性成为了国内外学者研究的一个难点。

2001年,Mitchell[1]和Dobashi[2]通过将视域体分割成平行的平面来渲染水下光束,每个分割平面上采用Godray模型计算光强积分,并将结果累加到帧缓存中,阴影通过映射来实现。2001年,Jensen[3]通过把视域体分割成32个切片来表示光强,使用体渲染技术来渲染,并且将一个有动画效果的焦散纹理投射到每一个切片上。2002年,Iwasaki[4,5,6]描述了一种基于物理模型的水下光束渲染的方法,为每个光束构建一个平行六面体,并将其分割成若干子体,以准确计算各个子体的光强,最后把结果累加到帧缓存中;同样,采用阴影映射方式描述阴影。

2013年,方贵盛[7]对近年来水模拟的方法进行了总结,介绍了一些水体渲染的加速和改进的方法。2009年Hilko Cords[8]在GPU上实现了浮动物体与水面的交互。2010年,Prashant Goswamiy[9]等人提出了一种交互式SPH(Smoothed Particle Hydrodynamics)仿真和渲染的方法来实现高质量的可视化。关键粒子的邻域搜索基于Z索引和并行排序,利用模拟数据从SPH粒子云中有效地提取所有表面粒子,然后从表面颗粒光栅化后的部分快速生成距离场,最后使用最先进的GPU光线投射直接渲染距离场。2012年,NVIDIA在一个叫做Nalu[10]的演示中用图像过滤器来模拟Godray。它首先将光线多次折射后照射到Nalu身上和头发上,然后渲染阴影投射体,并将它们从明亮的像素中减去。最后,它可以快速的模糊图像,制造出Godray的幻象。2011年,G?abor Liktor和Carsten Dachsbacher[11]提出了一个新颖的自适应和可伸缩的渲染算法,可用于在表面或体积单散射焦散的实时渲染。利用了焦散图和三角形体积的方法,捕获光空间中的镜面,但是跟踪光束而不是单个光子。光束从光源投射到场景的表面上自适应地生成,根据几何和光子分布的不连续性被迭代地改进,这使得其能够重建锐度体积的焦散图案,同时降低散焦区域的采样分辨率和填充率。endprint

此外,有些学者使用了混合的方法来进行模拟。2010年,Nuttapong Chentanez[12]结合基于网格和基于粒子的方法,都在CUDA中实现。2015年,E Darles,B Crespin[13]等人利用光谱和混合模型以及使用了Navier-Stokes方程来表示海洋表面,同时关注模拟泡沫和喷雾等现象以及光与海洋表面的相互作用。近年来osgEarth也越来越多地被用来渲染模拟海洋场景[14]。

本文根据Iwasaki提出的基于物理模型的方法,结合最新的研究方法,对光照模拟的算法进行了改进,使用CUDA8.0版本将水下光照模拟的计算过程在GPU上实现,并在Maxwell架构下的GTX960和Pascal架构下的GTX1080上进行测试、分析,充分利用CUDA并行计算的性能优势,并通过使用OpenGL的VBO(顶点缓冲区对象)和VAO(顶点数组对象)两种方式实现两者的结合,优化数据结构以及存储器分配,测试证明了这种算法有效缓解了在GPU架构上的性能瓶颈,提高了程序执行效率。

2 模型与方法

2.1 水下光照模型

在Iwasaki提出的基于物理模型的方法中,使用了照明体来表现光柱。首先,计算到达视点的光强度时,必须考虑由于水颗粒的光的散射。如图1所示,当视点位于水内时,使用公式1计算水面上的点Q到达视点Pv的光的强度Iv(λ)。

如果观察光线与水面的法线之间的角度小于临界角,则强度IQ由公式2表示。

如果观察射线与水表面的法线之间的角度大于临界角(48.6 度),则入射光是在水面(图1中的P2)上一点处的反射光。因此,把在点P2处到达视点的反射光认为是环境光,然后用环境光乘以P2Pv之间的水粒子的衰减比。

光柱的强度由公式1的积分项计算。为简单起见,将积分项表示为Ishaft。如图2所示,水面被细分为三角形网格,然后计算每个网格点处的折射矢量。

照明体由每个扫描平面切片,并且照明体和扫描平面之间的交叉区域被定义为焦散三角形(如图3)。散射光的积分等于观察射线相交的焦散三角形的强度的总和。公式1的第二项Ishaft由公式3近似。

[0LIPλexp-cλldl=iIpiλdiexp-cλli] (3)

再使用公式4计算点P处的散射强度IP(λ)。

[IPλ=IsunλTθii,θtiFpβλ,φ×exp-cλls+Iaρ] (4)

渲染光柱的基本思想是显示照明体的阴影正面。通过沿着观察射线与照明体的交叉线段对散射光进行积分来计算照明体的强度。如图2所示,通过水平面将每个照明体细分为几个子体积。由于在水表面处折射的太阳光的强度被指数地衰减,使沿着子体积的散射光的强度可以线性近似。这也使得可以通过使用Gouraud阴影功能来显示照明体。

在Iwasaki的方法中,对每一个光柱都做如下处理:首先将光柱分为子体积,删除自相交的子体积,然后对子体积重复如下过程:

(1) 将每个子体积细分为三个四面体。

(2) 将每个四面体投影到屏幕上。

(3) 将四面体分为两种情况,一种是投影到屏幕前的,一种是投影到屏幕后的,然后分别处理。

(4) 计算三角形顶点的强度。

(5) 显示三角形并在帧缓冲区中累加强度。

该方法以在子体积内沿着观察射线聚集散射光的强度,通过绘制子体积的三个四面体来渲染光柱。然而通过这种方法计算四面体的光强虽然能够减少计算时间,但是却失去了计算的准确性,本文中采用直接计算的方法,通过计算光柱侧面中点来绘制光柱,使得渲染的光柱更具真实性。

如图4所示,在由六个点Pi(i = 1,...,6)组成的子体积中,关注P1P4和P3P6两条光线。由于光线照射到水下以后会发生折射,所以P1P4和P3P6两条光线并不一定共面,不能直接用四个顶点绘制成两个三角形来表现光柱。此时,我们用这四个顶点的坐标依据公式5求出一个中点的坐标位置。通过公式6计算子体积点Pi处的强度IPi。

[IPiλ=IsPiλexp-cλli] (6)

使用中点坐标和四个顶点分别可以绘制出四个三角形面,对于每一个子體积需要计算出三个侧面中点,绘制12个小三角形,最后渲染这些小三角形表现光柱。对于光柱的强度,我们使用公式7的积分值来进行计算。

[Ic=0TIb-IaTt+Iadt=Ia+Ib2T] (7)

2.2 GPU架构

图形处理器(GPU)是处理计算机图形的专用设备,近年来, GPU逐渐发展成为高并行度、多线程、多核的处理器,可以满足高清晰度复杂图形实时处理的需求。2007年6月, NVIDIA公司推出了统一计算设计架构CUDA(Compute Unified Device Architecture),作为一种GPU的编程方法,它提供了丰富的高性能数学函数库,可在NVIDIA的GPU上运行,目前已发布CUDA8.0版本。

Pascal架构是NVIDIA公司推出的第6代GPU架构,相对于Maxwell架构,Pascal架构还引入了不少新技术,提供了更强大的性能。

(1) 拥有超高的浮点运算性能,提供了5.3Tflops双精度运算性能,9Tflops单精度浮点运算性能和21.2Tflops半精度运算性能。

(2) NVLink技术,能支持多GPU间或者CPU与GPU间的通信,双向通信带宽可达到160GB/s。

(3) 引入HBM2高速GPU存储架构,访存带宽同比增长3倍,最高可达720GB/s。

(4) 引入统一存储空间,提供了CPU和GPU存储的统一地址空间。endprint

(5) 计算抢占:允许计算任务在指令级被中断,可以打破kernel函数的运行时间限制,不必考虑超时问题。

2016年5月7日,NVIDIA公司正式发布了新一代旗舰显卡GeForce GTX 1080。它采用Pascal架构,拥有2560个CUDA处理器,160个纹理单元,核心频率为1607MHz,计算能力可以达到6.0。相比之前的Maxwell架构,Pascal架构对SM再一次做了提升,GTX1080的核心为GP104,包含4组GPC,每个GPC包含5个SM,每个SM中集成了128个CUDA单元、8个纹理单元、256KB的二级缓存、96KB的共享储存空间以及48KB的一级缓存。图5为核心GP104中一个SM的架构示意图。

2.3 CUDA和OpenGL的交互

OpenGL是图形硬件的一种软件接口,也是一个3D图形和模型库,具有高度的可移植性,并且有非常快的速度。CUDA和OpenGL交互操作的基本方式是使用CUDA计算生成数据,然后使用OpenGL在屏幕上绘制出数据所表示的图形。两者的结合可以通过两种方式来实现:

(1) 使用OpenGL的PBO(像素缓冲区对象)。在该方式下,CUDA直接生成像素数据,OpenGL显示这些像素;

(2) 使用OpenGL的VBO(顶点缓冲区对象)。在该方式下,CUDA生成顶点网格数据,OpenGL可以根据需要绘制出平滑的表面图或线框图或一系列顶点。

在本文中,我们使用VBO和VAO(Vertex Array Object)相结合的方式来存储数据,以达到CUDA和OpenGL的交互过程。首先,使用VBO存储顶点数据,包括顶点颜色、坐标、法线,以及顶点的indices,把本地(GL客户端)的数据完全交给GPU(GL服务端)来管理,可以映射到CUDA的地址空间,当做global memory被访问。其次,使用VAO存储GPU将怎么使用VBO里面的数据,以及顶点数据中哪些是坐标、哪些是颜色、哪些是法线等信息,没有了额外的opengles数据交互,节省了渲染时间。

3 优化与加速

3.1 程序基本框架与流程

在本文中,程序運行的基本流程如图6所示:

(1) 建立笛卡尔坐标系,y轴表示海底到海面的高度,x轴和z轴表示海平面的两个方向。加载海底地形数据,包括网格坐标、法线和海底地形的类型。

(2) 使用FFT的方法绘制海面三角网格,本文中使用的海面网格大小为256*256,以坐标原点为中心,x轴和z轴正负两个方向上各有128个网格点。

(3) 根据虚拟的光线照射方向,计算光线通过水面以后的折射方向,保存光线照射到海底的坐标。

(4) 将数据传到GPU端,根据相邻两条光线四个点的坐标计算出一个中点坐标以及该点的颜色值,进而确定一条光柱三个侧面的中点的坐标以及该点的颜色值。

(5) 根据光线计算海底焦散点的坐标以及该点的颜色值。

(6) 将计算结果保存在帧缓存中,更新网格数据,并将数据传回CPU端。

(7) 刷新屏幕,根据网格数据渲染、绘制光柱。

3.2 使用CUDA实现光照计算

从Iwasaki的水下光照模型提出以后,该方法被广泛应用,在渲染水下光照场景方面有着很好的效果。但随着渲染规模不断扩大,仅仅在CPU端进行光柱的计算已无法满足实时渲染的要求,为了达到更好的实时性,本文将光照的计算过程在GPU上使用CUDA来实现,使得运算过程高度并行化。

在 CUDA 编程模型中,完整的CUDA程序包括主机端和设备端两部分代码,主机端代码在CPU上执行,设备端代码又称为kernel运行在GPU上。kernel函数调用时根据线程维度<<>>,以block为单位映射到SM中,执行时以warp为单位。而影响kernel函数执行性能的相关因素包括了CUDAcore的计算能力、分支处理、线程切换开销、存储访问、occupancy(占用率)等。

本文对水下光柱和海底焦散两部分计算实现了并行处理。首先,对于海底焦散的计算,设置每个线程计算一个三角网格,根据法线方向计算三条光线折射到海底的焦散点坐标,根据光强计算出海底焦散的颜色值,将计算结果保存在VAO中。对于水下光柱的计算,设置每个线程计算一个三角网格,根据三个顶点与三个焦散点的坐标、颜色值计算侧面的中点坐标以及该中点的颜色值,最后将结果保存在VBO中。

3.3 OpenGL中VBO和VAO的结合

在水下海洋环境水体模拟的过程中,由于海面会受到风场、流场等环境因素的影响,为了使渲染效果更加逼真,往往需要根据环境的变化实时的进行数据更新以及场景渲染。因此,海面网格数据的更新速度就成为了影响水下场景渲染速度的重要因素。为了解决这一问题,本文将加载的顶点数据保存在VBO和VAO中,给它一个偏移量(offset)来指定我们打算填充缓冲的位置与起始位置之间的偏移量,然后我们可以将加载的位置数组、法线数组和纹理坐标数组结合为交叉数据,实现分批处理。随后,GPU端将计算结果传回CPU端,同时返回重复计算过程,CPU端刷新屏幕,使用更新后的数据进行绘制和渲染。这种方法极大地提高了数据访问的速度,提高了程序运行效率,具体实现方法如下:

(1) 创建VAO、VBO

glGenVertexArrays(1, &seaVAO); //创建VAO

glBindVertexArray(seaVAO);

glGenBuffers(1, &seaTexCoordVBO);//创建VBO

glBindBuffer(GL_ARRAY_BUFFER, seaTexCoordVBO);

(2) 注册、映射VBO

checkCudaErrors(cudaGraphicsGLRegisterBuffer(cuda_vbo_resource, vbo, cudaGraphicsMapFlagsNone));

checkCudaErrors(cudaGraphicsMapResources(1, cuda_vbo_resource, 0));

checkCudaErrors(cudaGraphicsResourceGetMappedPointer((void **)&ptr, &num_bytes, *cuda_vbo_resource));

(3) 使用

__global__ void UpdateGodrayVBOKernel(float * d_godray_data, int3 Sz, DIFDATA* d_ppData)

(4) 填充缓冲

glBufferData(GL_ARRAY_BUFFER, sea_Size* sizeof(float), NULL, GL_DYNAMIC_DRAW);

(5) 解除映射、注册

checkCudaErrors(cudaGraphicsUnmapResources(1, cuda_vbo_resource, 0));

unmapGLBufferObject(cuda_vbo_resource);

(6) 删除VAO、VBO

m_pListTerrain.clear();

for (int i = 0; i < m_pListTerrainVBO.size(); i++)

glDeleteBuffers(1, &m_pListTerrainVBO[i]);

m_pListTerrainVBO.clear();

for (int i = 0; i < m_pListTerrainVAO.size(); i++)

glDeleteVertexArrays(1, &m_pListTerrainVAO[i]);

m_pListTerrainVAO.clear();

4 测试与结果

4.1 测试环境

本文使用的CUDA版本为8.0,实验采用的机器配置为:Intel Core i5-4430,双核四线程,主频3.0GHz,内存8GB,使用了NVIDIA GTX960和GTX1080两种显卡,显卡性能对比见表1。

4.2 测试结果

本文中测试窗口像素设置为1600×900,网格大小为256×256,在没有使用GPU加速的原始程序中,Fps(帧率)为64,使用了GPU加速以后,在GTX960和GTX1080两种显卡上分别使用1、4、16、64、256、1024个线程进行测试,所得测试结果见表2,程序运行效果如图7所示。

由于硬件设备的限制,每个Block中的线程数最大不能超过1024,然而并不是每个Block中的线程数越多计算速度越快,这是因为受到了寄存器數的限制。根据GTX960和GTX1080两种显卡的硬件架构,每个Block中最多有65536个寄存器,当寄存器超出了限制时就会有一部分线程无法执行,此时计算效率不仅不会提高反而会下降,因此当寄存器数刚好达到满载时Block的计算效率达到理论上的最高值。而对于如何选择最合适的线程数目以及Block数以达到程序的最高效率,就需要通过测试来进行分析选择。

本文中的算法通过测试,我们发现当线程数为16时计算速度最快,效率最高,帧率在GTX960上可以达到172帧,在GTX1080上可以达到253帧。

表3是原始程序和加速后程序的计算效率对比,不妨设原始程序的计算能力为1.00,则在GTX960上加速后提高了1.68倍,在GTX1080上提高了2.95倍。

5 结论

本文针对复杂海洋环境中水下光照的计算与绘制,提出了一种基于GPU加速的水下海洋光照模拟的算法。该算法采用了高性能的GPU并行计算编程技术,提高了光线计算的效率,并引入了OpenGL的VBO和VAO两种方法,减少了通讯时间,提高了绘制的效率。最后通过对不同线程数的测试得出最佳运行线程数。实验结果表明算法的执行效率显著提高,可以用于实时渲染水下海洋场景。

参考文献:

[1] Mitchell,J. “Light Shafts Rendering Shadows in Participating Media.” Available online at http://www.ati.com/developer/gdce/2001/jensen/jensen_01.htm

[2] Dobashi, Y., T. Yamamoto, and T. Nishita. Interactive Rendering of Atmospheric Scattering Effects using Graphics Hardware. Proc. Graphics Hard-ware,2002: 99-108.

[3] Staff L, Goliá? J R. Deep-water animation and rendering[C]// 2001.

[4] Kei Iwasaki, Yoshinori Dobashi and Tomoyuki Nishita. An efficient method for rendering underwater optical effects using graphics hardware[J]. Computer Graphics forum. 2002, Volume 21(4):701-71.endprint

[5] Iwasaki K, Yoshimoto F, Dobashi Y, et al. A Method for Fast Rendering of Caustics from Refraction by Transparent Objects[J]. IEICE - Transactions on Information and Systems, 2005, E88-D(5):904-911.

[6] Iwasaki K, Furuya W, Dobashi Y, et al. Real‐time Rendering of Dynamic Scenes under All‐frequency Lighting using Integral Spherical Gaussian[J]. Computer Graphics Forum, 2012, 31(2pt3):727-734.

[7] 方貴盛, 潘志庚. 水虚拟仿真技术研究进展[J]. 系统仿真学报, 2013, 25(9):1981-1989.

[8] Hilko Cords. Real-Time Open Water Environments with Interacting Objects [C]// Proceedings of Eurographics Workshop on Natural Phenomena, Munich, Germany, 2009. New York, USA: ACM Press, 2009: 35-42.

[9] Goswami P, Schlegel P, Solenthaler B, et al. Interactive SPH simulation and rendering on the GPU[C]// Eurographics/acm SIGGRAPH Symposium on Computer Animation, SCA 2010, Madrid, Spain. DBLP, 2010:55-64.

[10] NVIDIAs Nalu Demo. Available online at http://www.nzone.com/object/nzone_nalu_home.html

[11] Papadopoulos C, Papaioannou G. Realistic Real-time Underwater Caustics and Godrays[J]. Proc Graphicon, 2010.

[12] Chentanez N. Real-time simulation of large bodies of water with small scale details[C]// Eurographics/acm SIGGRAPH Symposium on Computer Animation, SCA 2010, Madrid, Spain. DBLP, 2010:197-206.

[13] Darles E, Crespin B, Ghazanfarpour D, et al. A Survey of Ocean Simulation and Rendering Techniques in Computer Graphics[J]. Computer Graphics Forum, 2015, 30(1):43-60.

[14] 王锐, 钱学雷. Open Scene Graph 三维渲染引擎设计与实践[M].北京:清华大学出版社,2009.endprint