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

时间:2015-10-07 17:59:44

标签: glsl webgl shader simulation physics

我正在尝试使用着色器实现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,基于模拟的着色器看似随机行为的见解都将非常感激。

2 个答案:

答案 0 :(得分:0)

它似乎并不随机,建筑在看似正确的状态稳定并向不断的方向移动。

看起来你在着色器中应用了force然后在CPU端更新模型的位置,这个全局模型位置应该保持不变,或者应该被另一个值更新。

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

答案 1 :(得分:0)

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

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++;


        }
    }

}