Jibble

Author Topic: Dynamic Shadows in AGS - idea for module  (Read 807 times)

Snarky

  • Global Moderator
  • Global Moderator
  • Mittens Lord
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Dynamic Shadows in AGS - idea for module
« on: 31 Jan 2020, 16:42 »
(Split off from this thread)

So we've got a light source that throws a conspicuous shadow behind a shovel.
player walks up to the shovel.
So now the light source would need to throw a conspicuous shadow behind player as well, wouldn't it?

And _that_ shadow is going to move around with player and probably change shape and size all the time …

I've sometimes toyed with the idea of making a module for this. It would work with regions to define the parts of the background on which character shadows would be drawn, and there'd be some configuration to define the direction of the shadow (and of the surface, e.g. vertical, horizontal). The module would then take the most appropriate character view (e.g. if facing forward and the shadow is pointing left, take the "face left" view), fill it with black, distort as appropriate, and draw semi-transparent on the BG.

Only very simple effects are possible, because you need full 3D to do it properly (for example, unless you assume an infinitely distant light source like the sun, things get significantly trickier), but it might be good enough for some scenarios.

When I first joined AGS back in 2004 there was a game in production that supposedly was going to do something like this, too. I forget the name…
« Last Edit: 03 Feb 2020, 17:48 by Snarky »

TheManInBoots

  • Epically wrote function to declare an int
Re: Dynamic Shadows in AGS - idea for module
« Reply #1 on: 03 Feb 2020, 16:05 »
Quote
The character's shadow could be automated with a module
It's not the topic of this discussion, but I've also thought about it and the main difficulty is that shadows are not additive. Only the brightly lit parts of the background would become darker. The parts that are already under a cast shadow from the scene would not get darker. It means you can't just draw the character's shadow over the scene, as is. You'd need to keep the overall shadows in a separate channel. It quickly becomes overly complicated.

When the character stands between the object and the wall/floor the shadows ARE additive.
And for the non-additive shadows, I do not believe that it would become overly complicated.
From how I understood Snarky the areas upon which the shadows fall (I'll call them "Shadow Areas") would be drawn, just like you draw the walkable areas or walk behinds.
In that case it's very easy to simply cut a hole into the shadow area where the object shadow is placed. (Illustrations and Explanations below)
Spoiler: ShowHide

I understood it that you'd draw the shadow areas because he said, there would be horizontal and vertical areas. You would have to define those areas.
And the best way is to draw them.



Because, what if there is a hole or a window in the wall?



You wouldn't want to the hole to be covered by the shadow either!

Also you would need to define a Baseline for the Shadow Area (just like for the walk-behinds). Because the distance between the wall and the character defines the distance between the character and the shadow. (And maybe also the intensity/transparency of the shadow)


Those are supposedly flying men with wings!

Let's say you have a shovel object in the room with it's object shadow.



Then you just need to leave a hole where the shadow object is when drawing the shadow area. (Similar as when you draw walk-behinds)
And you can fill up the "hole" with another Shadow Area ID, in order to restore or remove it, so that character's shadow is cast or not cast on the place, depending on weather the shovel is picked up or not.



It's exactly like walkable areas/walk-behinds. And those are not complicated. And it would create a perfect shadow, because the overlaying shadow is cut out:



The real complications maybe only start when you have angled walls and different distances for the light source, but the module wouldn't need to include that.

Unless implementing the option to draw the shadow area is too complex, I say a simple shadow module/plugin is worth it and totally possible. Even if you couldn't draw the exact outlines of the shadow area, I wonder if depending on how the shadow sprites are drawn- as dynamic sprites I assume- if you could simply create a walk behind that cuts the "shadow hole" (at least in simple cases where you can play around with baselines)...
« Last Edit: 03 Feb 2020, 17:51 by Snarky »

Snarky

  • Global Moderator
  • Global Moderator
  • Mittens Lord
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: Dynamic Shadows in AGS - idea for module
« Reply #2 on: 03 Feb 2020, 18:13 »
Thanks for the illustrations, ManInBoots! Yes, that's more or less what I had in mind.

I also considered how to do shadows on side-walls (vertical, but at an angle to the observer): I think it mainly requires defining a diagonal "baseline" (essentially, a line along the intersection of the wall and floor, pointing towards the vanishing point). And to get "correct" perspective (mainly for floor shadows, though it also applies to wall shadows), you'd also need to define the height of the horizon. Perspective would probably be limited to direction and foreshortening, not converging towards the vanishing point, since that would require perspective transformation of the sprite.

The biggest problem for this idea is that it requires a skew/shear operation on the sprites, which AGS does not offer. It would be possible to create one manually (by cropping a sprite to its individual rows/columns and drawing them displaced onto a new canvas), but it would probably be very slow.

Kweepa

  • Mutated Guano Deviser
    • Best Innovation Award Winner 2009, for his modules and plugins
    • Kweepa worked on one or more games that won an AGS Award!
    •  
    • Kweepa worked on one or more games that was nominated for an AGS Award!
Re: Dynamic Shadows in AGS - idea for module
« Reply #3 on: 03 Feb 2020, 19:45 »
I played around with simple cast shadows that just sliced and skewed the main character sprite about ten years ago. It wasn't horribly slow.
[EDIT] SSH also created a module https://www.adventuregamestudio.co.uk/forums/index.php?topic=28905 (which might give you a leg up)
« Last Edit: 03 Feb 2020, 19:47 by Kweepa »
Still waiting for Purity of the Surf II

Snarky

  • Global Moderator
  • Global Moderator
  • Mittens Lord
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: Dynamic Shadows in AGS - idea for module
« Reply #4 on: 04 Feb 2020, 00:10 »
And here: https://www.adventuregamestudio.co.uk/forums/index.php?topic=35404.0

So yeah, maybe not worth making another one.  :-D

Re: Dynamic Shadows in AGS - idea for module
« Reply #5 on: 04 Feb 2020, 09:48 »
I really would love to have a module which handle dynamic shadows, I hope you will do it one day. I remember that once Khris has done something like this but it was only for the character and it was never released as far as I know. Here's the video of the dynamic shadows, what you think?

Monsieur OUXX

  • Mittens Vassal
  • Cavefish
  • Mittens Half Initiate
    • I can help with proof reading
    • I can help with translating
    • I can help with voice acting
    • Monsieur OUXX worked on one or more games that won an AGS Award!
    •  
    • Monsieur OUXX worked on one or more games that was nominated for an AGS Award!
Re: Dynamic Shadows in AGS - idea for module
« Reply #6 on: 04 Feb 2020, 09:52 »
I would still like to know how your would implement the shadow of the player being cast o top of the shadow of an object. Let's say for simplicity's sake that both shadows should be 50% opaque. Well, then when on top of each other, the combined shadow should still be 50% opaque, not 100%.


 

Re: Dynamic Shadows in AGS - idea for module
« Reply #7 on: 04 Feb 2020, 10:16 »
I would still like to know how your would implement the shadow of the player being cast o top of the shadow of an object. Let's say for simplicity's sake that both shadows should be 50% opaque. Well, then when on top of each other, the combined shadow should still be 50% opaque, not 100%.

If we are using hardware accelerated driver, then we need full sprite transform support, and then just draw transformed translucent shadow sprites. (We still would have to calculate the shape of transformation of these sprites somehow though)


If we are talking about software method, one solution that comes to mind is to have an array, corresponding to pixels, where for each pixel (or group of pixels) there's a number, which defines shadow IDs. When shadow moves around the place, these IDs are adjusted as it covers and frees some area.

One could limit dynamic shadows to a number of bits in the N-bit number (32 for regular int, but you may have much more if you allow multiple ints per area), and then store the bitmask, where each bit means a shadow ID. When calculating actual opacity you check for each shadow's opacity level and combine them for particular pixel.

I keep saying "for pixel", but, of course, one could optimize this and store this shadow number per group of pixels, like 2x2, or 4x4 pixels.
« Last Edit: 04 Feb 2020, 10:20 by Crimson Wizard »

Monsieur OUXX

  • Mittens Vassal
  • Cavefish
  • Mittens Half Initiate
    • I can help with proof reading
    • I can help with translating
    • I can help with voice acting
    • Monsieur OUXX worked on one or more games that won an AGS Award!
    •  
    • Monsieur OUXX worked on one or more games that was nominated for an AGS Award!
Re: Dynamic Shadows in AGS - idea for module
« Reply #8 on: 04 Feb 2020, 10:38 »
If we are talking about software method...

Are you discussing the technical means of computing the shadow's pixel values? I'm not 100% sure I understood. But if that's what you're doing, then it's not my question. Computing transparency is just a technicality. What I was asking was : "how do you tell your shadows engine that 'this background pixel does represent a shadow, and the player's shadow should not make it darker, while that other background pixel does not represent a shadow, so the player's shadow must make it darker' ?".
 

Re: Dynamic Shadows in AGS - idea for module
« Reply #9 on: 04 Feb 2020, 11:50 »
What I was asking was : "how do you tell your shadows engine that 'this background pixel does represent a shadow, and the player's shadow should not make it darker, while that other background pixel does not represent a shadow, so the player's shadow must make it darker' ?".

this is what my suggestion was about.

And yes, this suggestion assumes that you do all the work yourself, as opposed to delegating it to hardware-accelerated gfx driver, for which it would be simplier, and fast enough, to just draw all shadows each frame.
« Last Edit: 04 Feb 2020, 11:53 by Crimson Wizard »

Snarky

  • Global Moderator
  • Global Moderator
  • Mittens Lord
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: Dynamic Shadows in AGS - idea for module
« Reply #10 on: 04 Feb 2020, 12:24 »
I would still like to know how your would implement the shadow of the player being cast o top of the shadow of an object. Let's say for simplicity's sake that both shadows should be 50% opaque. Well, then when on top of each other, the combined shadow should still be 50% opaque, not 100%.

Well first of all, drawing with transparency is multiplicative, not additive, so 50% on top of 50% is 75%, not 100%.

Second, as TheManInBoots explained, you'd define the regions where shadows should be drawn, ideally by drawing a mask (if it turns out regions are not suited to this, you might have to provide the shadow mask as a separate sprite). So if some part of the region is already in shadow and shouldn't have the dynamic shadow applied, you just omit it from the mask.

Snarky

  • Global Moderator
  • Global Moderator
  • Mittens Lord
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: Dynamic Shadows in AGS - idea for module
« Reply #11 on: 04 Feb 2020, 12:29 »
Oh, and if the question is combining multiple dynamic shadows, you simply draw them all in opaque black on an intermediate canvas, then draw that with alpha-transparency onto the room.

Monsieur OUXX

  • Mittens Vassal
  • Cavefish
  • Mittens Half Initiate
    • I can help with proof reading
    • I can help with translating
    • I can help with voice acting
    • Monsieur OUXX worked on one or more games that won an AGS Award!
    •  
    • Monsieur OUXX worked on one or more games that was nominated for an AGS Award!
Re: Dynamic Shadows in AGS - idea for module
« Reply #12 on: 04 Feb 2020, 12:46 »
Oh, and if the question is combining multiple dynamic shadows, you simply draw them all in opaque black on an intermediate canvas, then draw that with alpha-transparency onto the room.

So if some of them are already part of the background, you just leave them out of that mask you were talking about?
 

Re: Dynamic Shadows in AGS - idea for module
« Reply #13 on: 04 Feb 2020, 12:47 »
I guess, this is also a question of optimization: do you redraw all the shadows every time? That is much simplier, but also slower if you use software drawing.

My above reply was containing a suggestion about optimization. Guess, I forgot to explain better...

Snarky

  • Global Moderator
  • Global Moderator
  • Mittens Lord
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: Dynamic Shadows in AGS - idea for module
« Reply #14 on: 04 Feb 2020, 12:50 »
Oh, and if the question is combining multiple dynamic shadows, you simply draw them all in opaque black on an intermediate canvas, then draw that with alpha-transparency onto the room.

So if some of them are already part of the background, you just leave them out of that mask you were talking about?

Yes.

Monsieur OUXX

  • Mittens Vassal
  • Cavefish
  • Mittens Half Initiate
    • I can help with proof reading
    • I can help with translating
    • I can help with voice acting
    • Monsieur OUXX worked on one or more games that won an AGS Award!
    •  
    • Monsieur OUXX worked on one or more games that was nominated for an AGS Award!
Re: Dynamic Shadows in AGS - idea for module
« Reply #15 on: 04 Feb 2020, 13:27 »
I guess, this is also a question of optimization: do you redraw all the shadows every time? That is much simplier, but also slower if you use software drawing.

My above reply was containing a suggestion about optimization. Guess, I forgot to explain better...

I find that usually for low-res games, per-pixel computations are not that big if a deal. For bigger amounts of pixels I use tricks relying on the build-in functions (Tint, redraw the same sprite several times, slice the sprite into smaller sprites, etc.). But usually I bump into the lack of flexibility of the functions used to manipulate the sprite's alpha mask. I wish I could intersect sprites, or intersect a sprite with another alpha mask (not just entirely overwrite it), for example, to produce cutouts of sprites.

« Last Edit: 04 Feb 2020, 13:33 by Monsieur OUXX »
 

Re: Dynamic Shadows in AGS - idea for module
« Reply #16 on: 04 Feb 2020, 13:34 »
I wish I could intersect sprites, or intersect a sprite with another alpha mask, for example, to produce cutouts of sprites.

See DynamicSprite.CopyTransparencyMask:
https://github.com/adventuregamestudio/ags-manual/wiki/DynamicSprite#dynamicspritecopytransparencymask

If i remember correctly, that should cut the transparent holes in one sprite using another.

Monsieur OUXX

  • Mittens Vassal
  • Cavefish
  • Mittens Half Initiate
    • I can help with proof reading
    • I can help with translating
    • I can help with voice acting
    • Monsieur OUXX worked on one or more games that won an AGS Award!
    •  
    • Monsieur OUXX worked on one or more games that was nominated for an AGS Award!
Re: Dynamic Shadows in AGS - idea for module
« Reply #17 on: 04 Feb 2020, 13:37 »
I wish I could intersect sprites, or intersect a sprite with another alpha mask, for example, to produce cutouts of sprites.

See DynamicSprite.CopyTransparencyMask:
https://github.com/adventuregamestudio/ags-manual/wiki/DynamicSprite#dynamicspritecopytransparencymask

If i remember correctly, that should cut the transparent holes in one sprite using another.

I know, but I meant without entirely replacing the sprite's current mask.
To be honest I need to dive back into it but I remember it not quite working in a way that would make it useful. I don't want to talk more about it as I don't have more constructive feedback than that fron the top of my head.
 

TheManInBoots

  • Epically wrote function to declare an int
Re: Dynamic Shadows in AGS - idea for module
« Reply #18 on: 05 Feb 2020, 02:41 »
Great you moved the thread Snarky!
Thanks for the illustrations, ManInBoots! Yes, that's more or less what I had in mind.
Sure thing. When I read that you wanted to create a shadow module, I just immediately could imagine it how it would work!
Yesterday I kept thinking about this throughout the day and came up with ideas on how to manipulate the dynamic sprites to create the shadow shape.

I use a lot of illustrations, so open the panels to look at it. I hoped using the panels "show/hide" gives for a better overview?...

Spoiler: ShowHide


First I want to mention that I believe that it would be better to use a shadow character and draw on it's view sprite instead of the background. This would allow to draw shadows on other objects as well. You would assign the character you choose as the shadow character or it's ID to the module with a certain function for example. And the characters baseline would repeatedly be Playercharacter.baseline-1, so it would cover everything behind the player character, but nothing in front, and not the player character himself. Otherwise how can it throw shadows on any object that the character walks past?

I want to describe a method to transform the sprites in a way so you can determine exactly from which direction, or which angle the light falls unto the character.

And I mean, as well from the x-direction:



As from the y-direction:



EXPLANATION OF TERM "LINE"
Spoiler: ShowHide

A quick explanation for when I talk about shearing.
Here we have a simple box 11x11 pixels (strongly magnified):



And now I am moving the "Y-LINES" to the right (since every line has an y value)



Now I move the "X-LINES" of the original box down (every line has an x-value)



This just to show what I mean with the terms "x-line" and "y-line".


MANIPULATION ON THE X-AXIS
Spoiler: ShowHide

Now, back to the transformation:

How would you manipulate the shadow sprite into the right shape when changing only the x-direction of the light source? (As those three different shadow examples in this picture below)



First you would have to choose the x-angle from which the light comes. In the illustration you see the red x-axis.
I marked the angles 45 degrees and 135 degrees. But obviously you could choose any angle between 1 and 179 degrees.
I also marked the baseline of the "vertical wall shadow area" with a dotted line.



Now let's take the example of 135 degrees.



First you would calculate the intersection point of the baseline with line that leaves from the characters base point (characters x,y coordinate) with 135 degrees.
I marked the intersection point with a blue X:



Now the x-value of that intersection point is the x-value where you place the shadow sprite.



Now you cut off (yellow line) the lower part of the shadow sprite and shear it into place.



There you have it! The shadow is finished!



Now when you actually draw the Dynamic Sprite the best way, from how I understand it, would be to draw it from bottom to top.
So you start with the sheared part. The first y-line is drawn just like the character sprite on the characters x-postion.
The second y-line then is moved/sheared to the right in this example. How much to the right?
Well you would calculate the difference between the x-coordinate of the original character and the x-value of the intersection point. Then you divide that by the number of "y-lines" that are being sheared. That number equals the distance between the character's y-coordinate and the shadow area baseline.
Let's say hypothetically in this case the y-line will be sheared by 10 pixels. The the second then will be moved and re-drawn with 20 pixel offset. The third 30 pixels, and so on.
So the y-lines are being sheared until we reach the baseline.
So from now on the y-lines won't be sheared anymore.
Let's say the last shear has been moved by 200 pixels. That means from now on every y-line of the sprite above the baseline will be drawn 200 pixels to the right. And thus the upper part will look normally drawn, just further to the right, as it should.


MANIPULATION ON THE Y-AXIS
Spoiler: ShowHide

Now how would you manipulate the sprite for the y-axis angle?

Let's say you have the angle of 135 degrees on the x-axis, and now also you want to transform the shadow with 135 degrees on the y-axis.



(Note that if x-angle<90degrees, the the y-angle would automatically switch to the left side of the y-axis, in case you understand what I mean by that. So again we don't need 360 degrees for the y-axis, but only the values 1-179)

So, y-angle set to 135 degrees, now we need to calculate the intersection point of the y-angle line with the x-value of the formerly mentioned intersection point with the baseline. I marked this second intersection point with an orange X.



As before, now we place the shadow sprite on the X-intersection value with the baseline.


But this time, before shearing the lower part as we did for the x-axis, we will SCALE the shadow sprite first! But only for the y-value! We basically "squish" or negatively stretch it.
And we stretch it until it has exactly the height of the y-angle intersection point:



(I assume one could use the same code as the engine uses for character scaling, but do it only for the "y-lines" and not the "x-lines")

Once this is done, we shear the part below the baseline like we did for the x-axis.



And voila! The shadow is finished. Now the light is coming in from the high left:




So for the sprite drawing:
You would have to stretch (in this case negatively stretch) the character to the right size first. Then you would start with the shearing and continue like you did when transforming on the x-axis.
Let's say the negative stretching is achieved by skipping certain y-lines. Then it would be advisable to make the process of stretching (skipping y-lines) and shearing at the SAME time, in order to safe drawing time and possibly avoid using an additional canvas.

There you have it. Those are my ideas on how to angle the shadow on the x- and y-axis!




I also have an idea for the angled walls! How to manipulate the sprites to create such a shadow:



But it's getting late here. I'll explain it more thoroughly another time.


SHEARING
Spoiler: ShowHide

Concerning shearing I want to mention a detail. Moving the y-lines when shearing to the left for example (as happened in the examples above) works fine.
HOWEVER, when you shear too much, it can create gaps between the pixels. Take for example a simple one pixel thick line (magnified in the illustration):



Now when you shear it strongly, this would happen (right side of the image cut out):



So the module would have to recognize gaps between the y-lines and automatically fill them up. Fortunately it would have to fill them up only with "black" pixels since the shadow is one-colored.
And how many pixels should it add to the right of the previous y-line?
Basically when drawing the new sheared y-line on top of the previous y-line, the module should:
add the 1/2 the length of the first y-line and 1/2 the length of the second y-line.
If that addition is shorter than the shearing distance, than it needs to draw additional pixels.
(the amount of pixels would be the difference: shear distance MINUS 1/2 * (y-line 1 PLUS y-line 2). Not sure if this was clearly enough explained.
(side note: for this to work, the module would have to recognize which pixels are "drawn" and which ones are transparent, in order to properly define the length of the y-line)

In the example:
The first y-line is one sprite one long.
The second as well.
The shearing distance is 2 sprites.
So the module needs to fill out:
2-(0,5 PLUS 0,5)=1
Since every y-line has the same length, the module needs to draw ONE pixel to the right of each y-line:






You are guys more advanced than I am with the programming, but maybe this can give you some ideas and some inspiration.

Anyways, I think it's an exciting project!

2ND EDIT: For your idea about the horizon Snarky, the vanity point etc. actually I think it's possible. But you wouldn't use a vanity point or horizon, but simply scale the shadow depending on it's y-value. That's the efficient way to do it I suppose.
« Last Edit: 05 Feb 2020, 19:49 by TheManInBoots »

Snarky

  • Global Moderator
  • Global Moderator
  • Mittens Lord
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: Dynamic Shadows in AGS - idea for module
« Reply #19 on: 05 Feb 2020, 17:20 »
I love your enthusiasm, Man!
I think your constructions are a little bit off, though. They look more or less OK in these particular scenarios (though I'm not convinced you're being 100% consistent), but if you try some other setups I believe you'll find that the rules you're using are wrong.

Most obviously, the vertical scaling of the wall shadow is not correct. Assuming a distant lightsource and a vertical character, the shadow cast on a vertical surface will be exactly as tall as the character. (Also, consider how it works if the shadow is cast sideways.)

However, I don't have time right now to work through all the details or attempt any code, so I'll leave it.

But usually I bump into the lack of flexibility of the functions used to manipulate the sprite's alpha mask. I wish I could intersect sprites, or intersect a sprite with another alpha mask (not just entirely overwrite it), for example, to produce cutouts of sprites.

I agree that the limitations are annoying, but what you describe here is definitely possible.

Cassiebsg

  • Cavefish
  • Fleeing the Cylon tyrrany...
    • Cassiebsg worked on one or more games that won an AGS Award!
    •  
    • Cassiebsg worked on one or more games that was nominated for an AGS Award!
Re: Dynamic Shadows in AGS - idea for module
« Reply #20 on: 05 Feb 2020, 18:28 »
People keep saying, not to focus on the limitations but look for the possibilities instead.  ;)
There are those who believe that life here began out there...

TheManInBoots

  • Epically wrote function to declare an int
Re: Dynamic Shadows in AGS - idea for module
« Reply #21 on: 05 Feb 2020, 19:31 »
Most obviously, the vertical scaling of the wall shadow is not correct. Assuming a distant lightsource and a vertical character, the shadow cast on a vertical surface will be exactly as tall as the character.
Yes, and they ARE in my illustrations.
So all of the vertical scaling is correct.
I think you didn't understand my illustrations.
Whenever you set the angle to 90 degrees (meaning the distant light source shines on the the vertical character in a linear way parallel to the ground) the shadow is as tall as the character.

(Also, consider how it works if the shadow is cast sideways.)

My model is close enough to reality.
It's a 2D assimilation.
In certain cases you might use the side view frame maybe.
But okay, if you want to have a perfectly realistic shadow then you should create a 3D model of the character sprite and calculate the shadow from a sideways angle and create a 3D model of the room to project the shadow on.
Sounds easy enough to do with AGS lol.

Well anyways, if you don't have time for it then there's no point for me to suggest ideas. It sounded like you were interested to do it that's why I shared it.
« Last Edit: 05 Feb 2020, 20:03 by TheManInBoots »

Snarky

  • Global Moderator
  • Global Moderator
  • Mittens Lord
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: Dynamic Shadows in AGS - idea for module
« Reply #22 on: 05 Feb 2020, 22:03 »
Most obviously, the vertical scaling of the wall shadow is not correct. Assuming a distant lightsource and a vertical character, the shadow cast on a vertical surface will be exactly as tall as the character.
Yes, and they ARE in my illustrations.
So all of the vertical scaling is correct.
I think you didn't understand my illustrations.

Whenever you set the angle to 90 degrees (meaning the distant light source shines on the the vertical character in a linear way parallel to the ground) the shadow is as tall as the character.

(The shadows in the scene are eyeballed, so they may not be quite accurate.)

This bit is wrong:

As before, now we place the shadow sprite on the X-intersection value with the baseline.


But this time, before shearing the lower part as we did for the x-axis, we will SCALE the shadow sprite first! But only for the y-value! We basically "squish" or negatively stretch it.
And we stretch it until it has exactly the height of the y-angle intersection point:



(I assume one could use the same code as the engine uses for character scaling, but do it only for the "y-lines" and not the "x-lines")

Once this is done, we shear the part below the baseline like we did for the x-axis.



And voila! The shadow is finished.

You're not supposed to "squeeze" the height of the shadow: the shadow of a vertical object on a vertical surface will not be distorted, regardless of the angle of the light (assuming the light-source is infinitely distant, and considering the object to be "flat"). It's just offset.

Imagine that the floor is glass, so the full shadow is cast upon the wall, as in this simple diagram:



Because the light is parallel (infinitely distant source) and the figure is parallel to the wall (both vertical), the shadow on the wall will be just as tall as the figure. No squeezing.

(Also, consider how it works if the shadow is cast sideways.)

My model is close enough to reality.
It's a 2D assimilation.

Perhaps it's close enough in some cases, but I think it's going to break pretty badly when, for example, the light comes from the side and shadows fall on a side wall (angled to the observer):



(Edit: Imagine the character walking from the left towards the wall on the right. In your model, the shadow on the wall will start off as an extremely squashed version of the sprite, then will gradually be stretched vertically as the character approaches.)

That's why I think something a bit more advanced (Edit: not even really more advanced, just more correct) is needed, though certainly not full 3D.
« Last Edit: 06 Feb 2020, 07:41 by Snarky »

eri0o

Re: Dynamic Shadows in AGS - idea for module
« Reply #23 on: 05 Feb 2020, 22:26 »
(I have an unreleased 3D math module if you need  to calculate stuff)

TheManInBoots

  • Epically wrote function to declare an int
Re: Dynamic Shadows in AGS - idea for module
« Reply #24 on: 06 Feb 2020, 13:17 »
Okay, I understand now what you're talking about Snarky. And you're right.
But it would be quite easy to adjust that in the method I proposed.

I'll explain it in geometrical terms, because I think it's easier to understand:

You simple move the entire shadow shape down to the intersection point:



And then you stretch only the lower part below the "shadow area" ("SA") baseline and shear it:



So that is easily solved and gives a perfect shadow shape for horizontal SA baselines.


Now for the angled walls, I tried it out:

With the method I initially proposed, you would get this result in your example:



If now you only stretch and shear the part below the SA baseline, and leave the upper part unstretched you get a similar result:



It is better and more realistic though, definitely.

However, I noticed another flaw in the method I proposed.
Since the wall is so angled, the shadow shape on the vertical wall should actually decrease it's width, since you look at it on it's angle.
Since that is not included, you can see that the legs are not fitting together on the vertical and horizontal SA:


So, there should be a stretching width wise (or on the y-coordinate, skipping x-lines) of the vertical shadow shape, depending on the angle of the wall. In the example, it would already look better:


But the legs are still not completely aligned. And that is because the gaps between the two legs, or the two arms and the body would slowly dissapear, the more the light comes in from the side. Because essentially the two legs, and the arms and the body, are more and more on one level now, from the light's perspective.
So you could create a similar effect of decreasing the gap by removing more gap pixels, the bigger the angle is. (the program could recognize a gap pixel when it runs through every x-value of the y-line. It reaches the first black pixel for one x-value. Then it reaches the transparent pixels. If after that for a higher x-value it reaches a black pixel again, then the transparent pixels before that and after the last black pixel count as "gap pixels".

Removing the gap pixels would make the vertical shadow look perfect in the example:



Side note on removing gap pixels:
Spoiler: ShowHide

It could also be possible to draw the turned character mask shape or import the mask shape unto the shadow shape, and add the turning axis.
It would not be all that complicated for the program to calculate the steps inbetween to make it look like the character is turning.

END OF SPOILER
___________________________________________________________________________________________________


Now you could also add an addition that when the wall's angle surpasses 45 degrees for example, that the module does not use the character's current view frame, but the view frame ID of the adjacent loop. This way you would have a perfect side shadow.

To illustrate:

You are using the side view as the shadow, and move it to the intersection point:



Now all you have to do is shear the part above the SA baseline (and not stretch it's height ;) ), and stretch it's width negatively, as I explained above.
And then all that is left to do is shear the lower part into place:



Looks good enough to me.

However what I noticed is that with such a strong wall angle you can't only shear the y-lines of the part below the SA baseline. The best result I got when shearing the y-lines only (and stretching) was:



Not exactly perfect, I know.
So you actually have to shear BOTH y-lines AND x-lines at the same time, and not stretch the lower part. Which makes it more complex to calculate the amount of shearing necessary. (Because shearing the y-lines completely changes the outcome of the shearing of the x-lines and vice versa). However it creates the perfect shadow shape.

That knowledge for double shearing might be useful for you, even if you'll use a different system.
Anyways, since you said you want to use a different system to create shadows, I'll leave it with that and leave you to it.
« Last Edit: 06 Feb 2020, 14:10 by TheManInBoots »