
Graveyard Keeper: How the graphics effects are made - thrower123
http://www.gamasutra.com/blogs/SvyatoslavCherkasov/20181023/329151/Graveyard_Keeper_How_the_graphics_effects_are_made.php
======
gavanwoolery
Note on the usage of lookup tables: Color transitions are _hard_ \- their
example here looks pretty good but in general tweening between two color
spaces in a linear manner can produce unwanted "washing out" or dull in-
between states. The problem is not just within the transition of individual
colors, but how the relative values of nearby color affect our perception. For
example, see this illusion in action:
[https://twitter.com/AkiyoshiKitaoka/status/10284735661933158...](https://twitter.com/AkiyoshiKitaoka/status/1028473566193315841)

~~~
pistachiopro
Color transitions are hard, and that illusion is pretty trippy. Beyond that,
my sense is another big problem most people run into when they try to light
pixel art (or any hand-painted asset) is that the asset is almost always "pre-
tonemapped" by the artist. By first inverse-tonemapping the asset before
applying any lighting, and then re-tonemapping afterwards, you can get pretty
good results (assuming you can work out your artist's intuitive tonemapping
function). Here's a fun article which explores the idea a bit more:
[http://www.codersnotes.com/notes/untonemapping/](http://www.codersnotes.com/notes/untonemapping/)

~~~
garaetjjte
I think cause of this article problem is not that textures require some
"untonemapping", but that they are typically stored with sRGB gamma, and thus
should be converted to linear for lighting, and converted back to sRGB gamma
in final pass. (either by explicitly using 2.2 gamma in shaders, or graphics
API conversion, eg. in GL using GL_SRGB8_ALPHA8 format and sRGB framebuffer
with enabled GL_FRAMEBUFFER_SRGB)

------
city41
I worked on a game with very similar dynamic lighting. I wrote a blog post
that goes into more detail code-wise on how I did it if anyone is interested:
[http://www.mattgreer.org/articles/dynamic-lighting-and-
shado...](http://www.mattgreer.org/articles/dynamic-lighting-and-shadows/)

~~~
JoeMattie
Hi there! just wanted to say thanks for your write up. I recently implemented
this approach (thanks to your notes) in the Godot engine for a game I'm
working on.
[https://twitter.com/FlyingBastion/status/1054394571948417024](https://twitter.com/FlyingBastion/status/1054394571948417024)

~~~
city41
Oh nice, you were able to use my post? That's awesome. Your game is looking
good, I just followed you guys.

------
degenerate
At first I though the approach to dynamic lighting was overdone ("they had to
paint light sources manually 4 times?") but then remembered the world is not
3D, so there's no way to do it automatically without drawing defined
boundaries among objects. Painting 4 directional light sources and blending
them together is super smart.

I totally envy pixel artists, especially those from the earlier days of the
art. What a different world.

~~~
jweir
I got my start as a pixel editor/animator using Deluxe Paint and Deluxe
Animator for DOS at Virgin Games.

Hand anti-aliasing, selecting your limited palette, and working with the
hardware and screen constraints was fun. But, we at the time (early 90s)
couldn't wait to have more colors and more resolution and more framerate and
more memory.

So, folks today get to choose their constraints, which is important to most
art, and the results are lovely.

~~~
corysama
Just making sure you've already seen Mark Ferrari's GDC talk:
[https://www.youtube.com/watch?v=aMcJ1Jvtef0](https://www.youtube.com/watch?v=aMcJ1Jvtef0)
:)

------
bananaoomarang
Always surprised by how well effects like this work. Wouldn't expect the wind
shader to look as good as it does, for instance. Games (especially older
games...) are full of so many elegant hacks!

One that I think about a lot is how in order to animate a 'rain' effect, you
can actually just spawn randomly positioned 'impacts' on the ground and
randomly positioned raindrops that disappear 'behind' the ground. You would
think you might need to resolve each raindrop's collision and animate an
'impact' at the right point but it turns out our brain is pretty good at being
fooled.

~~~
a_e_k
The beginning of "A Link to the Past" went even simpler than that and just
looped a transparent rain layer over everything:
[https://i.imgur.com/W4fdw19.gif](https://i.imgur.com/W4fdw19.gif)

I think what helped sell it, though, was the rain and thunder sound effects.

------
mistercow
This is really neat. I was amused by this, though:

>I tried to add a skew there, but it turned out to be unnecessary.

and then

>It should be noted here, by the way, that the sprite is highly distorted
vertically (the shadow sprite original looks like a circle). That’s why its
rotation looks like not just a simple rotation but also like a distortion.

…which, if I recall my affine transforms, would also be called a "skew". I
think I get the point though. This let them construct the skew in a more
intuitive way than trying to make it an explicit parameter.

------
clarry
>The problem “how to find the closest 3 light sources and to calculate the
distance and an angle was solved with a script running in the Update() loop. >
> Yes, it’s not the quickest way considering how much math is involved. If I
programmed it today, I would use that modern Unity Jobs System. But when I did
it there was no such thing so I had to optimize regular scripts we had.

I wish they'd let you in on a little more. Because my numb mind says this
isn't something you should ever need to optimize. How many light sources do
they have, dozens at most? And how many sprites? Dozens/hundreds? That is
nothing.. what is this heavy math? I figured all they'd need is a vector from
light source to object, and the vector's magnitude.

~~~
BugsJustFindMe
Indeed. And you don't even need square roots for identifying the three
closest, since squared distances are just as good for that. So it's, what, a
few instances of very basic arithmetic and then three roots? I don't see the
complication either. It would be nice to know which part of their process
introduced the difficulty. Was it the update frequency?

~~~
simcop2387
I might even avoid the squares and use a manhattan distance metric instead. No
multiplication at all, just absolute value and addition.

------
davedx
I started porting my 2D roguelike game to a 2D engine like this one and got so
bogged down in lighting difficulties that I gave up and abandoned the project.

This is really impressive, and a succinct write up of what can take a very
long time to implement successfully. 2D/3D hybrid engines are hard!

------
randyrand
Gorgeous. Did you consider doing things in 3d with an isometric camera?

------
billfruit
Another recent game 'Brigador', also has earned much praise for its lighting
work, and as a game in general.

~~~
patio11
That game got a very interesting review in Japanese which I was compelled to
translate:

[https://gamedaisukinahito.blog.fc2.com/blog-
entry-954.html](https://gamedaisukinahito.blog.fc2.com/blog-entry-954.html)

[https://pbs.twimg.com/media/Dja-
bHqU0AEYJYe.jpg:large](https://pbs.twimg.com/media/Dja-bHqU0AEYJYe.jpg:large)

------
johnchristopher
Neat. Now I understand why modern "2D" pixel art games still sometimes need
some GPU and CPU power.

------
hughes
Images have been consistently failing to load on this article for the last few
hours.

~~~
a1369209993
Same here; `wget -HkKp` worked, albeit it took about a minute to actually
download everything (and also the CSS broke).

------
airstrike
What an interesting read. Thanks for finding and sharing.

