GPU中实现反距离加权插值(IDW)

利用GPU实现IDW(反距离加权插值)

IDW的实现比较简单,已知插值点位比较少的情况下,可以直接遍历所有插值点,来获取临近的几个点,进行插值运算。插值点较多时,需要可以使用kd-tree来加速临近点的查找。本次仅对小数据量情况进行讨论,将IDW算法在shader中实现,可以方便的使用webgl的裁剪面和强大的并行计算。具体计算流程如下:

插值点位提交到GPU

数据提交,我使用了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中的变量为:定点数的三倍。

Shader中实现IDW算法

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

效果图

效果图有些奇怪,边界特别明显,我用的指数为2,最近的点位个数为2,印象里应该是比较平滑才对,这里理论知识需要在复习一下。
GPU中实现反距离加权插值(IDW)_第1张图片

现有问题

  • 最大的问题是,插值点位过多时,受限于uniform数据的个数限制,大量数据无法存放到shader的数组中

    • 可以使用生成texture的方法,来存放插值点的数据,同样的存在大量点位中查找最近的k个临近点的效率问题,暂时考虑使用kdtree来实现快速查找,但是需要在shader中实现对kdtree树的查找,这个断断续续看了两个月了,还没有实现,有大神一起做的话,欢迎讨论
  • idw的指数,固定为2,想要直接使用的小伙伴,可以自行修改

  • idw中,临近点的个数,shader中固定为2,这里需要实现一个有序的队列,来实现大于2的点位查找。

PS: 代码已提交,github地址,有在做相关内容的小伙伴,欢迎一起讨论

你可能感兴趣的:(idw,shader,gpu,webgl)