How to add shadows to textures?

@ghost8bit, you might want to take a look a the 2D shadow work that Rene Aye has done. He has created a 2D shadow library. Here are some resources on the topic.

2D Shadows Example

https://www.youtube.com/watch?v=L5qNrGk1cII

2D Shadow Library code:

https://bitbucket.org/reneaye/corona-2d-shadow-system/

Hangout Discussion with Rene Aye:

https://youtu.be/wtNuzLwFLxI?t=2364

Thanks guys for the answers,

@StarCrunch, sure, It must illustrate what I said about

image.png

As It shows, shadow affects the background. 

“Save the direction” means that the light source doesn’t change it’s position, so if you rotate an image the shadow doesn’t change it’s direction (from the up-right to rhe down-left or somehow).

@Rob, I thought about it, but it cant help fully, I mean, it would help with creation of a filter, but you cant apply the filter to that shape along the image.

@Charles, Yea, It’s only the lib I could find when I looked for shadow creating but anfortunately it doesn’t suit (the images above shows my case).

Now I think about applying image-shaped mask to a gradient filled square, how’d you think can it cope with the problem?

Okay, I figured it might be something like that, or I’d have thrown Rene’s (terrific) stuff your way too.  :slight_smile:

No promises, but I’ve been considering decent multi-pass effects to show, if we have time, during the shader segment on Monday’s Corona Geek. I’m not very satisfied with my current example, so I might try this. I have an idea that would build on the technique horacebury used here: Create a drop shadow

Oh, that sounds pretty cool, It’d be great if you show smth at Corona Geek!!! 

So, on this moment I have the following:

\_W=display.contentWidth \_H=display.contentHeight local background = display.newRect(\_W/2,\_H/2,\_W, \_H) background:setFillColor(0.6, 0.6, 0.8) --object we want to be with shadow local ball = display.newImage('30\_3@2x.png', \_W/2, \_H/2) local size = 10 -- shadow object local ballshadow = display.newImage( '30\_3@2x.png', \_W/2 - size+5, \_H/2 + size-5) ballshadow:setFillColor(0)--it fills our obj with black colour not touching the background of the image --here's a trick for fill.effect, we just make shadow-image's canvas bigger local r = display.newRect( ballshadow.x, ballshadow.y, ballshadow.width\*2, ballshadow.height\*2 ) r:setFillColor(0, 0) --take black obj with extended canvas into the group local g = display.newGroup() g:insert(r) g:insert(ballshadow) --turn a groupObj into a displayObj local c = display.capture( g ) --apply blur filter and set alpha c.fill.effect = "filter.blurGaussian" c.fill.effect.horizontal.blurSize = 10 c.fill.effect.horizontal.sigma = 128 c.fill.effect.vertical.blurSize = 10 c.fill.effect.vertical.sigma = 128 c.alpha = 0.7 c.x = ballshadow.x c.y = ballshadow.y display.remove( ballshadow ) c:toBack() background:toBack()

BUT:

Corona windows simulator shows neither object nor it’s shadow

Android app shows only the object

Corona mac simulator shows everything perthectly

Xcode ios simulator shows only the object

I wanna ask Corona labs: What the heck is going on???

image.png

Hi.

My best guess, if that’s your complete code, is that you’re falling afoul of the “Capture on Launch” issue, as described in the gotchas here: display.capture() Try putting all the code after you load your group into a timer, as done there.

Or maybe  g is still in the way? I see you removed ballshadow instead…

That said, it’s looking pretty good so far! The main novelty I think I could introduce, where the shader would come in, would be a little directional steering.

Hello!

Yeah it was that issue, now it works perfectly good (and yes I had to remove the whole g instead of ballshadow, thanks for the point)

Thank you very very much! God bless you, good man!

Okay, we’ll see how it plays out today. Probably will be tight on time, but at any rate I ran with your code and made this:

Shadow Multi-Pass

The shadow breaks up a bit, which I think is fixable by averaging a few neighbors. As is, it would be worth making a talking point of that sort of thing anyway. (I tried rearranging the multi-pass order, since after all we are doing a blur, but got an error. It looks like filter.blurGaussian is already multi-pass itself and maybe there are some quirks!)

@nasibullin The image is not working, so I guess you want to make something like a dropshadow like the Photoshop layer effects?

Furthermore in your code you are using the gaussianblur filter. I played a lot with it for my camera system with depth of field effects like here: http://devilsquid.com/how-a-2d-camera-system-makes-your-game-more-stylish-and-easier-to-develop-part-2/

All I can say is, that the gaussian blur filter does not work with mobile devices in real time. I don’t know why, but the filter must be recalculated on every frame which slows everything down on mobile devices. On desktop the filter is working fine for me.

But as long as your sprites do fit on the screen, maybe you can capture the filtered sprite once, and then remove the filter.

Best
René

@ René Out of curiosity, how recent are the devices you’re using? I’ve run into the same performance issues, but was unsure whether what I have isn’t just too old. I should have followed up on this and mentioned the second capture.

@ nasibullin Obviously just a basic shift in position is a pretty lame excuse for another shader, so I’ve thrown some color into my example too. But my purposes are intended for illustration, of course. Since you probably just need the shift, those calculations can of course all be done in Lua, say in an enterFrame handler.

Also, how was your own performance?

I tested with a iPhone 5 not (5S). The FPS dropped that much, that I decided to not investigate into this technique. But since the desktop comnpilers are out now, the camera system might be interesting for desktop apps. Right now I’m on vacation any my internet connection is rather lame here. When I’m back home I can test it with an iPad Air 2, but I think the FPS will drop too. The docs also do not recommend to use the blur filter for realtime effects. So I think only workaround is to capture the blurred object into a new image and then kill the original gauss blur filter.

I tested with iPad Air 2 and the FPS drops too. Not that much like on an iPhone 5 but definitely too much to use the blur filter on a mobile device in realtime.

this is such a simple/basic effect, that if performance is a concern, then i’d suggest just resorting to an “old tech” solution, and forget about any real-time gaussian blurs and such via shaders.

just precreate a monochrome mask of your sprite, blurred by some R.  then draw that under your sprite, offset by some XY, at partial transparency, possibly using multiply blend mode if normal doesn’t look right (tho just normal blend mode will probably look right if your shadow mask is truly mono black with alpha – use multiply if “faking it” with a grayscale-no-alpha bitmap).

now if you rotate them both synchronously, but keep the XY offset the same in global coords, it’ll preserve the illusion of a constant light source direction.  plus photoshop preprocessed blur will probably look better than your real-time blur anyway AND cost no real-time cpu to generate, just a single additional bitmap to render underneath (which is “cheap” in relative performance terms).

Old tech!

Exactly what I was thinking… but then I am old!

… and if the image you are trying to shadow moves, then create a physics joint between the object and it’s shadow.

Also, depending on how you may want multiple objects/shadows to interact, you can add the main objects and shadows to two different display groups.

Place the shadow group below the objects group and they will appear in two distinct layers. All shadows in the ‘background’ layer.

That way if two objects are placed close to each other the shadows still fall behind them.