Light values

Hi,

The image shown shows how I’m doing light values, the light is the yellow square in the middle and the values around are the light values applied to the tiles.
Issue is, what do you do if lots of light sources are placed next to each other?

PS - I’m lightening tiles by using setColor.

I assume 16 is max?

If you have 2 light sources next to each other they will add to each other, bringing them higher than 16. This is the equivalent of being “overexposed” in camera terms.

To avoid this problem you can reduce your exposure (so your max is e.g. 4) but then your scene is pretty dim! Alternately, you can just cap all the values at 16, so no cell is ever more than “fully illuminated”.

Something like this. Probably in java.lang.Math. I use Lua and shaders more than I do java packages and it’s been a while since I went over and confirmed all a package contains lol.



public int max(int in, int default) {
return in1 > default ? default : in1;
}


There are multiple ways to deal with this.

The physically correct solution is to simply add the intensities together. Light does not interact with light, so two lights at the same place is equal to one light that is twice as bright. However, you’re not here for a physics lecture. =P

Something that may look good is to simply only use the strongest light value hitting the tile. This gives a stylized but decent result which may look good for you.

Another more advanced approach is to fake HDR and adapt the light values to what the human eye sees. Although two lights would result in twice the brightness, that’s not necessarily what our eyes see. Our eyes can deal with a huge range of light intensities after all. It’s possible to fake this using floating point values and blending. You can read more about this here: http://www.java-gaming.org/topics/fixing-saturation-with-additive-blending-by-faking-hdr/33171/view.html.

Feel free to ask if you want more info on anything specific.

Hey many thanks.

Yeah my physics isn’t great, only did it at high school level…

Here is what I got with placing a torch with max light value of 15:

And after placing a light pretty much next to this I get this ugly light scene:

As you can see, I’m not adding the light sources together.

My code:



static final int MAXLIGHTLEVEL = 15;
	static final int W = 20;
	static final int H = 15;

private static void setLightSource(int x, int y, BlankEntity[][] map, int lightLevel) {
		map[x][y].lightValue = lightLevel;
		updateTileLight(map, x, y);
	}

	private static void updateTileLight(BlankEntity[][] map, int lightX, int lightY) {
		
		int lightLevel = 0;
		for(int x = 0; x<1+W/2; x++)
		{
			for (int y = 0; y < (H / 2); y++) {
				lightLevel = MAXLIGHTLEVEL - x - y;
				if(lightLevel>15) lightLevel = MAXLIGHTLEVEL;
				if(lightLevel<0) lightLevel = 0;
				map[x+lightX][lightY - y].lightValue = lightLevel;
				map[x+lightX][lightY + 1 + y].lightValue = lightLevel;
			}
		}
		for(int x = 0; x<1+W/2; x++)
		{
			for (int y = 0; y < (H / 2); y++) {
				lightLevel = MAXLIGHTLEVEL - x - y;
				if(lightLevel>15) lightLevel = MAXLIGHTLEVEL;
				if(lightLevel<0) lightLevel = 0;
				map[lightX-x][lightY - y].lightValue = lightLevel;
				map[lightX-x][lightY + 1 + y].lightValue = lightLevel;
			}
		}
	}

The above code gets called when a light is placed. BlankEntity is a tile block, each have their own light level, thus when they are rendered I just do:


BlankEntity entity = getEntity(col, row);
						float r = 1 * (float) entity.lightValue / MAXLIGHT;
						float g = 1 * (float) entity.lightValue / MAXLIGHT;
						float b = 1 * (float) entity.lightValue / MAXLIGHT;
						batch.setColor(r, g, b, 1);

What would be the best way of working light values out if a few torches are placed say next to each other? Do I need to check for torches being near each other?

PS - the light that kinda shines from the player and looks like a torch is just a box2d light.

Many thanks again

New code which seems to correct the fault:


private static void updateTileLight(BlankEntity[][] map, int lightX, int lightY) {
		
		int lightLevel = 0;
		for(int x = 0; x<1+W/2; x++)
		{
			for (int y = 0; y < (H / 2); y++) {
				lightLevel = MAXLIGHTLEVEL - x - y;
				if(lightLevel>15) lightLevel = MAXLIGHTLEVEL;
				if(lightLevel<0) lightLevel = 0;
				
				if(map[x+lightX][lightY - y].lightValue < lightLevel)
					map[x+lightX][lightY - y].lightValue = lightLevel;
				
				if(map[x+lightX][lightY + 1 + y].lightValue < lightLevel)
					map[x+lightX][lightY + 1 + y].lightValue = lightLevel;

                                if(map[lightX-x][lightY - y].lightValue < lightLevel)
					map[lightX-x][lightY - y].lightValue = lightLevel;
				
				if(map[lightX-x][lightY + 1 + y].lightValue < lightLevel)
					map[lightX-x][lightY + 1 + y].lightValue = lightLevel;
			}
		}		
	}

So, basically just checking the block tile level before changing it, if it is lighter then leave it as it is…does this seem correct?

And a screen shot:

Thanks

Hi,

Was wondering if there would be a way of passing the light values to the shader? ::slight_smile:

Hi,

Having to lights working when adding, now need to work out how to ‘dim’ the tiles when lights are destroyed, any good ideas for this?

Any advice is appreciated.

Thanks

Each tile has a default.

If they are invisible when not lit, the value should be 0. If it is on the surface it should be 5. Lit it should be 10. Max lighting possible is 10 or 15 for super light.

Some method like that.

Your question’s a little vague but I’m going to assume it’s the tile-based lighting you’re having trouble with.

Since your lights are diamonds, recursion works fairly well. You would recurse in the four directions, checking if the tile is darker than your light source and continue spreading.

I used this method around a year ago in Project MP and it works really well. I dug up a code sample from that game, I don’t know if it’s much help but it gets the gist of it.

Here’s a picture of what it looked like.

It looks smoothed out because I sampled the 8 neighbouring tiles’ light values and made a gradient out of it.

Day/night cycles without being laggy with lighting updates is another story that I can explain if you want, but we’ll see if your problem’s solved before we move on.

Hi,

Sorry, I have lights working, using diamond style like minecraft. When a torch is placed, the area lights up, when I destroy this light, the tiles go back
to what there default light value is, my issue is if you have more than one torch say next to each other, if I destroy one of the lights, the tiles go
back to what there default light value is, when of course, they shouldn’t as there is another light next to the one just destroyed…

Thanks

Your blocks have a light value. Instead of reupdating just that one block when it’s placed, all the blocks in an area should get a lighting update after a block update (place, remove) where all the light sources are re-updated.

As you move around the world you’ll have to reupdate periodically.

Hi,

I update an area of blocks when a torch is placed down, what I’m thinking of doing is, when torch is removed, put blocks to original light value they are
originally set at an then check if any torches are in the area of this torch I just removed, if so, update blocks again…

I can see what you mean though by having to keep updating periodically where lights are concerned as blocks could be removed and placed dynamically near them…
Although I guess when block is placed, it could get light value from it’s neigbouring block?


onBlockUpdate() // placing or removal of a block
   lightingUpdate(in area)

afterPlayerHasGoneOutOfLightingUpdateRange()
   lightingUpdate(in new area around player)

lightingUpdate(boundaries)
      reset lighting in boundary
      iterate through area for light source blocks
         for each light source, do the recursive lighting stemming out of each block
      

Hi,

My plan was to:

  1. Render blocks with their default light colour
  2. When light placed, update color of blocks in certain boundary
  3. Remove light - reset blocks in boundary to original color value

The above is fine when only one torch and not adding/removing blocks - but of course, this is no good as you can have more than one torch and add/remove blocks dynamically.

So, like you mention Chrislo27, need to update periodically like you have shown in your pseudo code.

Got the lights working so when remove everything is updated, looks great.

One issue I do note though is the water, for some reason some flicker with the color when water comes
near a torch - probably something and nothing…

Anyway, put latest video in the WIP section :slight_smile:

Many thanks