Shaders with Scene2D

Objective: 

A minimalist example on how to use Shaders with LibGDX. In this case a Shockwave/Ripple effect.

This does not explain how Shaders work. For that I would start with:

  1. LibGDX Shader wiki
  2. The book of Shaders.

In this code sample I take a simple Shockwave / ripple Shader available on Shadertoy and demonstrate how it can be drawn as an Actor in a Scene2D.

This hopefully will give you the basics to translate more shaders.

The Shadertoy shader used as the base is available here

How this works:

The shader is applied to a texture and rendered using the spritebatch. With Scene2D the spriteBatch is rendered through the draw method, called on each of the actors on the stage.

In order to apply the shader we create a Group Actor: Anything you want to be passed through the shader is simply added to the Group rather than the Stage. In this case we add the Shockwave actor to the stage and add the image to the Shockwave Actor.

Our main screen therefore looks like this:

public class MyGdxGame extends ApplicationAdapter {
   private Stage stage;

   @Override
   public void create () {
      stage = new Stage(new ScreenViewport());
      Gdx.input.setInputProcessor(stage);
      Texture texture = new Texture(Gdx.files.absolute("background.jpg"));

      stage.addActor(ShockWave.getInstance());

      Image image1 = new Image(texture);
      image1.setPosition(0,0);
      image1.setSize(Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
      image1.addListener(new ClickListener() {
         public void clicked(InputEvent event, float x, float y) {
            ShockWave.getInstance().start(x,y);
         }
      });

      ShockWave.getInstance().addActor(image1);

   }

   @Override
   public void render () {
      Gdx.gl.glClearColor(1, 1, 1, 1);
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
      stage.act();
      stage.draw();

   }
}

Easy right?

Let´s take a look at the ShockWave Actor.

When the Group is drawn, it creates a Framebuffer, draws all the children in the frambuffer and then applies the Shader to the Framebuffer texture.

The code for the ShockWave actor is here

  • The Vertex Shader in this case is a simple pass through.
  • The Fragment Shader is where the magic happen. It takes as parameter the screen location where the shockwave is to be rendered.

Both files are stored in the Asset Folder.

This then can be used for example for explosions or other ripple effects.

The Source Code is available on github here