Implementar interpolação ponderada de distância inversa (IDW) na GPU

Usando GPU para implementar IDW (interpolação ponderada de distância inversa)

A implementação do IDW é relativamente simples, quando existem poucos pontos de interpolação, é possível atravessar diretamente todos os pontos de interpolação para obter vários pontos próximos e realizar operações de interpolação. Quando existem muitos pontos de interpolação, é necessário usar o kd-tree para agilizar a busca de pontos adjacentes. Desta vez, apenas a pequena quantidade de dados é discutida. O algoritmo IDW é implementado no shader, que pode usar facilmente o plano de recorte do webgl e computação paralela poderosa . O processo de cálculo específico é o seguinte:

Envie os pontos de interpolação para a GPU

Para o envio de dados, usei uniformvariáveis ​​de matriz para armazenamento. Durante o processo de renderização, enviei diretamente os dados do ponto de interpolação. O tipo de dados é vec3webgl. Usei a biblioteca de terceiros twgl (para preguiça). Twgl pode reduzir a quantidade de escrita de código webgl nativo. Os dados usados ​​para teste são Math.random()gerados diretamente usando .

//points为math.random生成的测试数据
const uniforms = {
    points: points
};
twgl.setUniforms(programInfo, uniforms);

Deve-se observar que o tipo de dados declarado no shader é vec3, usando x, y e z para armazenar a posição e o valor de observação por sua vez. Ao gerar dados de teste, se você precisar simular 300 pontos, o comprimento da matriz que precisa ser gerada é 300 * 3. Ou seja, a variável submetida ao uniforme é: três vezes o número do ponto fixo.

Implementar algoritmo IDW no Shader

O algoritmo IDW precisa usar as coordenadas de pixel da tela, portanto, o Fragment Shader deve ser selecionado . A ideia de realização é relativamente simples. Depois que os dados do ponto de interpolação são transmitidos, eles são calculados calculando a distância entre os dois pontos mais próximos. De observações. O gl_FragCoord integrado no webgl pode obter facilmente as coordenadas de pixel da tela. O código no shader é o seguinte:

#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);
}

Imagem de efeito

As representações são um pouco estranhas e os limites são particularmente óbvios. O índice que usei é 2 e o número de pontos mais próximos é 2. A impressão deve ser relativamente suave. O conhecimento teórico aqui precisa ser revisto.
Insira a descrição da imagem aqui

Problema existente

  • O maior problema é que quando há muitos pontos de interpolação, limitados pelo número de dados uniformes, uma grande quantidade de dados não pode ser armazenada na matriz de sombreador

    • Você pode usar o método de geração de textura para armazenar os dados dos pontos de interpolação. O mesmo problema existe na eficiência de encontrar os k pontos vizinhos mais próximos em um grande número de pontos. Por enquanto, considere usar o kdtree para obter uma pesquisa rápida, mas você precisa implementar a árvore kdtree no sombreador Eu assisti isso intermitentemente por dois meses, mas não foi percebido ainda. Se há um grande deus para fazer isso, bem-vindo para discutir
  • O índice de idw é fixado em 2. Aqueles que desejam usá-lo diretamente podem modificá-lo por si próprios

  • Em idw, o número de pontos adjacentes é fixado em 2 no shader. Aqui, uma fila ordenada é necessária para encontrar pontos maiores que 2.

PS: O código foi enviado, endereço do github , há amigos que estão fazendo conteúdo relacionado, bem-vindo para discutir

Acho que você gosta

Origin blog.csdn.net/yue1241630499/article/details/109281055
Recomendado
Clasificación