A more efficient way to do tile-based lighting?


(TaylorAnderson) #1

So I’m working on a game where you’re travelling on a path through a dark forest, and I’ve got a lighting engine thats basically just an overlay over every tile that changes its alpha depending on its distance from a light source. I’ve almost got this system running really well, the only thing that REALLY dents performance is the precise alpha changes that run for every tile on the screen. If I round alpha to the nearest first decimal place I get the performance I want, but the light looks really jittery. What I’m wondering is–is there a way to optimize this? My overlay is a simple square with no scaling, no rotating, absolutely nothing happening to it except alpha changes every frame. Do I have to use an image for this or is there something better? Or should I use a different method entirely?

Thanks,

Taylor


(azrafe7) #2

Have you tried @SHiLLySiT’s Lit or TileLighting?

Also… if you can share (at least some part of) you’re lighting system code, maybe we’ll come out with some suggestions on how to optimize it, or we’ll try to. :wink:


(TaylorAnderson) #3

The way I’m doing it doesn’t need to be very complicated, and I thought it’d be valuable knowledge to try to do it myself.

This is the update of my Tile class, which does all of the work:

override public function update():void
{
	
	lightRef = world.getInstance("lightref")
	if (canUpdate)
	{
		updateLights();
	}
	visible = onCamera && overlay.alpha < 1
	if (collide("tree", x, y))
		overlay.visible = false;
	if (this.y > FP.camera.y + FP.height-100)
	{
		world.recycle(this)
		Collidable(world.create(Collidable, true)).init(x, y)
	}
}
public function get canUpdate():Boolean
{
	for each(var s:LightSource in lightRef.lights)
	{
		if (FP.distance(x, y, s.x, s.y) < 170)
			return true;
	}
	return false;
}
public function updateLights():void
{
	distance = 200;
	for each(var s:LightSource in lightRef.lights)
	{
		if (FP.distance(x, y, s.x, s.y) < distance)
			distance = FP.distance(x, y, s.x, s.y)
		
	}
	overlay.alpha = distance/160
	//overlay.alpha = int((distance / 160) * 10) / 10
	

}

(Bora Kasap) #4

there is a way to do this.

First, you should override your screen completely with a transparent & black image file(thats the darkness). Then you should subtract pixel values from this black mask with another images which they are radial gradient masks of your light sources.

EDIT: Ahh, but that’s not tile based right? So, lets continue thinkig about…


(Jacob Albano) #5

You’re doing a getInstance() and a collide() call every frame for every tile; that’s going to seriously hurt you.

Instead of getting the reference of the “lightref” class every frame, try caching it and only get it if it’s null.

lightRef = lightRef || world.getInstance("lightref");

In addition, your canUpdate() call is doing the same exact loop as updateLights(), so it’s not actually saving you any time. FP.distance() is another fairly heavy function so doing that twice * number of lights is also cutting into your time.

Suggestions:

  • Assign the value of FP.distance(x, y, s.x, s.y) to a variable in updateLights(), so you’re not calculating it twice per loop.
  • Instead of attempting to skip updating the lights, call updateLights() no matter what, and skip lights that are too far away.
  • See if you can avoid checking for collision with trees every frame. Your trees aren’t moving (I hope :scream:), and if your tiles aren’t moving either you should only have to check it the first time it updates.

(azrafe7) #6

@jacobalbano You’re a ninja, man! :wink:

Was trying to write almost the same considerations (poorly!).

Only other thing I’d add is to try a distanceSquared function and see how much it improves performance, and maybe post some minimal project so that we can really play with it in order to boost FPS.


(TaylorAnderson) #7

I’m gonna implement @jacobalbano’s solutions and then if i’m still seeing fps issues i’ll post more code


(TaylorAnderson) #8

I don’t really know what else it could be…but I just remembered that I have Adobe Scout, that profiler everyone seems to like, so maybe I’ll run that and see if it shows me anything

EDIT: now i’m having issues with adobe scout too…computers dont like me today…gonna look through my source code for a little bit


(TaylorAnderson) #9

When I build the application and launch it as an AIR application the performance is much better, not 60fps consistently but pretty close. Maybe I’ll just leave it for now