Skip to content

Instantly share code, notes, and snippets.

@mattdesl
Created August 15, 2013 15:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattdesl/6241893 to your computer and use it in GitHub Desktop.
Save mattdesl/6241893 to your computer and use it in GitHub Desktop.
Two-pass lighting shader for 2D games
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.FrameBuffer;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
public class LightingGame implements ApplicationListener {
private OrthographicCamera camera;
private SpriteBatch batch;
private Texture light;
private Texture background;
private FrameBuffer lightMap;
private TextureRegion fboRegion;
private ShaderProgram shadowShader;
private ShaderProgram defaultShader;
@Override
public void create() {
camera = new OrthographicCamera(1024/2, 300);
camera.position.set(1024/4, 300/2, 0);
camera.update();
batch = new SpriteBatch();
background = new Texture(Gdx.files.internal("data/tiles.png"));
light = new Texture(Gdx.files.internal("data/light.png"));
lightMap = new FrameBuffer(Format.RGBA8888, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);
fboRegion = new TextureRegion(lightMap.getColorBufferTexture(), 0, 0, lightMap.getWidth(), lightMap.getHeight());
fboRegion.flip(false, true);
setupShaders();
}
public void setupShaders(){
defaultShader = SpriteBatch.createDefaultShader();
String vertexShader = "attribute vec4 " + ShaderProgram.POSITION_ATTRIBUTE + ";\n" //
+ "attribute vec4 " + ShaderProgram.COLOR_ATTRIBUTE + ";\n" //
+ "attribute vec2 " + ShaderProgram.TEXCOORD_ATTRIBUTE + "0;\n" //
+ "uniform mat4 u_projTrans;\n" //
+ "varying vec4 v_color;\n" //
+ "varying vec2 v_texCoords;\n" //
+ "\n" //
+ "void main()\n" //
+ "{\n" //
+ " v_color = " + ShaderProgram.COLOR_ATTRIBUTE + ";\n" //
+ " v_texCoords = " + ShaderProgram.TEXCOORD_ATTRIBUTE + "0;\n" //
+ " gl_Position = u_projTrans * " + ShaderProgram.POSITION_ATTRIBUTE + ";\n"
+ "}\n";
String fragmentShader = "#ifdef GL_ES\n" //
+ "#define LOWP lowp\n" //
+ "precision mediump float;\n" //
+ "#else\n" //
+ "#define LOWP \n" //
+ "#endif\n" //
+ "varying LOWP vec4 v_color;\n" //
+ "varying vec2 v_texCoords;\n" //
+ "uniform sampler2D u_texture;\n"
+ "uniform sampler2D u_texture1;\n"
+ "uniform vec2 lightMapResolution;\n"
+ "void main()\n"//
+ "{\n" //
+ " vec4 texColor0 = texture2D(u_texture, v_texCoords); \n"
+ " vec4 texColor1 = texture2D(u_texture1, gl_FragCoord.xy / lightMapResolution); \n"
+ " vec4 shadow = texColor0 * vec4(0.5, 0.5, 0.5, 1.0);\n"
+ " vec4 light = texColor0;\n"
+ " gl_FragColor = mix(shadow, light, texColor1.a);"
+ "}";
shadowShader = new ShaderProgram(vertexShader, fragmentShader);
if (!shadowShader.isCompiled()) {
System.err.println(shadowShader.getLog());
System.exit(0);
}
if (shadowShader.getLog().length()!=0)
System.out.println(shadowShader.getLog());
}
@Override
public void dispose() {
batch.dispose();
}
@Override
public void render() {
// Draw lightMap
lightMap.begin();
Gdx.gl.glClearColor(0, 0, 0, 0.0f);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
batch.setShader(defaultShader);
batch.begin();
batch.draw(light, Gdx.input.getX()-light.getWidth()/2f, Gdx.graphics.getHeight()-Gdx.input.getY()-light.getHeight()/2f);
batch.end();
batch.flush();
lightMap.end();
// Draw normal stuff
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.setShader(shadowShader);
batch.begin();
shadowShader.setUniformf("lightMapResolution", lightMap.getWidth(), lightMap.getHeight());
shadowShader.setUniformi("u_texture1", 1);
lightMap.getColorBufferTexture().bind(1);
background.bind(0);
batch.draw(background, 0, 0);
batch.end();
}
@Override
public void resize(int width, int height) {
camera.setToOrtho(false, width, height);
}
@Override
public void pause() {
}
@Override
public void resume() {
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment