使用模拟着色器时的随机速度

random velocities when using simulation shader

我正在尝试使用着色器实现 Fruchterman Reingold 模拟。在着色器中实现计算部分之前,我将其写在 javascript 中。它完全符合我的预期,如下所示:

http://jaredmcqueen.github.io/gpgpu-force-direction/canvas_app.html

在着色器中实现计算部分时,我得到了一个在屏幕上随机漂移的稳定结构。我无法弄清楚是什么排斥力/吸引力导致我的图表如此不可预测地浮动:

http://jaredmcqueen.github.io/gpgpu-force-direction/gpgpu_app.html

物理学的核心来自排斥/吸引函数:

//fr(x) = (k*k)/x;
vec3 addRepulsion(vec3 self, vec3 neighbor){
    vec3 diff = self - neighbor;
    float x = length( diff );
    float f = ( k * k ) / x;
    return normalize(diff) * f;
}

//fa(x) = (x*x)/k;
vec3 addAttraction(vec3 self, vec3 neighbor){
    vec3 diff = self - neighbor;
    float x = length( diff );
    float f = ( x * x ) / k;
    return normalize(diff) * f;
}

任何关于为什么 gpgpu、基于模拟的着色器表现得看似随机的任何见解都将不胜感激。

它看起来不是随机的,建筑稳定在看似正确的状态并朝着恒定的方向移动。

看起来您在着色器中施加了力,然后更新了模型在 CPU 侧的位置,这个全局模型位置应该保持不变,或者应该已经更新了另一个值。

根据我在代码中看到的内容,我建议消除浮点比较 (compareNodePosition.w == -1.0 || 0.0) 和 continue 运算符。请说是否有帮助。我还没有研究算法逻辑。

事实证明我错误地遍历了边缘。这是我的新边缘迭代:

float idx = selfEdgeIndices.x;
float idy = selfEdgeIndices.y;
float idz = selfEdgeIndices.z;
float idw = selfEdgeIndices.w;

float start = idx * 4.0 + idy;
float end = idz * 4.0 + idw;


if(! ( idx == idz && idy == idw ) ){

    float edgeIndex = 0.0;

    for(float y = 0.0; y < edgesTexWidth; y++){
        for(float x = 0.0; x < edgesTexWidth; x++){


        vec2 ref = vec2( x + 0.5 , y + 0.5 ) / vec2(edgesTexWidth,edgesTexWidth);
        vec4 pixel = texture2D(edgeData,ref);

        if (edgeIndex >= start && edgeIndex < end){
            nodePosition = getNeighbor(pixel.x);
            nodeDiff.xyz -= addAttraction(currentNodePosition.xyz, nodePosition);
        }
        edgeIndex++;

        if (edgeIndex >= start && edgeIndex < end){
            nodePosition = getNeighbor(pixel.y);
            nodeDiff.xyz -= addAttraction(currentNodePosition.xyz, nodePosition);
        }
        edgeIndex++;

        if (edgeIndex >= start && edgeIndex < end){
            nodePosition = getNeighbor(pixel.z);
            nodeDiff.xyz -= addAttraction(currentNodePosition.xyz, nodePosition);
        }
        edgeIndex++;

        if (edgeIndex >= start && edgeIndex < end){
            nodePosition = getNeighbor(pixel.w);
            nodeDiff.xyz -= addAttraction(currentNodePosition.xyz, nodePosition);
        }
        edgeIndex++;


        }
    }

}