【问题标题】:Using 2D metaballs to draw an outline with a constant thickness使用 2D 元球绘制具有恒定厚度的轮廓
【发布时间】:2018-08-24 01:02:36
【问题描述】:

我将元球的概念应用到我正在制作的游戏中,以表明玩家选择了几艘船,例如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) (虽然这没有意义)有点帮助,尽管它不能解决问题。

任何帮助或建议将不胜感激。

【问题讨论】:

  • 使用片段着色器方法可能无法实现恒定的厚度。您可以在 CPU 上提取等值线并将该信息作为线带传递给 GPU。或者,您可以对片段着色器的结果进行基于图像的细化。不过,这可能计算量更大。

标签: graphics 2d glsl shader geometry-surface


【解决方案1】:

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

顶点:

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

预览:

【讨论】:

  • 好的,谢谢!我会试试这个,如果它有效,我会告诉你。
  • 从预览来看,它有点违背了使用元球的目的,但就我的目的而言,它是相同的,所以我将把它作为我问题的解决方案。
  • 顺便问一下,在这种情况下使用丢弃而不是 gl_FragColor = vec4(0, 0, 0, 0) 对性能有影响吗?
  • @Tom 我认为丢弃应该更快或相同的速度。真正的区别在于,通过将颜色设置为vec4(0,0,0,0) 而不进行混合,您将像素清除为黑色......因此,如果您有任何免费的 gfx 或已经渲染的东西,它将被黑色覆盖。通过使用丢弃它的类似透明度......所以您可以轻松地将这个着色器与其他渲染内容结合起来。另一方面,discard 无法优化为无分支,因此如果您对一些模拟 if 语句的方程进行编码(就像我为 d 所做的那样),无分支颜色设置可能会更快。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-24
  • 2021-04-14
  • 1970-01-01
  • 1970-01-01
  • 2019-01-25
  • 2016-02-15
  • 2017-10-31
相关资源
最近更新 更多