使用 2D metaballs 绘制具有恒定厚度的轮廓

Using 2D metaballs to draw an outline with a constant thickness

我将 metaballs 的概念应用到我正在制作的游戏中,以显示玩家已经选择了几艘船,就像这样 http://prntscr.com/klgktf

但是,我的目标是保持此轮廓的粗细不变,这不是我使用当前代码得到的结果。

我正在使用 GLSL 着色器来执行此操作,并将一个统一的船舶位置数组传递给碎片着色器 (u_metaballs)。

顶点着色器:

#version 120

void main() {
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

碎片着色器:

#version 120

uniform vec2 u_metaballs[128];

void main() {
    float intensity = 0;

    for(int i = 0; i < 128 && u_metaballs[i].x != 0; i++){
        float r = length(u_metaballs[i] - gl_FragCoord.xy);
        intensity += 1 / r;
    }

    gl_FragColor = vec4(0, 0, 0, 0);
    if(intensity > .2 && intensity < .21)
        gl_FragColor = vec4(.5, 1, .7, .2);
}

我试过调整强度范围,甚至将 1 / r 更改为 10000 / (r ^ 4) 这(虽然没有任何意义)有点帮助,但它不能解决问题。

如有任何帮助或建议,我们将不胜感激。

经过更多的教导,即使在单次通过中也是可行的......你只需计算到最近的元球的距离,如果小于或等于边界厚度渲染片段,否则丢弃它......这里的例子(假设单四边形<-1,+1> 渲染覆盖整个屏幕):

顶点:

// Vertex
varying vec2 pos;       // fragment position in world space
void main()
    {
    pos=gl_Vertex.xy;
    gl_Position=ftransform();
    }

片段:

// Fragment
#version 120
varying vec2 pos;

const float r=0.3;  // metabal radius
const float w=0.02; // border line thickness
uniform vec2 u_metaballs[5]=
    {
    vec2(-0.25,-0.25),
    vec2(+0.25,-0.25),
    vec2( 0.00,+0.05),
    vec2(+0.30,+0.35),
    vec2(-1000.1,-1000.1),  // end of metaballs
    };

void main()
    {
    int i;
    float d;
    // d = min distance to any metaball
    for (d=r+r+w+w,i=0;u_metaballs[i].x>-1000.0;i++)
     d=min(d,length(pos-u_metaballs[i].xy));
    // if outside range  ignore fragment
    if ((d<r)||(d>r+w)) discard;
    // otherwise render it
    gl_FragColor=vec4(1.0,1.0,1.0,1.0);
    }

预览: