前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >3.1.1 借助显卡GPU绘制Contour

3.1.1 借助显卡GPU绘制Contour

作者头像
周星星9527
发布2018-08-08 15:49:29
1.2K0
发布2018-08-08 15:49:29
举报

如何绘制标量场呢?我们常用诸如商业软件Tecplot,或者基于Python的开源软件包matplotlib中的contour绘制Contour图形(等值线)。这里介绍使用显卡GPU绘制Contour,使用flash的stage3D技术,目前而言flash过时了,但它的参考意义仍然在。

显卡是什么,笔者浅薄,先简单认为显卡擅长于画三角形,对三角形进行着色,渲染,加之诸如灯光、迷雾之类的效果。其实三角形是所有图形的基础,我们看到的大千世界也可以近视为若干三角形无缝拼接而成(貌似在画有限元的三角元网格,其实差不多),而每个三角形的顶点颜色各异,三角形内部的颜色是顶点颜色的线性插值(眼熟?和有限元中形函数似的,的确);也可以看作是将眼前的景象拍照,把照片遮挡在眼前看,这是GPU显示的另一种工作方式:贴图,这里不谈。所以我们如何操纵GPU绘制等值图呢?将离散区域分为有限个无缝连接的小三角形,然后用GPU绘制每个三角形即可得到整个域的等值图。下面给予一段网上(http://www.adobe.com/devnet/flashplayer/articles/hello-triangle.html)抄袭来的顶点着色器(Vertex Shader)的Demo,用GPU绘制一个三角形:

代码语言:javascript
复制
1. package
2. {
3.  import com.adobe.utils.AGALMiniAssembler;
4.  
5.  import flash.display.Sprite;
6.  import flash.display3D.Context3D;
7.  import flash.display3D.Context3DProgramType;
8.  import flash.display3D.Context3DVertexBufferFormat;
9.  import flash.display3D.IndexBuffer3D;
10.  import flash.display3D.Program3D;
11.  import flash.display3D.VertexBuffer3D;
12.  import flash.events.Event;
13.  import flash.geom.Matrix3D;
14.  import flash.geom.Rectangle;
15.  import flash.geom.Vector3D;
16.  import flash.utils.getTimer;
17.  
18.    [SWF(width="800", height="600",frameRate="60",backgroundColor="#FFFFFF")]
19.  public classHelloTriangleColored extends Sprite
20.    {
21.  protected varcontext3D:Context3D;
22.  protected varprogram:Program3D;
23.  protected varvertexbuffer:VertexBuffer3D;
24.  protected varindexbuffer:IndexBuffer3D;
25.  
26.  public functionHelloTriangleColored()
27.       {
28.          stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, initMolehill );
29.          stage.stage3Ds[0].requestContext3D();
30.  
31.          addEventListener(Event.ENTER_FRAME, onRender);
32.  
33.       }
34.  
35.  protected functioninitMolehill(e:Event):void
36.       {
37.          context3D= stage.stage3Ds[0].context3D; 
38.          context3D.configureBackBuffer(800,600, 1, true);
39.  
40.  var vertices:Vector.<Number> = Vector.<Number>([
41.             -0.3,-0.3,0,1, 0, 0, // x, y, z, r, g, b
42.             -0.3,0.3, 0, 0, 1, 0,
43.             0.3,0.3, 0, 0, 0, 1]);
44.  
45.  // Create VertexBuffer3D. 3 vertices, of 6 Numbers each
46.          vertexbuffer= context3D.createVertexBuffer(3, 6);
47.  // Upload VertexBuffer3D to GPU. Offset 0, 3 vertices
48.          vertexbuffer.uploadFromVector(vertices,0, 3); 
49.  
50.  var indices:Vector.<uint> = Vector.<uint>([0, 1, 2]);
51.  
52.  // Create IndexBuffer3D. Total of 3 indices. 1 triangle of3 vertices
53.          indexbuffer= context3D.createIndexBuffer(3); 
54.  // Upload IndexBuffer3D to GPU. Offset 0, count 3
55.          indexbuffer.uploadFromVector(indices, 0, 3); 
56.  
57.  var vertexShaderAssembler : AGALMiniAssembler = new AGALMiniAssembler();
58.          vertexShaderAssembler.assemble(Context3DProgramType.VERTEX,
59.             "m44 op, va0, vc0\n" + // pos to clipspace
60.             "mov v0, va1" //copy color
61.          );
62.  
63.  var fragmentShaderAssembler : AGALMiniAssembler= new AGALMiniAssembler();
64.          fragmentShaderAssembler.assemble(Context3DProgramType.FRAGMENT,
65.  
66.             "mov oc, v0"
67.          );
68.  
69.          program= context3D.createProgram();
70.          program.upload(vertexShaderAssembler.agalcode, fragmentShaderAssembler.agalcode);
71.       }
72.  
73.  
74.  protected functiononRender(e:Event):void
75.       {
76.  if ( !context3D ) 
77.  return;
78.  
79.          context3D.clear( 1, 1, 1, 1 );
80.  
81.  // vertex position to attribute register 0
82.          context3D.setVertexBufferAt(0, vertexbuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
83.  // color to attribute register 1
84.          context3D.setVertexBufferAt(1,vertexbuffer, 3, Context3DVertexBufferFormat.FLOAT_3);
85.  // assign shader program
86.          context3D.setProgram(program);
87.  
88.  var m:Matrix3D = new Matrix3D();
89.          m.appendRotation(getTimer()/40, Vector3D.Z_AXIS);
90.          context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX,0, m, true);
91.  
92.          context3D.drawTriangles(indexbuffer);
93.  
94.          context3D.present();
95.  
96.       }
97.  
98.    }
99. }

看不懂吧,正常,第一次接触Flash的3D编程,看不懂太正常了,等你看了他的入门后句会觉得简单,请搜索Molehill Flash。我们现在可以迁移这个技术到HTML5 webGL实现基于HTML5的Contour绘制,本教程目前只提供参考思路。

如此我们可以实现绘制等值图,如下是运行结果。

等等,还缺点什么?Legend,这个漂亮的东西困扰了我好久。2010年秋季,我去宣化做项目,几个老外在现场调试程序,隧围观之,不得不说,人家的用户体验确实到位,使用3D技术显示工业测控值。看到他们的Legend竟然是几段拼接而成,我恍然大悟,原来Legend是几组颜色过渡而成。下面是我曾经写基于Flex SDK有限元前处理和后处理程序包中的一个算法(),函数getGradualColor可以得到一组连续的颜色分布,程序不做解释,可意会,不可言传:

代码语言:javascript
复制
1. packageFEModel.util.visual
2. {
3.  public class ColorUtil
4.    {
5.  public static function combineRGB(r:uint,g:uint,b:uint):uint
6.       {
7.  if(r<0) r=0
8.  if(r>255) r=255;
9.  
10.  if(g<0) g=0
11.  if(g>255) g=255;
12.  
13.  if(b<0) b=0
14.  if(b>255) b=255;
15.  
16.  var RGB:uint=(r<<16)|(g<<8)|b;
17.  return RGB;
18.       }
19.  
20.  public static function getGradualColor(cnt:uint=10):Vector.<uint>
21.       {
22.  var colorList:Vector.<uint>=new Vector.<uint>(cnt+1,true);
23.  
24.  for(var i:uint=0;i<cnt+1;i++)
25.          {
26.  var ratio:Number=i/cnt;
27.  if(ratio<=0.25)
28.                colorList[i]=colorInR1(ratio);
29.  else if(ratio<=0.5)
30.                colorList[i]=colorInR2(ratio);
31.  else if(ratio<=0.75)
32.                colorList[i]=colorInR3(ratio);
33.  else
34.                colorList[i]=colorInR4(ratio);
35.          }
36.  return colorList.reverse();
37.       }
38.  
39.  public static function colorInR1(ratio:Number):uint
40.       {
41.          ratio/=0.25;
42.  return combineRGB(255,ratio*255,0);
43.       }
44.  
45.  public static function colorInR2(ratio:Number):uint
46.       {
47.          ratio=(ratio-0.25)/0.25;
48.  return combineRGB((1-ratio)*255,255,0);
49.       }
50.  
51.  public static function colorInR3(ratio:Number):uint
52.       {
53.          ratio=(ratio-0.5)/0.25;
54.  return combineRGB(0,255,ratio*255);
55.       }
56.  
57.  public static function colorInR4(ratio:Number):uint
58.       {
59.          ratio=(ratio-0.75)/0.25;
60.  return combineRGB(0,(1-ratio)*255,255);
61.       }
62.    }
63. }

给出Legend的绘制结果:

结语:本文简要介绍了基于GPU的Contour图绘制,这里鼓励感兴趣的同学使用HTML5 webGL实现Contour图的绘制。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-07-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 传输过程数值模拟学习笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档