在libgdx中使用ShaderProgram创建一个用于游戏内菜单叠加的覆盖层

6

目前正在制作一款游戏,并尝试在点击“菜单”按钮时获取一个覆盖屏幕的叠加层 - 这应该是相当常见/简单的事情,但仍然在实现过程中遇到问题。

我当前的设置:

  • TiledMapRenderer:用于呈现TMX瓷砖(背景/地图)
  • SpriteBatch:用于各种资产(例如玩家图像)
  • Stage:用于容纳菜单按钮
  • ShaderProgram:使用GLSL创建叠加层/阴影效果
  • SpriteBatch和地图设置为使用ShaderProgram

正如许多人建议的那样,为了提高性能,我只使用一个SpriteBatch - 因此各种资产和菜单Stage都使用同一个SpriteBatch。

着色器的目的是添加一个暗/半透明的叠加层,使屏幕变灰,因此打开菜单时更容易阅读。

我遇到的主要问题是,因为资产和菜单共享同一个SpriteBatch,它们也共享同一个着色器...所以,当我启用着色效果时,所有东西(包括背景和菜单按钮)都会变成灰色。

如何只使用一个SpriteBatch,但仅将Shader应用于背景(并保持菜单按钮正常/未着色)?


一些想法:使用第二个SpriteBatch?只在特定的z阈值之后应用灰度效果? - Stefan Hanke
2
据我理解,使用多个SpriteBatch对性能有显著影响,因此我只使用了一个SpriteBatch。 - pyko
2个回答

9
  • 你可以使用:setShader(ShaderProgram shader)

  • 你可以在着色器中添加一些逻辑来启用叠加效果(一个uniform变量,读取某个varying属性等),但不建议这样做,因为每行代码都会在每秒执行数千次。

  • [推荐] 你可以实际绘制一个真正的叠加层。有一个小灰色纹理(8x8像素)带有透明度,在背景之后和菜单之前绘制它。这将在屏幕坐标上显示,就像菜单一样,对吗?所以它也不会增加任何复杂性(创建足够大的精灵即可)。

  • [高级] 如果你的游戏在按下菜单键时暂停,你可以在点击菜单按钮时将屏幕复制到FBO中。然后你可以对图像进行后处理(变暗、模糊),并将其用作菜单的背景。这将允许更好的效果,并且实际上更有效率,因为整个场景的绘制被“缓存”在fbo内(绘制单个fbo纹理比重新计算整个场景更快)。


好奇,为什么你建议绘制一个实际的覆盖层?更高效吗?还是因为它更简单。 (覆盖层可能会覆盖整个屏幕)。以前从未使用过FBO,我会研究一下 :) - pyko
1
原因1是它完全与游戏(背景)渲染解耦。我的意思是,当菜单未显示时,它不会对性能产生任何影响。如果您使用“可配置”的着色器,则添加的那些“if”语句将在每个顶点、每帧执行。您应该优化游戏渲染,这肯定是瓶颈,而分离菜单就是一种优化。原因2- 是的,它更简单,您不需要过多地优化菜单(因为它不是瓶颈),所以您添加的复杂性越少,效果越好。//(在您的情况下,FBO就像屏幕截图) - aacotroneo
谢谢回复!这正是我发现的 - 着色器实现的性能比图像叠加差。将研究FBO以获得高级效果 :) - pyko
1
FBO的快速入门。与其将背景绘制到屏幕上,您可以将其绘制到FBO中(如果要进行像模糊这样的操作,其中较低的分辨率不会有影响,可以使其小于屏幕大小以进行优化)。该FBO将具有“屏幕截图”,您可以使用它来代替真实的背景。您还可以对其应用高级和昂贵的效果,因为它们仅应用一次,而不是每帧都应用。祝好运!=) - aacotroneo

2

在libgdx论坛上询问后,我找到了解决方法 - 解决方案是在着色器中设置强度,然后在绘制下一个物体之前刷新批处理(即spriteBatch.flush())。

大致如下...

spriteBatch.start();
//draw stuff
spriteBatch.flush();
// set shader strength/variables
// draw more stuff (is now affected by shader)
spriteBatch.end();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接