使用模拟着色器时的随机速度
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++;
}
}
}
我正在尝试使用着色器实现 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++;
}
}
}