Initiating vars etc:
Vector3 bright = new Vector3(6.3f, 6.3f, 6.7f); // Load shaders from text files vertexShader = Gdx.files.internal("data/shaders/vertexShader.glsl").readString(); defaultPixelShader = Gdx.files.internal("data/shaders/defaultPixelShader.glsl").readString(); finalPixelShader = Gdx.files.internal("data/shaders/pixelShader.glsl").readString(); ShaderProgram.pedantic = false; defaultShader = new ShaderProgram(Art.vertexShader, Art.defaultPixelShader); finalShader = new ShaderProgram(Art.vertexShader, Art.finalPixelShader);currentShader = finalShader; ambientColor = bright; finalShader.begin(); finalShader.setUniformi("u_lightmap", 1); finalShader.setUniformf("ambientColor", ambientColor.x, ambientColor.y, ambientColor.z, ambientIntensity); finalShader.end(); // Image for spot light light = new Texture(Gdx.files.internal("data/shaders/light.png")); fbo = new FrameBuffer(Format.RGBA8888, 1024, 788, false); finalShader.begin(); finalShader.setUniformf("resolution", 1024, 788); finalShader.end();
Render Loop
After setting up the variables and shader files in the render loop I adjusted the ambientColor over time to give affect of night day.
// Adjust ambientColor to give appearance of night/day finalShader.begin(); finalShader.setUniformi("u_lightmap", 1); finalShader.setUniformf("ambientColor", ambientColor.x, ambientColor.y, ambientColor.z, ambientIntensity); finalShader.end(); // I added logic to only show spotlight during night if(show_light){ fbo.begin(); fbo.getColorBufferTexture().bind(1); light_batch.setShader(defaultShader); light_batch.begin(); light.bind(0); light_batch.draw(light, hero.x-l_off+.4f,hero.y-l_off+.2f, light_size,light_size); light_batch.end(); fbo.end(); } // Draw your map here light_batch.setShader(currentShader); light_batch.begin(); MapGenerator.draw(gameController.camera, light_batch); light_batch.end();
Night
Evening
This solution limited me to using one spot light, also my knowledge of OpenGL Shader language is zero. At this point I went back to the LibGDX documentation and came across Box2dLights, a library that uses collision data from Box2D to create lights/shadows.
// BOX2DLIGHTS private PointLight spriteLight; private RayHandler rayHandler; // Create a new Box2D World, this is required. World world = new World(new Vector2(), true); RayHandler.useDiffuseLight(true); // Setup the new RayHandler, it will use the same camera as the main game rayHandler = new RayHandler(world); rayHandler.setCulling(true); rayHandler.setCombinedMatrix(gameController.camera.combined); rayHandler.setAmbientLight(1); // Light to follow the hero spriteLight = new PointLight(rayHandler, 50); spriteLight.setPosition(hero.x,hero.y); spriteLight.setDistance(5); spriteLight.setColor(3, 12, 33, 0.3f); // Keep the unique ID of the light hero_light = spriteLight.hashCode(); // this lights the map (Sun) spriteLight = new PointLight(rayHandler, 50); spriteLight.setPosition(hero.x-20,hero.y-20); spriteLight.setDistance(250); spriteLight.setColor(3, 12, 33, 0.5f); // Test shadow being cast by solid object PolygonShape tileShape = new PolygonShape(); tileShape.setAsBox(.5f, .5f); FixtureDef fixtureDef = new FixtureDef(); fixtureDef.shape = tileShape; fixtureDef.filter.groupIndex = 0; BodyDef tileBodyDef = new BodyDef(); float bodyX = hero.x-3; float bodyY = hero.y-4f; tileBodyDef.position.set(bodyX, bodyY); tileBodyDef.type = BodyType.StaticBody; Body tileBody = world.createBody(tileBodyDef); tileBody.createFixture(fixtureDef); // RENDER LOOP CODE rayHandler.setCombinedMatrix(gameController.camera.combined, gameController.camera.position.x, gameController.camera.position.y,gameController.camera.viewportWidth, gameController.camera.viewportHeight); rayHandler.updateAndRender();
Here I set up some basic lights, a small one for the hero and a large light to act as the sun, I added one solid object to show a shadow being cast. Would need to add bodies for each object in the game and update there positions. Here the alpha is set to low on the sun light to give impression of night:
Zoomed out, earlier in the day:
Multiple Lights
Accessing and looping through all lights is simple, we stored the hashcode of the hero light so on each render loop update its position, else change the alpha value; increase/decrease this value to simulate night to day and vice versa.
for (Light light : rayHandler.lightList) { if (light.hashCode() == hero_light){ light.setPosition(hero.x,hero.y); }else{ light.setColor(1, 1, 1, ambientIntensity); } }
where can I find the entire source code? Seems great.
ReplyDeleteI will set up a public repository for these tutorials. Sorry for slow response.
ReplyDeletePls when you upload your code ?
DeleteHow you display UI GAME with Box2DLight ?
With your demo code, my whole screen is Black except my light.
Pls help me ^^
me too
Delete