【问题标题】:GLSL 2D Rounded cornersGLSL 2D 圆角
【发布时间】:2016-08-29 20:50:42
【问题描述】:

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

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

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

【问题讨论】:

  • 顺便说一句,我的游戏是用 Java 中的 libGDX 编写的。

标签: opengl glsl rounded-corners


【解决方案1】:

我偶然发现了一个很好的解决方案。不完全符合您的要求,但实际上看起来更好。

// 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)
它的值范围从窗口边缘的0.0 到中心的0.5^4
您可以使用一些简单的数学运算来制作更靠近窗口边缘的阴影。
Here is an example of how it may look.
(来自Duality 的屏幕截图,我为 Ludum Dare 35 输入的条目。)支持>

【讨论】:

  • 有没有办法应用某种 AA 来达到这种效果?感谢您的快速回复顺便说一句,非常感谢。 GotDownvotedFeelsBadMan
  • @kwantuM 是的。试着自己做。它遵循与我回答中最后一条建议相同的原则。
  • 我明天会尝试实现它,感谢您的帮助。如果我遇到困难,我会发表评论:)
  • 我已经改进了您的答案,使其变得平滑,并且不使用“if”,因为它会导致性能问题。
  • @kwantuM 很好。但是为什么你认为if 会导致性能问题?我能找到的所有引用都说if 可能会执行两个分支并丢弃其中一个导致性能损失,但它不应该对这段代码产生太大影响。
【解决方案2】:

感谢@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的resize事件中设置uniforms如下:

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

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

【讨论】:

    猜你喜欢
    • 2021-09-15
    • 1970-01-01
    • 1970-01-01
    • 2021-05-04
    • 1970-01-01
    • 1970-01-01
    • 2011-02-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多