I'm making a game in libgdx where the main character has a light on him and where the light doesn't reach it should be dark, I'm using the setBlendFunction from SpriteBash to emulate the light. My problem is I don't know how I can make all around the light texture dark, I could size the light texture to fit the whole screen but that would be sloppy and an inconveniente in code. Does anyone have any ideas? Thanks you.
Here is a picture of the game showing my problem
This is typically done with a FrameBuffer.
You want to instantiate and recreate as necessary in the resize()
method so it always matches the size of the screen/window. In resize()
:
if (frameBuffer != null && (frameBuffer.getWidth() != width || frameBuffer.getHeight() != height)){
frameBuffer.dispose();
frameBuffer = null;
}
if (frameBuffer == null){
try {
frameBuffer = new FrameBuffer(Pixmap.Format.RGBA8888, width, height, false);
} catch (GdxRuntimeException e){ // device doesn't support 8888
frameBuffer = new FrameBuffer(Pixmap.Format.RGB565, width, height, false);
}
}
And in render()
, before drawing anything in your game, you first draw the shadow map on the frameBuffer:
frameBuffer.begin();
Gdx.gl.glClearColor(/* ... */); // This will be your ambient color, a dark color, like gray
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
spriteBatch.setProjectionMatrix(camera.combined); // same camera as your game scene
spriteBatch.setBlendFunction(GL20.GL_ONE, GL20.GL_ONE); //additive blending
spriteBatch.begin();
// draw light sprites, such as a white circle where your character is standing
spriteBatch.end();
frameBuffer.end();
Then draw your game scene normally. Don't forget to change your blend function back to what you normally use (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA by default) before drawing that. And finally, draw the shadow map over the game:
// Use identity matrix so you don't have to worry about lining up the frame buffer texture
spriteBatch.setProjectionMatrix(spriteBatch.getProjectionMatrix().idt());
// Set multiplicative blending for shadows
spriteBatch.setBlendFunction(GL20.GL_ZERO, GL20.GL_SRC_COLOR);
spriteBatch.begin();
spriteBatch.draw(frameBuffer.getColorBufferTexture(), -1, 1, 2, -2); //dimensions for full screen with identity matrix
spriteBatch.end();