Print Page | Close Window

How to shadow your sprites?

Printed From: Pixel Joint
Category: The Lounge
Forum Name: Resources and Support
Forum Discription: Help your fellow pixel artists out with links to good tutorials, other forums, software, fonts, etc. Bugs and support issues should go here as well.
URL: https://pixeljoint.com/forum/forum_posts.asp?TID=26274
Printed Date: 11 September 2025 at 9:07pm


Topic: How to shadow your sprites?
Posted By: Jin9310
Subject: How to shadow your sprites?
Date Posted: 21 May 2018 at 2:05am
Hello,

I am working on one game project along with my friend and I would like to ask you for help. We are doing an isometric piece and I came across problem with shadow of the sprites. Well I have figured out some 'work-around' but it doesn't seem right :) So I wanted to ask you guys, if you have some tips&tricks that you are using while shadowing your sprites, if any, or if you leave the shadows completely on programmer, perhaps?

I am using Aseprite and friend of mine is programming in GameMaker. What I did is a new layer to my sprite in which I create a shadow of the object. After that I simply change the opacity of that 'shadow'. Now this can work quite good, until the shadow of one sprite gets into the shadow of other sprite, which creates even 'new' darker shadow. And that is not really cool. Attaching some pictures for better demonstration (hope my description is understandable:)).






Cheers and Thanks!



Replies:
Posted By: eishiya
Date Posted: 21 May 2018 at 10:29am
If the little tree is in the shadow of the big tree, the normally-lit parts of the sprite should be in shadow. It doesn't cast an additional shadow because shadow is the absence of light, and the light there is already absent. Also, don't forget that your scene is 3D, and that the little tree is rising up, it's not going sideways out of the shadow. Just adding the shadows simply does not work well, since that's a 2D process.
This is what it should look like:

(Also, watch your shadows/highlights, the shading on the big tree doesn't match the light direction suggested by the cast shadow.)

Hopefully having an image of what you need will help you figure out how to achieve it.

IMHO the easiest option is to have a top light source, so that all the shadows are directly beneath the object and thus don't overlap other objects (except maybe character sprites walking underneath trees, but those shadows adding won't look too bad). The shadows can then be included in the sprite without problems, it looks good, it avoids shadows affecting the composition of the scene, and it doesn't require the programmer to do anything.


If you really want to have long cast shadows, then I think what you need to do is more complicated than just having alpha-blending shadows in the sprites. You're going to need a shadow map. The easiest is just a B&W map where each pixel is either white (no shadow) or black (shadow). The shadow map would need to be drawn in two (or three) passes:
1. Render all the shadows cast by objects onto the map. These can be generated programmatically from the shape of the sprite, or created from additional shadow assets assigned to each sprite. The shadows should NOT be included in the sprites themselves, since then they'll just overlap with the shadow map and make a mess. If you erase the silhouettes instead of shading them, you can simply cycle through every object and erase its silhouette from the map with no other checks, which makes the code simpler and faster.
2. Cycle through the list of vertical objects in the scene. For each object, if that object's base falls into an area that's been rendered as shadow in the shadow map, then add that object's sprite's silhouette to the shadow map (or the opposite - set the sprite's silhouette to white, so that shadows don't overlap objects, which avoids many awkward shading scenarios and lets your scene remain bright and shiny). Be careful to avoid having objects shade themselves. For the best results, do this second pass on a copy of the shadow map instead of modifying the first one, or starting from the top so that a tall object in the front doesn't accidentally affect the shading of objects behind it.
This can be done at run-time, but if your world isn't dynamic, you could pre-render these for each scene to save processing power.

Render the shadow map on top of the scene at a low-ish opacity and you're done :D For best results, don't just render it as-is, but colourize the black parts a little. Shadows look best when they've not just darker versions of the original colours.

If you want to get really fancy, you could use the erase-silhouette version of the algorithm, but also replace the sprites of objects that are in shadow with manually shaded versions that don't have highlights. This can be done at run-time, or manually during level creation if the world isn't dynamic.

Edit: here's an illustration in case the text isn't clear: https://i.imgur.com/AMp97Ta.png (sorry for the text link, damn forum wouldn't let me link it properly)
In this example, the shadow map is colourized (the shadow pixels are a light blue colour) and then Multiplied onto the scene.


Posted By: Jin9310
Date Posted: 30 May 2018 at 3:41am
First of all, thank you so much for such extensive answer!

At this point I am doing a top light source as it seems to be the fastest way now, since we don't have much time :) (nor experience)
However I really like the option with shadow map and already have made myself some notes. Will definitely give it a try before jumping to other projects.

Once again thank you very much for your help ;)

cheers



Print Page | Close Window