图形实时渲染是典型的CPU+GPU异构并行任务。传统三维图形管线的渲染由CPU负责输入和定义渲染规则,GPU固定渲染管线负责图形绘制。这种固定的处理模式虽然简化了开发流程,但难以实现复杂效果的三维模拟,束缚了三维图形的表达效果。GPU可编程特性改变了固定图形流水线的模式,实现了面向顶点与像素的编程,使得图形渲染更加灵活和高效。OpenGL 2.0增加了可编程渲染管线,用OpenGL着色语言控制顶点和片段的处理,通过这种更为灵活的图形硬件控制,满足三维图形特效开发的需要。以下为GPU可编程渲染的流程图

纹理映射符号法


(一)逐矢量要素的纹理映射的方法

对场景中的节点(Node)或几何体(Geometry)应用纹理属性时,通常需要预先指定每个顶点的纹理坐标,以便将图像正确地贴至物体上。只有几何体可以设置纹理坐标,因此在设置节点的纹理坐标之前,必须得到该节点子树中所有的几何体对象并设置它们的纹理坐标。为几何体对象geom的纹理单元0设置纹理坐标的具体代码如下:
osg::ref_ptr<osg::Vec2Array> texcoords = newosg::Vec2Array;
texcoords->push_back(…);
…
Geom->setTexCoordArray(0,texcoords.get());

其中,texcoords为纹理坐标,Geom为几何体对象,setTexCoordArray()用于设置几何体对象的纹理坐标数组。
上述方式虽然能实现矢量要素的符号化,但由于此方法每次只能将单个矢量要素进行纹理映射,当加载海量矢量要素时,绘制效率受到影响。


(二)着色器阶段实现矢量要素纹理映射的方法

分析上述方法存在的不足,在此基础上,本文提出了在着色器阶段基于纹理映射实现矢量要素符号化的方法。此方法的主要思想在于利用GPU的高速计算能力和可编程的功能,将纹理映射在着色器阶段实现。采用并行计算能力达到本文预期实现的矢量要素高效符号化的结果。

(1) 顶点着色器主要实现顶点位置的传入与将一些用于后期编程的主要参数的传入(符号尺寸、旋转角度、符号类型等)。具体如下:

gl_TexCoord[0] = vec4(a_size,a_rotation,a_markerType,1.0); gl_Position = gl_Vertex;
   其中,a_size,a_rotation,a_markerType为传入参数(符号尺寸、旋转角度、符号类型等),将其传入纹理坐标数组中;并将所有的顶点坐标数据并行地加入顶点着色器。

(2) 几何着色器主要实现顶点坐标的计算,纹理坐标的设置,并将点要素根据传入参数拓展成一个矩形。
根据传入参数计算拓展成的几何体的具体算法如下:

     float r= sqrt(earthHeart.x*earthHeart.x+earthHeart.y*earthHeart.y+earthHeart.z*earthHeart.z);floata = gl_PositionIn[0].x-earthHeart.x;floatb = gl_PositionIn[0].y-earthHeart.y;floatc = gl_PositionIn[0].z-earthHeart.z;floatw = gl_PositionIn[0].w;floats = gl_TexCoordIn[0][0].x/30000;floatra = radians(gl_TexCoordIn[0][0].y-45);floatrb = radians(gl_TexCoordIn[0][0].y+45);floatrc = radians(gl_TexCoordIn[0][0].y+135);floatrd = radians(gl_TexCoordIn[0][0].y+225);floatmarkerType = gl_TexCoordIn[0][0].z;
   其中,earthHeart为地球球心的数组,ra,rb,rc,rd分别为所需矩形的四个顶点坐标的角度,并计算球心至矢量要素所在位置的距离,存入变量r中。

接下来对每个顶点数据进行图元处理,确定整个渲染模型的形状。以下以其中一个顶点数据为例,实现在片元着色器之前创建新的顶点和形状。

     gl_TexCoord[0]= vec4(1, 1, markerType, 1);gl_Position= gl_ModelViewProjectionMatrix * vec4(gl_PositionIn[0].x+s/(2*sqrt((r*r)/(b*b)-1))*(-a*cos(rc)+r*c/b*sin(rc)),gl_PositionIn[0].y+s/(2*sqrt((r*r)/(b*b)-1))*((r*r)/b-b)*cos(rc),gl_PositionIn[0].z+s/(2*sqrt((r*r)/(b*b)-1))*(-c*cos(rc)-r*a/b*sin(rc)),w);gl_FrontColor= gl_FrontColorIn[0]; EmitVertex();

其中,gl_TexCoord[0]为纹理坐标,gl_Position为地理坐标,gl_FrontColor为正面颜色,通过顶点坐标传入的顶点坐标数组以及旋转角度参数,经过旋转变换、投影变换等,求得新的顶点的地理坐标;并通过将纹理坐标绑定到相应的地理坐标上,为之后的纹理贴图做好准备;EmitVertex()方法将新产生的顶点加入到几何着色器中。
以上步骤就完成了一个顶点的创建,通过重复上述步骤,新建多个顶点并将其加入到几何着色器中,从而实现点形成面的过程。
(3) 片元着色器是实现矢量要素符号化的核心阶段,也是实现纹理映射的关键。具体步骤如下:
i. 二维纹理的创建,具体实现如下:

osg::ref_ptr< osg::Image> iLogo =osgDB::readImageFile( Images/Buoy.png );osg::Texture2D*texLogo = new osg::Texture2D( iLogo.get() );texLogo->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR );texLogo->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR );
osg::ref_ptr< osg::Uniform > texLogoUniform=newosg::Uniform( tex, 0 );

以上步骤通过图像(Image)实现创建二维纹理,并且设置二维纹理的参数,将此二维纹理添加入统一变量(Uniform),便于在片元着色器中调用。
ii. 片元着色器中调用二维纹理,具体实现如下:

uniform sampler2D tex;
vec4 color = texture2D(tex,gl_TexCoord[0].st);
gl_FragColor = color;

其中,texture2D()方法实现将纹理坐标(gl_TexCoord[0])与二维纹理(tex)进行绑定,并将其存入颜色的四维数组(color),赋给OpenGL的内置变量gl_FragColor。从而实现纹理映射。
基于几何的方法将矢量数据与地形网格紧密关联起来,在地形起伏状况比较大的情况下,要求矢量数据附着于地形表面,需要解决的问题在于地物与地形相匹配。如果地物与地形不匹配,则可能会出现地物悬浮在地形上方或陷入地表等与真实世界不相符的状况。国内外相关的研究集中在解决矢量数据与地形表面精确匹配的问题,其效果大都不太理想,究其原因,在于矢量数据转换到地形中渲染时,在同一个层次下矢量数据的顶点不能很好的离散插值到地形表面上。


几何符号法


(一) 逐矢量要素几何构建的方法
逐矢量要素几何构建的方法的实现流程:遍历整个矢量数据集,单个数据构建单独的叶节点(Geode),并逐个加入到场景树中,具体实现过程如下所示:

for( FeatureList::iterator f = features.begin(); f!= features.end(); ++f ){Feature*input = f->get();GeometryIteratorparts( input->getGeometry(), true );while(parts.hasMore() ){Geometry*part = parts.next();osg::ref_ptr<osg::Geometry>osgGeom = new osg::Geometry();osg::Vec3Array*allPoints = new osg::Vec3Array();osgGeom->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, allPoints->getNumFeature()) );osgGeom->setVertexArray(allPoints );geode->addDrawable(osgGeom );}}

其中,features为矢量要素集,osgGeom为几何体对象,geode 为叶节点,setVertexArray()用于设置几何体对象的点要素数组,addDrawable()用于添加几何体对象到叶节点中。
在现有OsgEarth框架下,每当获取一次矢量数据源生成相应的几何体(Geometry)后,将几何体加入到子节点(Geode)中,然后将节点添加入场景树。此方法当数据量较大时,循环次数随之增加,必然会导致内存压力,在渲染速度上迅速下降,而且浏览过程中会导致卡顿现象,效率不能达到本文所预期的效果。


(二) 着色器阶段实现几何符号化的方法
本文在此基础上,结合实际需求,考虑矢量要素的多形式表达,研究设计典型的符号库,从而达到支持非制图工作者便捷使用地图符号的目的。此方法的主要思想在于利用GPU的高速计算能力和可编程的功能,将纹理映射在着色器阶段实现,通过在着色器建立不同符号的计算模型,从而实现矢量要素的多种符号化表达。
根据上一节中GPU加速的基于纹理的矢量要素符号化方法中关于着色器的实现流程,本文已实现在几何着色器中,将符号化形状的参数(markerType)传入到纹理坐标数组中,接下来,将会在片元着色器中通过逐像素着色的原理实现特定符号的形状,并附着特定颜色。
本文实现了常见类型形状的着色,包括正方形、圆形、三角形、五边形等,接下来以简单的图形符号(三角形)为例,介绍其实现符号化的主要原理,具体实现如下:

if(markerType>=1.5&&markerType<2.5){if((0.5-gl_TexCoord[0].x)*2-gl_TexCoord[0].y>=0 ||(gl_TexCoord[0].x-0.5)*2-gl_TexCoord[0].y>=0)discard;}

其中markerType为传入的符号化形状的参数,discard用于将像素丢弃,不进行渲染。通过判断像素是否在形状区域内部,剔除外部像素,从而达到符号化的效果。


下图为使用此方法的多几何形状的符号化结果。

GPU可编程渲染的矢量点要素符号三维可视化相关推荐

  1. 斯图加特大学GPU光线投射体渲染技术提携

    斯图加特大学GPU光线投射体渲染技术介绍 前言:在以往人们的印象中,美国的CG技术是一世界第一流的,而没有注意德国CG技术的发展.事实上,德国大学的CG是相当高的,与美国第一流的大学学术交往非常频繁. ...

  2. 《GPU高性能编程CUDA实战》中代码整理

    CUDA架构专门为GPU计算设计了一种全新的模块,目的是减轻早期GPU计算中存在的一些限制,而正是这些限制使得之前的GPU在通用计算中没有得到广泛的应用. 使用CUDA C来编写代码的前提条件包括:( ...

  3. [译]基于GPU的体渲染高级技术之raycasting算法

    [译]基于GPU的体渲染高级技术之raycasting算法 PS:我决定翻译一下<Advanced Illumination Techniques for GPU-Based Volume Ra ...

  4. GPU图形图像渲染原理

    目录 引言 GPU 历史 GPU 图形渲染流水线 GPU 存储系统 GPU 流处理器 CPU-GPU 异构系统 GPU 资源管理模型 CPU-GPU 工作流 屏幕图像显示原理 引言 原文链接 http ...

  5. 异构计算(CPU + GPU)编程简介

    异构计算(CPU + GPU)编程简介 1.概念 所谓异构计算,是指CPU+ GPU或者CPU+ 其它设备(如FPGA等)协同计算.一般我们的程序,是在CPU上计算.但是,当大量的数据需要计算时,CP ...

  6. CPU+GPU异构计算编程简介

    异构计算(CPU + GPU)编程简介 1. 概念 所谓异构计算,是指CPU+ GPU或者CPU+ 其它设备(如FPGA等)协同计算.一般我们的程序,是在CPU上计算.但是,当大量的数据需要计算时,C ...

  7. GPU高性能编程CUDA实战(二)

    视觉IMAX的第45篇文章 前言 在上一篇文章中: CUDA工程的建立(两种方法) 第一种方法: 这种方法在 接下来实施「三步走战略」配置「附加包含目录」.「附加库目录」以及「附加依赖项」.第一步:配 ...

  8. openacc的Linux安装教程,科学网—opensuse 13.1 系统 openACC编译器使用及GPU并行编程环境配置 - 马小军的博文...

    本文讲述opensuse13.1系统openACC编译器使用及GPU并行编程环境配置. 这里以笔记本显卡驱动为NVIDIA为例 在安装前,请确保系统已经安装kernel-devel ,kernel-s ...

  9. 《GPU高性能编程》——gl_helper.h

    <GPU高性能编程 CUDA实战> 书中 gl_helper.h 文件分享 <GPU高性能编程CUDA实战>是一本不错的好书,其中所含示例代码,经常包含有 "gl_h ...

最新文章

  1. poj 2516 最小费用最大流
  2. Win7备份的取消与磁盘空间恢复
  3. 广西2021各校高考成绩查询入口,2021年广西高考成绩排名查询系统,广西高考位次排名查询...
  4. javascript技术教程蔡敏_程序员都必掌握的前端教程之JavaScript基础教程(上)
  5. 2021年宝鸡中学高考成绩查询,宝鸡各高中2020年高考喜报成绩一览
  6. 开源 协作工具_使用HackMD在开源项目上进行协作
  7. 共享单车当废铁卖 ofo回应:已达报废年限
  8. oracle 10g rac 停止,Oracle10g RAC 关闭及启动
  9. 【剑指offer】62、圆圈中最后剩下的数字
  10. java从入门到进阶
  11. 斐讯K1K2刷机固件教程!最新最全整理版!(小米路由、newifi通用)
  12. 手把手教你制作一个操作系统
  13. 将罗马字符串转换为整数(C#)
  14. 06_因果图法、判定表法、场景法
  15. 依赖倒置原则应用-司机开车案例
  16. 小程序behavior
  17. html5图片弹性布局,HTML5 使用弹性框布局实现可选择和压缩的网格
  18. Markdown编辑器-初始模板参考
  19. 国家开放大学 操作系统 行测2这个答案是92分的
  20. 小米手环6天空人天气表盘

热门文章

  1. 让你的Android开发效率提高10倍的开源工具库AndroidTools的使用
  2. 如何恢复手机误删的短信?只需三招就能恢复
  3. 【沁恒WCH CH32V307V-R1在RT-Thread Studio上环境配置教程】
  4. weblogic集群问题(1)
  5. 牛!清华学霸作息表冲上热搜
  6. 4.3计算机动画制作 教案,计算机动画制作1教案
  7. 苹果电脑的标志为何被咬了一口?纪念同志天才图灵
  8. Java 写一段蔡徐坤跳舞的代码
  9. JAVA微信小程序美食菜谱系统毕业设计 开题报告
  10. 《神经网络与深度学习》邱希鹏 学习笔记(3)