Created
August 15, 2013 15:41
-
-
Save mattdesl/6241893 to your computer and use it in GitHub Desktop.
Two-pass lighting shader for 2D games
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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