赞
踩
IDW的实现比较简单,已知插值点位比较少的情况下,可以直接遍历所有插值点,来获取临近的几个点,进行插值运算。插值点较多时,需要可以使用kd-tree来加速临近点的查找。本次仅对小数据量情况进行讨论,将IDW算法在shader中实现,可以方便的使用webgl的裁剪面和强大的并行计算。具体计算流程如下:
数据提交,我使用了uniform
数组变量来存储,在渲染过程中,直接提交插值点位的数据,数据类型为vec3
,webgl我使用了twgl第三方库(为了偷懒), twgl可以减少编写原生webgl代码量。测试用的数据直接使用Math.random()
生成。
//points为math.random生成的测试数据
const uniforms = {
points: points
};
twgl.setUniforms(programInfo, uniforms);
需要注意,shader中声明的数据类型为vec3,使用x,y,z依次来存储位置,观测值。生成测试数据时,如果需要模拟300个点位,则需要生成的数组长度为300*3。即提交到uniform中的变量为:定点数的三倍。
IDW算法的生成需要用到,屏幕的像素坐标,所以应选用Fragment Shader,实现思路比较简单,插值点位的数据传入后,通过计算最近的两个点位的距离,来计算,该像素位置的观测值。webgl中内置的gl_FragCoord,可以方便的获取屏幕像素坐标。shader中的代码如下:
#version 300 es precision mediump float; uniform vec3 points[300]; //存储最近的点的索引,和距离 struct interpoPoint { int idx; float dist; }; interpoPoint queues[2]; out vec4 outcolor; //更新队列, void updatequeue(int idx,float dist){ if(dist<queues[0].dist){ queues[1]=queues[0]; queues[0].idx=idx; queues[0].dist=dist; }else if(dist<queues[1].dist){ queues[1].idx=idx; queues[1].dist=dist; } } float getCoorddist(vec2 coord,vec2 point){ float dertx=coord.x-point.x; float derty=coord.y-point.y; return dertx*dertx+derty*derty; } float getCoordColor(vec2 coord){ //前两个点位的距离更新到queues float dist0=getCoorddist(coord,points[0].xy); float dist1=getCoorddist(coord,points[1].xy); if(dist0<dist1){ queues[0].idx=0; queues[0].dist=dist0; queues[1].idx=1; queues[1].dist=dist1; }else{ queues[0].idx=1; queues[0].dist=dist1; queues[1].idx=0; queues[1].dist=dist0; } for(int i=2;i<300;i++){ float dist=getCoorddist(coord,points[i].xy); updatequeue(i,dist); } //idw float denominator=(1.0/queues[0].dist)+(1.0/queues[1].dist); float numerator1=points[queues[0].idx].z*(1.0/queues[0].dist)/denominator; float numerator2=points[queues[1].idx].z*(1.0/queues[1].dist)/denominator; return numerator1+numerator2; } void main(){ float color=getCoordColor(gl_FragCoord.xy); outcolor=vec4(vec3(color),1.0); }
效果图有些奇怪,边界特别明显,我用的指数为2,最近的点位个数为2,印象里应该是比较平滑才对,这里理论知识需要在复习一下。
最大的问题是,插值点位过多时,受限于uniform数据的个数限制,大量数据无法存放到shader的数组中
idw的指数,固定为2,想要直接使用的小伙伴,可以自行修改
idw中,临近点的个数,shader中固定为2,这里需要实现一个有序的队列,来实现大于2的点位查找。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。