Graphics 使用二维变形球绘制具有恒定厚度的轮廓

Graphics 使用二维变形球绘制具有恒定厚度的轮廓,graphics,2d,glsl,shader,geometry-surface,Graphics,2d,Glsl,Shader,Geometry Surface,我将metaballs的概念应用到我正在制作的游戏中,以显示玩家已经选择了几艘船,如下图所示 然而,我的目标是保持这个大纲的恒定厚度,而这不是我在当前代码中得到的 我使用一个GLSL着色器来实现这一点,并将船只的统一位置数组(u_变形球)传递给碎片着色器 顶点着色器: #version 120 void main() { gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; } 碎片着色器: #version 120 uni

我将metaballs的概念应用到我正在制作的游戏中,以显示玩家已经选择了几艘船,如下图所示

然而,我的目标是保持这个大纲的恒定厚度,而这不是我在当前代码中得到的

我使用一个GLSL着色器来实现这一点,并将船只的统一位置数组(u_变形球)传递给碎片着色器

顶点着色器:

#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);
}
#版本120
均匀vec2u_元球[128];
void main(){
漂浮强度=0;
对于(int i=0;i<128&&u_元球[i].x!=0;i++){
float r=长度(u_变形球[i]-gl_FragCoord.xy);
强度+=1/r;
}
gl_FragColor=vec4(0,0,0,0);
如果(强度>0.2和强度<0.21)
gl_FragColor=vec4(.5,1,7,2);
}
我尝试过使用强度范围,甚至将1/r改为10000/(r^4),这(虽然没有意义)有点帮助,但并不能解决问题


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

经过更多的教学,即使是单次通过,也可以。。。您只需计算到最近的变形球的距离,如果小于或等于边界厚度渲染片段,则放弃它。。。这里的示例(假设单个四元
呈现覆盖整个屏幕):

顶点:

//顶点
可变vec2位置;//碎片在世界空间中的位置
void main()
{
pos=gl_顶点.xy;
gl_位置=F变换();
}
片段:

//片段
#版本120
可变vec2位置;
常数浮点r=0.3;//变形半径
常量浮点w=0.02;//边界线厚度
统一vec2 u_元球[5]=
{
vec2(-0.25,-0.25),
向量2(+0.25,-0.25),
vec2(0.00,+0.05),
向量2(升0.30,升0.35),,
vec2(-1000.1,-1000.1),//元球结束
};
void main()
{
int i;
浮动d;
//d=到任何变形球的最小距离
对于(d=r+r+w+w,i=0;u_元球[i].x>-1000.0;i++)
d=最小值(d,长度(pos-u_变形球[i].xy));
//如果超出范围,则忽略片段
如果((dr+w))丢弃;
//否则渲染它
gl_FragColor=vec4(1.0,1.0,1.0,1.0);
}
预览:


使用片段着色器方法可能无法实现恒定厚度。您可以在CPU上提取等值线,并将该信息作为线带传递给GPU。或者可以根据片段着色器的结果进行基于图像的细化。不过,这可能在计算上比较重。好的,谢谢!我会试试这个,我会让你知道它是否有效。从预览来看,它有点违背了使用Metaball的目的,但出于我的目的,它是一样的,所以我将以此作为我问题的解决方案。顺便问一下,在这种情况下,使用discard而不是gl_FragColor=vec4(0,0,0,0)是否会对性能产生任何影响?@汤姆,我想应该快一点,或者同样的速度。真正的区别在于,通过将颜色设置为
vec4(0,0,0,0)
而不进行混合,可以将像素清除为黑色。。。因此,如果你有任何bacground gfx或已渲染的内容,它将被黑色覆盖。通过使用其类似的透明度。。。因此,您可以轻松地将此着色器与其他渲染内容相结合。另一方面,discard无法优化为无分支,因此,如果您编码了一些类似于
if
语句的等式(就像我对
d
所做的那样),则无分支颜色设置可能会更快。