Dynamic lighting

Make games! Discuss those games here.

Moderators: Bob the Hamster, marionline, SDHawk

Post Reply
lennyhome
Slime Knight
Posts: 115
Joined: Fri Feb 14, 2020 6:07 am

Dynamic lighting

Post by lennyhome »

It's a proof of concept I wanted to make for a while. It does dynamic lighting with sub-tile precision.
https://sourceforge.net/projects/snes9l ... g/download
It's very unoptimized and quite expensive to compute in scripting alone in real time but it's practical and it could also be used to pre-calculate static lights for dungeons at the start of the map only.
No screenshots because it's a dynamic effect. Just load it up and walk in the middle of the field. I'll get into details in case anybody's interested.
User avatar
Spoonweaver
Liquid Metal King Slime
Posts: 6462
Joined: Mon Dec 08, 2008 7:07 am
Contact:

Re: Dynamic lighting

Post by Spoonweaver »

Looks pretty cool.
Allow me to share a gif of it in action for people to see.
lighting0000.gif
lighting0000.gif (1.98 MiB) Viewed 1366 times
lennyhome
Slime Knight
Posts: 115
Joined: Fri Feb 14, 2020 6:07 am

Re: Dynamic lighting

Post by lennyhome »

Thank you very much for the GIF and the interest. The source code is with my compiler here:
https://sourceforge.net/projects/snes9l ... z/download
In "hsc/misc/lighting.hss". My compiler uses C-like operators and a more C-like syntax but other than that it should be easy to port it over to the standard compiler.

The basic idea is very dumb and it's derived from this:
https://en.wikipedia.org/wiki/Bresenham ... _algorithm
with the difference that instead of drawing pixels, I'm doing a scan checking if a line reaches from a source to a destination without crossing any occluder.

For the sub-tile precision you can look into the tilesets and you'll see that there's a row of 16 possible shading patterns. I do the visibility check 4 times per tile. It produces a bit pattern and that bit pattern selects the shading tile.

And that's about it.

EDIT:
I've done some small cosmetic improvements and also improved the performance somewhat since the previous post. I just wanted to note a couple of things before I forget.
With the Bresenham line algorithm it's not the same thing to go from point A to point B or from point B to point A. The visibility checks are more stable going from the candidate sub-tile to the player than the other way around.
In the code you'll see multiplications and divisions by constants such as 16384, 8192, 4096... You'll notice that those are all powers of 2. My intent there was to do bit shifts but they're not supported by the VM at the moment.
I've also tried to avoid using my fix24 library and a special syntax I've built in my compiler to facilitate porting and also so maybe somebody can gain an understanding on how to improvise some fixed point math when needed.
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Re: Dynamic lighting

Post by TMC »

Nice, that's really smooth. I've never tried doing field of view with half-tiles, but I see it's a really effective way to improve the results.

I ported a recursive shadowcasting algorithm (which is much more efficient than ray-casting to every half-tile on screen as you are) to HS years ago for Carcere Vicis, which I've plugged into your lighting.rpg here, but it's only tilebased, and that algorithm has some fairly ugly artifacts. The script could probably be easily converted to half-tiles (since it also uses fixed precision) which would probably fix the artifacts. I might try it tomorrow. I also created an improved version of the algorithm (in a gdscript port) to compute partial tile visibility, which also fixes the problems.
And disappointingly my script is not that many times faster, but making it run on half-tiles will slow it by 4x. (However, it is updating tiles over the edge of the map, within a view radius).
lennyhome
Slime Knight
Posts: 115
Joined: Fri Feb 14, 2020 6:07 am

Re: Dynamic lighting

Post by lennyhome »

Initially I wanted to pair it with automapping to make some sort of soft shadow effect. But then I've realized that the total number of tiles on the screen in OHR is low and so I went for half-tiling blocks instead. Ideally it should be a combination of the two things. Maybe some clever tiling scheme could be found.

I wanted to do it in the simplest way possible because I intended to share the code and I also wanted to know if I could get away with it. Fun Fact: I also have a Megazeux version of it. But I'm looking at your algorithm and I've played Carcere Vicis a little bit and it's very interesting.

There's also another an improvement that could be made in respect to how the OHR walls work. As it is, I consider a tile with any wall as full occluder but instead one could consider specific wall bits depending on the octant that is being scanned.

If I had to implement it on real '80s hardware my concern would have been determining the lines gradients. That's the only place that requires a true division. Everywhere else is just additions and bit shifts, so I would have looked into some way to cache the line gradients. I think.
Post Reply