public
Created

Two-pass lighting shader for 2D games

  • Download Gist
LightingGame.java
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
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() {
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.