GLSL 2D 圆角

GLSL 2D Rounded corners

我想在我的游戏屏幕上添加一些黑色轮廓,使它看起来像是圆角。 这是我想要达到的效果:

我认为使用着色器创建这种效果可能很容易,而不是在所有内容之上绘制一个巨大的位图。

有人可以帮我处理这个效果的 GLSL 着色器代码吗?我有 0 个着色器经验,无法在互联网上找到类似的东西。

我无意中找到了一个很好的解决方案。不完全符合您的要求,但实际上它看起来更好。

// RESOLUTION is a vec2 with your window size in pixels.
vec2 pos = fragCoord.xy / RESOLUTION;
// Adjust .2 (first pow() argument) below to change frame thickness.
if (pos.x * pos.y * (1.-pos.x) * (1.-pos.y) < pow(.2,4.))
    fragColor = vec4(0,0,0,1);

结果如下:

如果你不喜欢那些细线,你可以通过放大图像来删除它们。可以通过添加此行来完成:

// The .985 is 1/scale_factor. You can try to change it and see how it works.
// It needs to be adjusted if you change frame thickness.
pos = (pos - .5) * .985 + .5;


虽然这个效果看起来不错,但只添加一个微弱的阴影可能更聪明。
使用相同的等式很容易实现:pos.x * pos.y * (1.-pos.x) * (1.-pos.y)
它的值范围从 window 边缘的 0.0 到中心的 0.5^4
您可以使用一些简单的数学运算来使阴影在靠近 window 边缘时变得更厚。
Here is an example of how it may look.
(来自 Duality 的屏幕截图,我的 Ludum Dare 35 条目。)

感谢@HolyBlackCat,我的着色器现在可以工作了。我改进了性能并使其看起来更平滑。

varying vec4 v_color;
varying vec2 v_texCoord0;

uniform vec2 u_resolution;
uniform vec2 u_screenOffset;

uniform sampler2D u_sampler2D;
const float max = pow(0.2, 4);

void main()
{
    vec2 pos = (gl_FragCoord.xy - u_screenOffset) / u_resolution;

    float vignette = pos.x * pos.y * (1.-pos.x) * (1.-pos.y);

    vec4 color = texture2D(u_sampler2D, v_texCoord0) * v_color;
    color.rgb = color.rgb * smoothstep(0, max, vignette);

    gl_FragColor = color;
}

在libGDX的调整大小事件中设置制服如下:

shader.begin();
shader.setUniformf("u_resolution", viewport.getScreenWidth(), viewport.getScreenHeight());
shader.setUniformf("u_screenOffset", viewport.getScreenX(), viewport.getScreenY());
shader.end();

这将确保着色器也适用于视口(仅使用 FitViewport 测试过)。