Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using ShaderProgram in libgdx to create an overlay for in-game menu

Tags:

shader

libgdx

Currently making a game and trying to do get an overlay to cover the screen when the "menu" button is clicked - something that I would imagine should be fairly common/simple, but still having problems implementing it.

The current setup I have:

  • TiledMapRenderer: to render TMX tiles (background/map)
  • SpriteBatch: for various assets (eg. player image)
  • Stage: to hold the menu buttons
  • ShaderProgram: using GLSL to create the overlay/shading effect
  • SpriteBatch and map are set to use the ShaderProgram

As suggested by many people, for performance, I am only using one SpriteBatch - so the same sprite batch is used by both the various assets and menu Stage.

The aim of the shader is to add a dark/semi-transparent overlay to grey out the screen so the menu will be easier to read when it is open.

The main issue I'm having is that because the assets and menu share the same SpriteBatch, they also share the same shader...so, when I enable the shading effect everything (background and menu buttons) is greyed out.

How can I use only one SpriteBatch but only apply the Shader to the background (and keep the menu buttons normal/unshaded)?

like image 476
pyko Avatar asked Feb 22 '13 13:02

pyko


2 Answers

  • you can use: setShader (ShaderProgram shader)

  • you could add some logic to your shader to enable the overlay (a uniform, read some varying attribute, etc), but this is not recommended because every line you put there gets executed thousand times per second.

  • [Recommended] you could actually draw a real overlay. Have a small gray texture (8x8px) with transparency and draw it after the background and before the menu. That would be on screen coordinates, just like the menu, right? so it won't add any complexity either (create a sprite big enough).

  • [Advanced] providing your game pauses when you press the menu, you could copy your screen to a FBO when the menu button is clicked. Then you can post-process the image (darken, blur), and use that as the background for the menu. That would allow nicer effects, and would be actually more efficient, as the hole scene drawing gets "cached" inside the fbo (it's faster to draw a single fbo texture, than recompute the hole scene).

like image 185
aacotroneo Avatar answered Oct 20 '22 07:10

aacotroneo


After asking around on the libgdx forums, figured it out - the solution was to set the strength in the shader, then flush the batch (ie. spriteBatch.flush()) before drawing the next thing.

So roughly...

spriteBatch.start();
//draw stuff
spriteBatch.flush();
// set shader strength/variables
// draw more stuff (is now affected by shader)
spriteBatch.end();
like image 2
pyko Avatar answered Oct 20 '22 09:10

pyko